OSDN Git Service

msm: ipa: add additional checks to prevent use-after free errors
authorMichael Adisumarta <madisuma@codeaurora.org>
Thu, 19 Sep 2019 23:25:02 +0000 (16:25 -0700)
committerGerrit - the friendly Code Review server <code-review@localhost>
Fri, 20 Sep 2019 22:46:28 +0000 (15:46 -0700)
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>
drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
drivers/platform/msm/ipa/ipa_v3/ipa_i.h
drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
drivers/platform/msm/ipa/ipa_v3/ipa_utils.c

index 9afdfdb..060b40a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -51,7 +51,7 @@ static int ipa3_generate_flt_hw_rule(enum ipa_ip_type ip,
        memset(&gen_params, 0, sizeof(gen_params));
 
        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;
@@ -1402,7 +1402,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;
index 4d6bc6f..7691aa9 100644 (file)
@@ -2125,5 +2125,6 @@ struct dentry *ipa_debugfs_get_root(void);
 bool ipa3_is_msm_device(void);
 struct device *ipa3_get_pdev(void);
 int ipa3_allocate_dma_task_for_gsi(void);
+bool ipa3_check_idr_if_freed(void *ptr);
 void ipa3_free_dma_task_for_gsi(void);
 #endif /* _IPA3_I_H_ */
index 659d38e..5413e62 100644 (file)
@@ -94,6 +94,7 @@ static int ipa_generate_rt_hw_rule(enum ipa_ip_type ip,
                struct ipa3_hdr_proc_ctx_entry *proc_ctx;
                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;
@@ -731,7 +732,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;
        }
 
@@ -1366,7 +1368,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--;
@@ -1567,7 +1570,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;
index f4bce29..a00fcae 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2019, 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
@@ -3865,3 +3865,19 @@ struct device *ipa3_get_pdev(void)
 
        return ipa3_ctx->pdev;
 }
+
+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;
+}