msm: ipa: add additional checks to prevent use-after free errors

Adding a function to check for dangling pointer using IPA IDR structure
to avoid use after free error.

Change-Id: I0bd3d733bf10403366abc643f89c3e5c5e6228e9
Acked-by: Suhas Mallesh <smallesh@qti.qualcomm.com>
Signed-off-by: Michael Adisumarta <madisuma@codeaurora.org>
This commit is contained in:
Michael Adisumarta 2019-09-24 16:36:17 -07:00
commit 8386504ae8
4 changed files with 29 additions and 5 deletions

View file

@ -64,7 +64,7 @@ static int ipa3_generate_flt_hw_rule(enum ipa_ip_type ip,
}
gen_params.ipt = ip;
if (entry->rt_tbl)
if (entry->rt_tbl && (!ipa3_check_idr_if_freed(entry->rt_tbl)))
gen_params.rt_tbl_idx = entry->rt_tbl->idx;
else
gen_params.rt_tbl_idx = entry->rule.rt_tbl_idx;
@ -1815,7 +1815,9 @@ int ipa3_reset_flt(enum ipa_ip_type ip, bool user_only)
entry->ipacm_installed) {
list_del(&entry->link);
entry->tbl->rule_cnt--;
if (entry->rt_tbl)
if (entry->rt_tbl &&
(!ipa3_check_idr_if_freed(
entry->rt_tbl)))
entry->rt_tbl->ref_cnt--;
/* if rule id was allocated from idr, remove */
rule_id = entry->rule_id;

View file

@ -2768,6 +2768,7 @@ int ipa3_alloc_counter_id(struct ipa_ioc_flt_rt_counter_alloc *counter);
void ipa3_counter_remove_hdl(int hdl);
void ipa3_counter_id_remove_all(void);
int ipa3_id_alloc(void *ptr);
bool ipa3_check_idr_if_freed(void *ptr);
void *ipa3_id_find(u32 id);
void ipa3_id_remove(u32 id);
int ipa3_enable_force_clear(u32 request_id, bool throttle_source,

View file

@ -97,6 +97,7 @@ static int ipa_generate_rt_hw_rule(enum ipa_ip_type ip,
proc_ctx = (entry->proc_ctx) ? : entry->hdr->proc_ctx;
if ((proc_ctx == NULL) ||
ipa3_check_idr_if_freed(proc_ctx) ||
(proc_ctx->cookie != IPA_PROC_HDR_COOKIE)) {
gen_params.hdr_type = IPAHAL_RT_RULE_HDR_NONE;
gen_params.hdr_ofst = 0;
@ -747,7 +748,8 @@ struct ipa3_rt_tbl *__ipa3_find_rt_tbl(enum ipa_ip_type ip, const char *name)
set = &ipa3_ctx->rt_tbl_set[ip];
list_for_each_entry(entry, &set->head_rt_tbl_list, link) {
if (!strcmp(name, entry->name))
if (!ipa3_check_idr_if_freed(entry) &&
!strcmp(name, entry->name))
return entry;
}
@ -1747,7 +1749,8 @@ int __ipa3_del_rt_rule(u32 rule_hdl)
if (entry->hdr)
__ipa3_release_hdr(entry->hdr->id);
else if (entry->proc_ctx)
else if (entry->proc_ctx &&
(!ipa3_check_idr_if_freed(entry->proc_ctx)))
__ipa3_release_hdr_proc_ctx(entry->proc_ctx->id);
list_del(&entry->link);
entry->tbl->rule_cnt--;
@ -1948,7 +1951,9 @@ int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only)
tbl->rule_cnt--;
if (rule->hdr)
__ipa3_release_hdr(rule->hdr->id);
else if (rule->proc_ctx)
else if (rule->proc_ctx &&
(!ipa3_check_idr_if_freed(
rule->proc_ctx)))
__ipa3_release_hdr_proc_ctx(
rule->proc_ctx->id);
rule->cookie = 0;

View file

@ -6249,6 +6249,22 @@ void *ipa3_id_find(u32 id)
return ptr;
}
bool ipa3_check_idr_if_freed(void *ptr)
{
int id;
void *iter_ptr;
spin_lock(&ipa3_ctx->idr_lock);
idr_for_each_entry(&ipa3_ctx->ipa_idr, iter_ptr, id) {
if ((uintptr_t)ptr == (uintptr_t)iter_ptr) {
spin_unlock(&ipa3_ctx->idr_lock);
return false;
}
}
spin_unlock(&ipa3_ctx->idr_lock);
return true;
}
void ipa3_id_remove(u32 id)
{
spin_lock(&ipa3_ctx->idr_lock);