Merge "drm/msm/sde: remove out of bound access for qos lut parsing"

This commit is contained in:
Linux Build Service Account 2017-09-12 05:25:46 -07:00 committed by Gerrit - the friendly Code Review server
commit c32cff4902

View file

@ -27,11 +27,11 @@
/** /**
* Max hardware block in certain hardware. For ex: sspp pipes * Max hardware block in certain hardware. For ex: sspp pipes
* can have QSEED, pcc, igc, pa, csc, etc. This count is max * can have QSEED, pcc, igc, pa, csc, qos entries, etc. This count is
* 12 based on software design. It should be increased if any of the * 64 based on software design. It should be increased if any of the
* hardware block has more subblocks. * hardware block has more subblocks.
*/ */
#define MAX_SDE_HW_BLK 12 #define MAX_SDE_HW_BLK 64
/* each entry will have register address and bit offset in that register */ /* each entry will have register address and bit offset in that register */
#define MAX_BIT_OFFSET 2 #define MAX_BIT_OFFSET 2
@ -444,8 +444,16 @@ static uint32_t _sde_copy_formats(
static int _parse_dt_u32_handler(struct device_node *np, static int _parse_dt_u32_handler(struct device_node *np,
char *prop_name, u32 *offsets, int len, bool mandatory) char *prop_name, u32 *offsets, int len, bool mandatory)
{ {
int rc = of_property_read_u32_array(np, prop_name, offsets, len); int rc = -EINVAL;
if (len > MAX_SDE_HW_BLK) {
SDE_ERROR(
"prop: %s tries out of bound access for u32 array read len: %d\n",
prop_name, len);
return -E2BIG;
}
rc = of_property_read_u32_array(np, prop_name, offsets, len);
if (rc && mandatory) if (rc && mandatory)
SDE_ERROR("mandatory prop: %s u32 array read len:%d\n", SDE_ERROR("mandatory prop: %s u32 array read len:%d\n",
prop_name, len); prop_name, len);
@ -467,6 +475,14 @@ static int _parse_dt_bit_offset(struct device_node *np,
if (arr) { if (arr) {
len /= sizeof(u32); len /= sizeof(u32);
len &= ~0x1; len &= ~0x1;
if (len > (MAX_SDE_HW_BLK * MAX_BIT_OFFSET)) {
SDE_ERROR(
"prop: %s len: %d will lead to out of bound access\n",
prop_name, len / MAX_BIT_OFFSET);
return -E2BIG;
}
for (i = 0, j = 0; i < len; j++) { for (i = 0, j = 0; i < len; j++) {
PROP_BITVALUE_ACCESS(prop_value, prop_index, j, 0) = PROP_BITVALUE_ACCESS(prop_value, prop_index, j, 0) =
be32_to_cpu(arr[i]); be32_to_cpu(arr[i]);
@ -501,8 +517,8 @@ static int _validate_dt_entry(struct device_node *np,
sde_prop[0].prop_name); sde_prop[0].prop_name);
if ((*off_count > MAX_BLOCKS) || (*off_count < 0)) { if ((*off_count > MAX_BLOCKS) || (*off_count < 0)) {
if (sde_prop[0].is_mandatory) { if (sde_prop[0].is_mandatory) {
SDE_ERROR("invalid hw offset prop name:%s\"\ SDE_ERROR(
count: %d\n", "invalid hw offset prop name:%s count: %d\n",
sde_prop[0].prop_name, *off_count); sde_prop[0].prop_name, *off_count);
rc = -EINVAL; rc = -EINVAL;
} }
@ -545,8 +561,9 @@ static int _validate_dt_entry(struct device_node *np,
sde_prop[i].type); sde_prop[i].type);
break; break;
} }
SDE_DEBUG("prop id:%d prop name:%s prop type:%d \"\ SDE_DEBUG(
prop_count:%d\n", i, sde_prop[i].prop_name, "prop id:%d prop name:%s prop type:%d prop_count:%d\n",
i, sde_prop[i].prop_name,
sde_prop[i].type, prop_count[i]); sde_prop[i].type, prop_count[i]);
if (rc && sde_prop[i].is_mandatory && if (rc && sde_prop[i].is_mandatory &&
@ -564,14 +581,16 @@ static int _validate_dt_entry(struct device_node *np,
if (off_count && (prop_count[i] != *off_count) && if (off_count && (prop_count[i] != *off_count) &&
sde_prop[i].is_mandatory) { sde_prop[i].is_mandatory) {
SDE_ERROR("prop:%s count:%d is different compared to \"\ SDE_ERROR(
offset array:%d\n", sde_prop[i].prop_name, "prop:%s count:%d is different compared to offset array:%d\n",
sde_prop[i].prop_name,
prop_count[i], *off_count); prop_count[i], *off_count);
rc = -EINVAL; rc = -EINVAL;
goto end; goto end;
} else if (off_count && prop_count[i] != *off_count) { } else if (off_count && prop_count[i] != *off_count) {
SDE_DEBUG("prop:%s count:%d is different compared to \"\ SDE_DEBUG(
offset array:%d\n", sde_prop[i].prop_name, "prop:%s count:%d is different compared to offset array:%d\n",
sde_prop[i].prop_name,
prop_count[i], *off_count); prop_count[i], *off_count);
rc = 0; rc = 0;
prop_count[i] = 0; prop_count[i] = 0;
@ -607,8 +626,9 @@ static int _read_dt_entry(struct device_node *np,
case PROP_TYPE_U32: case PROP_TYPE_U32:
rc = of_property_read_u32(np, sde_prop[i].prop_name, rc = of_property_read_u32(np, sde_prop[i].prop_name,
&PROP_VALUE_ACCESS(prop_value, i, 0)); &PROP_VALUE_ACCESS(prop_value, i, 0));
SDE_DEBUG("prop id:%d prop name:%s prop type:%d \"\ SDE_DEBUG(
value:0x%x\n", i, sde_prop[i].prop_name, "prop id:%d prop name:%s prop type:%d value:0x%x\n",
i, sde_prop[i].prop_name,
sde_prop[i].type, sde_prop[i].type,
PROP_VALUE_ACCESS(prop_value, i, 0)); PROP_VALUE_ACCESS(prop_value, i, 0));
if (rc) if (rc)
@ -618,8 +638,9 @@ static int _read_dt_entry(struct device_node *np,
PROP_VALUE_ACCESS(prop_value, i, 0) = PROP_VALUE_ACCESS(prop_value, i, 0) =
of_property_read_bool(np, of_property_read_bool(np,
sde_prop[i].prop_name); sde_prop[i].prop_name);
SDE_DEBUG("prop id:%d prop name:%s prop type:%d \"\ SDE_DEBUG(
value:0x%x\n", i, sde_prop[i].prop_name, "prop id:%d prop name:%s prop type:%d value:0x%x\n",
i, sde_prop[i].prop_name,
sde_prop[i].type, sde_prop[i].type,
PROP_VALUE_ACCESS(prop_value, i, 0)); PROP_VALUE_ACCESS(prop_value, i, 0));
break; break;
@ -628,8 +649,9 @@ static int _read_dt_entry(struct device_node *np,
&PROP_VALUE_ACCESS(prop_value, i, 0), &PROP_VALUE_ACCESS(prop_value, i, 0),
prop_count[i], sde_prop[i].is_mandatory); prop_count[i], sde_prop[i].is_mandatory);
if (rc && sde_prop[i].is_mandatory) { if (rc && sde_prop[i].is_mandatory) {
SDE_ERROR("%s prop validation success but \"\ SDE_ERROR(
read failed\n", sde_prop[i].prop_name); "%s prop validation success but read failed\n",
sde_prop[i].prop_name);
prop_exists[i] = false; prop_exists[i] = false;
goto end; goto end;
} else { } else {
@ -651,19 +673,21 @@ static int _read_dt_entry(struct device_node *np,
prop_value, i, prop_count[i], prop_value, i, prop_count[i],
sde_prop[i].is_mandatory); sde_prop[i].is_mandatory);
if (rc && sde_prop[i].is_mandatory) { if (rc && sde_prop[i].is_mandatory) {
SDE_ERROR("%s prop validation success but \"\ SDE_ERROR(
read failed\n", sde_prop[i].prop_name); "%s prop validation success but read failed\n",
sde_prop[i].prop_name);
prop_exists[i] = false; prop_exists[i] = false;
goto end; goto end;
} else { } else {
if (rc) if (rc)
prop_exists[i] = false; prop_exists[i] = false;
SDE_DEBUG("prop id:%d prop name:%s prop \"\ SDE_DEBUG(
type:%d", i, sde_prop[i].prop_name, "prop id:%d prop name:%s prop type:%d",
i, sde_prop[i].prop_name,
sde_prop[i].type); sde_prop[i].type);
for (j = 0; j < prop_count[i]; j++) for (j = 0; j < prop_count[i]; j++)
SDE_DEBUG(" count[%d]: bit:0x%x \"\ SDE_DEBUG(
off:0x%x \n", j, "count[%d]: bit:0x%x off:0x%x\n", j,
PROP_BITVALUE_ACCESS(prop_value, PROP_BITVALUE_ACCESS(prop_value,
i, j, 0), i, j, 0),
PROP_BITVALUE_ACCESS(prop_value, PROP_BITVALUE_ACCESS(prop_value,
@ -984,6 +1008,13 @@ static int sde_sspp_parse_dt(struct device_node *np,
snprintf(sblk->src_blk.name, SDE_HW_BLK_NAME_LEN, "sspp_src_%u", snprintf(sblk->src_blk.name, SDE_HW_BLK_NAME_LEN, "sspp_src_%u",
sspp->id - SSPP_VIG0); sspp->id - SSPP_VIG0);
if (sspp->clk_ctrl >= SDE_CLK_CTRL_MAX) {
SDE_ERROR("%s: invalid clk ctrl: %d\n",
sblk->src_blk.name, sspp->clk_ctrl);
rc = -EINVAL;
goto end;
}
sblk->maxhdeciexp = MAX_HORZ_DECIMATION; sblk->maxhdeciexp = MAX_HORZ_DECIMATION;
sblk->maxvdeciexp = MAX_VERT_DECIMATION; sblk->maxvdeciexp = MAX_VERT_DECIMATION;
@ -1345,6 +1376,14 @@ static int sde_wb_parse_dt(struct device_node *np,
PROP_VALUE_ACCESS(prop_value, WB_ID, i); PROP_VALUE_ACCESS(prop_value, WB_ID, i);
wb->xin_id = PROP_VALUE_ACCESS(prop_value, WB_XIN_ID, i); wb->xin_id = PROP_VALUE_ACCESS(prop_value, WB_XIN_ID, i);
wb->vbif_idx = VBIF_NRT; wb->vbif_idx = VBIF_NRT;
if (wb->clk_ctrl >= SDE_CLK_CTRL_MAX) {
SDE_ERROR("%s: invalid clk ctrl: %d\n",
wb->name, wb->clk_ctrl);
rc = -EINVAL;
goto end;
}
wb->len = PROP_VALUE_ACCESS(prop_value, WB_LEN, 0); wb->len = PROP_VALUE_ACCESS(prop_value, WB_LEN, 0);
wb->format_list = wb2_formats; wb->format_list = wb2_formats;
if (!prop_exists[WB_LEN]) if (!prop_exists[WB_LEN])
@ -2067,7 +2106,7 @@ static int sde_perf_parse_dt(struct device_node *np,
goto end; goto end;
} }
prop_value = kzalloc(SDE_PROP_MAX * prop_value = kzalloc(PERF_PROP_MAX *
sizeof(struct sde_prop_value), GFP_KERNEL); sizeof(struct sde_prop_value), GFP_KERNEL);
if (!prop_value) { if (!prop_value) {
rc = -ENOMEM; rc = -ENOMEM;