msm: ipa: Fix to slab out of bounds issue

Add changes to verify passed value with in the allocated
max array size range or not before accessing structure.

Change-Id: If70493e937f6f0bc29bbfe08bf43738bdb4e9cf4
Acked-by: Ashok Vuyyuru <avuyyuru@qti.qualcomm.com>
Signed-off-by: Mohammed Javid <mjavid@codeaurora.org>
This commit is contained in:
Mohammed Javid 2018-04-10 15:33:48 +05:30
parent d803000f57
commit 1e03864e8a
3 changed files with 115 additions and 19 deletions

View file

@ -432,6 +432,8 @@ static ssize_t ipa_read_hdr(struct file *file, char __user *ubuf, size_t count,
list_for_each_entry(entry, &ipa_ctx->hdr_tbl.head_hdr_entry_list,
link) {
if (entry->cookie != IPA_HDR_COOKIE)
continue;
nbytes = scnprintf(
dbg_buff,
IPA_MAX_MSG_LEN,
@ -606,6 +608,14 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
if (attrib->protocol_eq_present)
pr_err("protocol:%d ", attrib->protocol_eq);
if (attrib->num_ihl_offset_range_16 >
IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS) {
IPAERR_RL("num_ihl_offset_range_16 Max %d passed value %d\n",
IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS,
attrib->num_ihl_offset_range_16);
return -EPERM;
}
for (i = 0; i < attrib->num_ihl_offset_range_16; i++) {
pr_err(
"(ihl_ofst_range16: ofst:%u lo:%u hi:%u) ",
@ -614,6 +624,12 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
attrib->ihl_offset_range_16[i].range_high);
}
if (attrib->num_offset_meq_32 > IPA_IPFLTR_NUM_MEQ_32_EQNS) {
IPAERR_RL("num_offset_meq_32 Max %d passed value %d\n",
IPA_IPFLTR_NUM_MEQ_32_EQNS, attrib->num_offset_meq_32);
return -EPERM;
}
for (i = 0; i < attrib->num_offset_meq_32; i++) {
pr_err(
"(ofst_meq32: ofst:%u mask:0x%x val:0x%x) ",
@ -635,6 +651,12 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
attrib->ihl_offset_eq_16.value);
}
if (attrib->num_ihl_offset_meq_32 > IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS) {
IPAERR_RL("num_ihl_offset_meq_32 Max %d passed value %d\n",
IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS, attrib->num_ihl_offset_meq_32);
return -EPERM;
}
for (i = 0; i < attrib->num_ihl_offset_meq_32; i++) {
pr_err(
"(ihl_ofst_meq32: ofts:%d mask:0x%x val:0x%x) ",
@ -643,6 +665,12 @@ static int ipa_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
attrib->ihl_offset_meq_32[i].value);
}
if (attrib->num_offset_meq_128 > IPA_IPFLTR_NUM_MEQ_128_EQNS) {
IPAERR_RL("num_offset_meq_128 Max %d passed value %d\n",
IPA_IPFLTR_NUM_MEQ_128_EQNS, attrib->num_offset_meq_128);
return -EPERM;
}
for (i = 0; i < attrib->num_offset_meq_128; i++) {
for (j = 0; j < 16; j++) {
addr[j] = attrib->offset_meq_128[i].value[j];
@ -812,11 +840,14 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count,
u32 rt_tbl_idx;
u32 bitmap;
bool eq;
int res = 0;
tbl = &ipa_ctx->glob_flt_tbl[ip];
mutex_lock(&ipa_ctx->lock);
i = 0;
list_for_each_entry(entry, &tbl->head_flt_rule_list, link) {
if (entry->cookie != IPA_FLT_COOKIE)
continue;
if (entry->rule.eq_attrib_type) {
rt_tbl_idx = entry->rule.rt_tbl_idx;
bitmap = entry->rule.eq_attrib.rule_eq_bitmap;
@ -835,10 +866,14 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count,
i, entry->rule.action, rt_tbl_idx);
pr_err("attrib_mask:%08x retain_hdr:%d eq:%d ",
bitmap, entry->rule.retain_hdr, eq);
if (eq)
ipa_attrib_dump_eq(
if (eq) {
res = ipa_attrib_dump_eq(
&entry->rule.eq_attrib);
else
if (res) {
IPAERR_RL("failed read attrib eq\n");
goto bail;
}
} else
ipa_attrib_dump(
&entry->rule.attrib, ip);
i++;
@ -848,6 +883,8 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count,
tbl = &ipa_ctx->flt_tbl[j][ip];
i = 0;
list_for_each_entry(entry, &tbl->head_flt_rule_list, link) {
if (entry->cookie != IPA_FLT_COOKIE)
continue;
if (entry->rule.eq_attrib_type) {
rt_tbl_idx = entry->rule.rt_tbl_idx;
bitmap = entry->rule.eq_attrib.rule_eq_bitmap;
@ -867,18 +904,23 @@ static ssize_t ipa_read_flt(struct file *file, char __user *ubuf, size_t count,
pr_err("attrib_mask:%08x retain_hdr:%d ",
bitmap, entry->rule.retain_hdr);
pr_err("eq:%d ", eq);
if (eq)
ipa_attrib_dump_eq(
&entry->rule.eq_attrib);
else
if (eq) {
res = ipa_attrib_dump_eq(
&entry->rule.eq_attrib);
if (res) {
IPAERR_RL("failed read attrib eq\n");
goto bail;
}
} else
ipa_attrib_dump(
&entry->rule.attrib, ip);
i++;
}
}
bail:
mutex_unlock(&ipa_ctx->lock);
return 0;
return res;
}
static ssize_t ipa_read_stats(struct file *file, char __user *ubuf,

View file

@ -357,6 +357,8 @@ static ssize_t ipa3_read_hdr(struct file *file, char __user *ubuf, size_t count,
list_for_each_entry(entry, &ipa3_ctx->hdr_tbl.head_hdr_entry_list,
link) {
if (entry->cookie != IPA_HDR_COOKIE)
continue;
nbytes = scnprintf(
dbg_buff,
IPA_MAX_MSG_LEN,
@ -540,6 +542,12 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
if (attrib->tc_eq_present)
pr_err("tc:%d ", attrib->tc_eq);
if (attrib->num_offset_meq_128 > IPA_IPFLTR_NUM_MEQ_128_EQNS) {
IPAERR_RL("num_offset_meq_128 Max %d passed value %d\n",
IPA_IPFLTR_NUM_MEQ_128_EQNS, attrib->num_offset_meq_128);
return -EPERM;
}
for (i = 0; i < attrib->num_offset_meq_128; i++) {
for (j = 0; j < 16; j++) {
addr[j] = attrib->offset_meq_128[i].value[j];
@ -551,6 +559,12 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
mask, addr);
}
if (attrib->num_offset_meq_32 > IPA_IPFLTR_NUM_MEQ_32_EQNS) {
IPAERR_RL("num_offset_meq_32 Max %d passed value %d\n",
IPA_IPFLTR_NUM_MEQ_32_EQNS, attrib->num_offset_meq_32);
return -EPERM;
}
for (i = 0; i < attrib->num_offset_meq_32; i++)
pr_err(
"(ofst_meq32: ofst:%u mask:0x%x val:0x%x) ",
@ -558,6 +572,12 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
attrib->offset_meq_32[i].mask,
attrib->offset_meq_32[i].value);
if (attrib->num_ihl_offset_meq_32 > IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS) {
IPAERR_RL("num_ihl_offset_meq_32 Max %d passed value %d\n",
IPA_IPFLTR_NUM_IHL_MEQ_32_EQNS, attrib->num_ihl_offset_meq_32);
return -EPERM;
}
for (i = 0; i < attrib->num_ihl_offset_meq_32; i++)
pr_err(
"(ihl_ofst_meq32: ofts:%d mask:0x%x val:0x%x) ",
@ -572,6 +592,14 @@ static int ipa3_attrib_dump_eq(struct ipa_ipfltri_rule_eq *attrib)
attrib->metadata_meq32.mask,
attrib->metadata_meq32.value);
if (attrib->num_ihl_offset_range_16 >
IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS) {
IPAERR_RL("num_ihl_offset_range_16 Max %d passed value %d\n",
IPA_IPFLTR_NUM_IHL_RANGE_16_EQNS,
attrib->num_ihl_offset_range_16);
return -EPERM;
}
for (i = 0; i < attrib->num_ihl_offset_range_16; i++)
pr_err(
"(ihl_ofst_range16: ofst:%u lo:%u hi:%u) ",
@ -764,7 +792,11 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf,
pr_err("rule_id:%u prio:%u retain_hdr:%u ",
rules[rl].id, rules[rl].priority,
rules[rl].retain_hdr);
ipa3_attrib_dump_eq(&rules[rl].eq_attrib);
res = ipa3_attrib_dump_eq(&rules[rl].eq_attrib);
if (res) {
IPAERR_RL("failed read attrib eq\n");
goto bail;
}
}
pr_err("=== Routing Table %d = Non-Hashable Rules ===\n", tbl);
@ -795,7 +827,11 @@ static ssize_t ipa3_read_rt_hw(struct file *file, char __user *ubuf,
pr_err("rule_id:%u prio:%u retain_hdr:%u\n",
rules[rl].id, rules[rl].priority,
rules[rl].retain_hdr);
ipa3_attrib_dump_eq(&rules[rl].eq_attrib);
res = ipa3_attrib_dump_eq(&rules[rl].eq_attrib);
if (res) {
IPAERR_RL("failed read attrib eq\n");
goto bail;
}
}
pr_err("\n");
}
@ -869,6 +905,7 @@ static ssize_t ipa3_read_flt(struct file *file, char __user *ubuf, size_t count,
u32 rt_tbl_idx;
u32 bitmap;
bool eq;
int res = 0;
mutex_lock(&ipa3_ctx->lock);
@ -878,6 +915,8 @@ static ssize_t ipa3_read_flt(struct file *file, char __user *ubuf, size_t count,
tbl = &ipa3_ctx->flt_tbl[j][ip];
i = 0;
list_for_each_entry(entry, &tbl->head_flt_rule_list, link) {
if (entry->cookie != IPA_FLT_COOKIE)
continue;
if (entry->rule.eq_attrib_type) {
rt_tbl_idx = entry->rule.rt_tbl_idx;
bitmap = entry->rule.eq_attrib.rule_eq_bitmap;
@ -899,18 +938,23 @@ static ssize_t ipa3_read_flt(struct file *file, char __user *ubuf, size_t count,
pr_err("hashable:%u rule_id:%u max_prio:%u prio:%u ",
entry->rule.hashable, entry->rule_id,
entry->rule.max_prio, entry->prio);
if (eq)
ipa3_attrib_dump_eq(
if (eq) {
res = ipa3_attrib_dump_eq(
&entry->rule.eq_attrib);
else
if (res) {
IPAERR_RL("failed read attrib eq\n");
goto bail;
}
} else
ipa3_attrib_dump(
&entry->rule.attrib, ip);
i++;
}
}
bail:
mutex_unlock(&ipa3_ctx->lock);
return 0;
return res;
}
static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
@ -961,7 +1005,11 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
bitmap, rules[rl].rule.retain_hdr);
pr_err("rule_id:%u prio:%u ",
rules[rl].id, rules[rl].priority);
ipa3_attrib_dump_eq(&rules[rl].rule.eq_attrib);
res = ipa3_attrib_dump_eq(&rules[rl].rule.eq_attrib);
if (res) {
IPAERR_RL("failed read attrib eq\n");
goto bail;
}
}
pr_err("=== Filtering Table ep:%d = Non-Hashable Rules ===\n",
@ -985,7 +1033,11 @@ static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf,
bitmap, rules[rl].rule.retain_hdr);
pr_err("rule_id:%u prio:%u ",
rules[rl].id, rules[rl].priority);
ipa3_attrib_dump_eq(&rules[rl].rule.eq_attrib);
res = ipa3_attrib_dump_eq(&rules[rl].rule.eq_attrib);
if (res) {
IPAERR_RL("failed read attrib eq\n");
goto bail;
}
}
pr_err("\n");
}

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -61,8 +61,10 @@ static int ipa3_generate_flt_hw_rule(enum ipa_ip_type ip,
gen_params.rule = (const struct ipa_flt_rule *)&entry->rule;
res = ipahal_flt_generate_hw_rule(&gen_params, &entry->hw_len, buf);
if (res)
IPAERR("failed to generate flt h/w rule\n");
if (res) {
IPAERR_RL("failed to generate flt h/w rule\n");
return res;
}
return 0;
}