Merge "drm/msm/sde: remove out of bound access for qos lut parsing"
This commit is contained in:
commit
c32cff4902
1 changed files with 64 additions and 25 deletions
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue