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, list_for_each_entry(entry, &ipa_ctx->hdr_tbl.head_hdr_entry_list,
link) { link) {
if (entry->cookie != IPA_HDR_COOKIE)
continue;
nbytes = scnprintf( nbytes = scnprintf(
dbg_buff, dbg_buff,
IPA_MAX_MSG_LEN, 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) if (attrib->protocol_eq_present)
pr_err("protocol:%d ", attrib->protocol_eq); 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++) { for (i = 0; i < attrib->num_ihl_offset_range_16; i++) {
pr_err( pr_err(
"(ihl_ofst_range16: ofst:%u lo:%u hi:%u) ", "(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); 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++) { for (i = 0; i < attrib->num_offset_meq_32; i++) {
pr_err( pr_err(
"(ofst_meq32: ofst:%u mask:0x%x val:0x%x) ", "(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); 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++) { for (i = 0; i < attrib->num_ihl_offset_meq_32; i++) {
pr_err( pr_err(
"(ihl_ofst_meq32: ofts:%d mask:0x%x val:0x%x) ", "(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); 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 (i = 0; i < attrib->num_offset_meq_128; i++) {
for (j = 0; j < 16; j++) { for (j = 0; j < 16; j++) {
addr[j] = attrib->offset_meq_128[i].value[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 rt_tbl_idx;
u32 bitmap; u32 bitmap;
bool eq; bool eq;
int res = 0;
tbl = &ipa_ctx->glob_flt_tbl[ip]; tbl = &ipa_ctx->glob_flt_tbl[ip];
mutex_lock(&ipa_ctx->lock); mutex_lock(&ipa_ctx->lock);
i = 0; i = 0;
list_for_each_entry(entry, &tbl->head_flt_rule_list, link) { list_for_each_entry(entry, &tbl->head_flt_rule_list, link) {
if (entry->cookie != IPA_FLT_COOKIE)
continue;
if (entry->rule.eq_attrib_type) { if (entry->rule.eq_attrib_type) {
rt_tbl_idx = entry->rule.rt_tbl_idx; rt_tbl_idx = entry->rule.rt_tbl_idx;
bitmap = entry->rule.eq_attrib.rule_eq_bitmap; 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); i, entry->rule.action, rt_tbl_idx);
pr_err("attrib_mask:%08x retain_hdr:%d eq:%d ", pr_err("attrib_mask:%08x retain_hdr:%d eq:%d ",
bitmap, entry->rule.retain_hdr, eq); bitmap, entry->rule.retain_hdr, eq);
if (eq) if (eq) {
ipa_attrib_dump_eq( res = ipa_attrib_dump_eq(
&entry->rule.eq_attrib); &entry->rule.eq_attrib);
else if (res) {
IPAERR_RL("failed read attrib eq\n");
goto bail;
}
} else
ipa_attrib_dump( ipa_attrib_dump(
&entry->rule.attrib, ip); &entry->rule.attrib, ip);
i++; 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]; tbl = &ipa_ctx->flt_tbl[j][ip];
i = 0; i = 0;
list_for_each_entry(entry, &tbl->head_flt_rule_list, link) { list_for_each_entry(entry, &tbl->head_flt_rule_list, link) {
if (entry->cookie != IPA_FLT_COOKIE)
continue;
if (entry->rule.eq_attrib_type) { if (entry->rule.eq_attrib_type) {
rt_tbl_idx = entry->rule.rt_tbl_idx; rt_tbl_idx = entry->rule.rt_tbl_idx;
bitmap = entry->rule.eq_attrib.rule_eq_bitmap; 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 ", pr_err("attrib_mask:%08x retain_hdr:%d ",
bitmap, entry->rule.retain_hdr); bitmap, entry->rule.retain_hdr);
pr_err("eq:%d ", eq); pr_err("eq:%d ", eq);
if (eq) if (eq) {
ipa_attrib_dump_eq( res = ipa_attrib_dump_eq(
&entry->rule.eq_attrib); &entry->rule.eq_attrib);
else if (res) {
IPAERR_RL("failed read attrib eq\n");
goto bail;
}
} else
ipa_attrib_dump( ipa_attrib_dump(
&entry->rule.attrib, ip); &entry->rule.attrib, ip);
i++; i++;
} }
} }
bail:
mutex_unlock(&ipa_ctx->lock); mutex_unlock(&ipa_ctx->lock);
return 0; return res;
} }
static ssize_t ipa_read_stats(struct file *file, char __user *ubuf, 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, list_for_each_entry(entry, &ipa3_ctx->hdr_tbl.head_hdr_entry_list,
link) { link) {
if (entry->cookie != IPA_HDR_COOKIE)
continue;
nbytes = scnprintf( nbytes = scnprintf(
dbg_buff, dbg_buff,
IPA_MAX_MSG_LEN, 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) if (attrib->tc_eq_present)
pr_err("tc:%d ", attrib->tc_eq); 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 (i = 0; i < attrib->num_offset_meq_128; i++) {
for (j = 0; j < 16; j++) { for (j = 0; j < 16; j++) {
addr[j] = attrib->offset_meq_128[i].value[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); 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++) for (i = 0; i < attrib->num_offset_meq_32; i++)
pr_err( pr_err(
"(ofst_meq32: ofst:%u mask:0x%x val:0x%x) ", "(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].mask,
attrib->offset_meq_32[i].value); 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++) for (i = 0; i < attrib->num_ihl_offset_meq_32; i++)
pr_err( pr_err(
"(ihl_ofst_meq32: ofts:%d mask:0x%x val:0x%x) ", "(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.mask,
attrib->metadata_meq32.value); 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++) for (i = 0; i < attrib->num_ihl_offset_range_16; i++)
pr_err( pr_err(
"(ihl_ofst_range16: ofst:%u lo:%u hi:%u) ", "(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 ", pr_err("rule_id:%u prio:%u retain_hdr:%u ",
rules[rl].id, rules[rl].priority, rules[rl].id, rules[rl].priority,
rules[rl].retain_hdr); 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); 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", pr_err("rule_id:%u prio:%u retain_hdr:%u\n",
rules[rl].id, rules[rl].priority, rules[rl].id, rules[rl].priority,
rules[rl].retain_hdr); 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"); 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 rt_tbl_idx;
u32 bitmap; u32 bitmap;
bool eq; bool eq;
int res = 0;
mutex_lock(&ipa3_ctx->lock); 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]; tbl = &ipa3_ctx->flt_tbl[j][ip];
i = 0; i = 0;
list_for_each_entry(entry, &tbl->head_flt_rule_list, link) { list_for_each_entry(entry, &tbl->head_flt_rule_list, link) {
if (entry->cookie != IPA_FLT_COOKIE)
continue;
if (entry->rule.eq_attrib_type) { if (entry->rule.eq_attrib_type) {
rt_tbl_idx = entry->rule.rt_tbl_idx; rt_tbl_idx = entry->rule.rt_tbl_idx;
bitmap = entry->rule.eq_attrib.rule_eq_bitmap; 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 ", pr_err("hashable:%u rule_id:%u max_prio:%u prio:%u ",
entry->rule.hashable, entry->rule_id, entry->rule.hashable, entry->rule_id,
entry->rule.max_prio, entry->prio); entry->rule.max_prio, entry->prio);
if (eq) if (eq) {
ipa3_attrib_dump_eq( res = ipa3_attrib_dump_eq(
&entry->rule.eq_attrib); &entry->rule.eq_attrib);
else if (res) {
IPAERR_RL("failed read attrib eq\n");
goto bail;
}
} else
ipa3_attrib_dump( ipa3_attrib_dump(
&entry->rule.attrib, ip); &entry->rule.attrib, ip);
i++; i++;
} }
} }
bail:
mutex_unlock(&ipa3_ctx->lock); mutex_unlock(&ipa3_ctx->lock);
return 0; return res;
} }
static ssize_t ipa3_read_flt_hw(struct file *file, char __user *ubuf, 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); bitmap, rules[rl].rule.retain_hdr);
pr_err("rule_id:%u prio:%u ", pr_err("rule_id:%u prio:%u ",
rules[rl].id, rules[rl].priority); 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", 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); bitmap, rules[rl].rule.retain_hdr);
pr_err("rule_id:%u prio:%u ", pr_err("rule_id:%u prio:%u ",
rules[rl].id, rules[rl].priority); 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"); 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 * 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 * 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; gen_params.rule = (const struct ipa_flt_rule *)&entry->rule;
res = ipahal_flt_generate_hw_rule(&gen_params, &entry->hw_len, buf); res = ipahal_flt_generate_hw_rule(&gen_params, &entry->hw_len, buf);
if (res) if (res) {
IPAERR("failed to generate flt h/w rule\n"); IPAERR_RL("failed to generate flt h/w rule\n");
return res;
}
return 0; return 0;
} }