mmc: msm_sdcc: fix buffer overflow conditions
This function fixes few possible buffer overflow
conditions in find_most_appropriate_phase()
function.
Change-Id: Icc17469a3850aa8531a6ef176bacc83fa2c50159
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 69ec647..f03aeac 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -3201,14 +3201,15 @@
static int find_most_appropriate_phase(struct msmsdcc_host *host,
u8 *phase_table, u8 total_phases)
{
+ #define MAX_PHASES 16
int ret;
- u8 ranges[16][16] = { {0}, {0} };
- u8 phases_per_row[16] = {0};
+ u8 ranges[MAX_PHASES][MAX_PHASES] = { {0}, {0} };
+ u8 phases_per_row[MAX_PHASES] = {0};
int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0;
int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0;
bool phase_0_found = false, phase_15_found = false;
- if (total_phases > 16) {
+ if (!total_phases || (total_phases > MAX_PHASES)) {
pr_err("%s: %s: invalid argument: total_phases=%d\n",
mmc_hostname(host->mmc), __func__, total_phases);
return -EINVAL;
@@ -3228,6 +3229,9 @@
}
}
+ if (row_index >= MAX_PHASES)
+ return -EINVAL;
+
/* Check if phase-0 is present in first valid window? */
if (!ranges[0][0]) {
phase_0_found = true;
@@ -3235,7 +3239,7 @@
/* Check if cycle exist between 2 valid windows */
for (cnt = 1; cnt <= row_index; cnt++) {
if (phases_per_row[cnt]) {
- for (i = 0; i <= phases_per_row[cnt]; i++) {
+ for (i = 0; i < phases_per_row[cnt]; i++) {
if (ranges[cnt][i] == 15) {
phase_15_found = true;
phase_15_raw_index = cnt;
@@ -3253,12 +3257,23 @@
/* number of phases in raw where phase 15 is present */
u8 phases_15 = phases_per_row[phase_15_raw_index];
- cnt = 0;
- for (i = phases_15; i < (phases_15 + phases_0); i++) {
+ if (phases_0 + phases_15 >= MAX_PHASES)
+ /*
+ * If there are more than 1 phase windows then total
+ * number of phases in both the windows should not be
+ * more than or equal to MAX_PHASES.
+ */
+ return -EINVAL;
+
+ /* Merge 2 cyclic windows */
+ i = phases_15;
+ for (cnt = 0; cnt < phases_0; cnt++) {
ranges[phase_15_raw_index][i] =
ranges[phase_0_raw_index][cnt];
- cnt++;
+ if (++i >= MAX_PHASES)
+ break;
}
+
phases_per_row[phase_0_raw_index] = 0;
phases_per_row[phase_15_raw_index] = phases_15 + phases_0;
}
@@ -3270,9 +3285,18 @@
}
}
- i = ((curr_max * 3) / 4) - 1;
+ i = ((curr_max * 3) / 4);
+ if (i)
+ i--;
+
ret = (int)ranges[selected_row_index][i];
+ if (ret >= MAX_PHASES) {
+ ret = -EINVAL;
+ pr_err("%s: %s: invalid phase selected=%d\n",
+ mmc_hostname(host->mmc), __func__, ret);
+ }
+
return ret;
}