[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <b8970a530d420109ee9fe0b268e097fb839211b0.1669020858.git.wangbiao3@xiaomi.com>
Date: Mon, 21 Nov 2022 18:04:20 +0800
From: <wangbiao3@...omi.com>
To: <mingo@...hat.com>, <peterz@...radead.org>,
<juri.lelli@...hat.com>, <vincent.guittot@...aro.org>,
<brauner@...nel.org>, <bsegall@...gle.com>
CC: <linux-kernel@...r.kernel.org>, <wangbiao3@...omi.com>,
<wenjieli@....qualcomm.com>, <chenguanyou@...omi.com>
Subject: [PATCH 1/1] sched: fix user_mask double free
From: wangbiao3 <wangbiao3@...omi.com>
Clone/Fork a new task,call dup_task_struct->arch_dup_task_struct(tsk,orig)
which copy the data of parent/sibling task inclding p->user_cpus_ptr,so
the user_cpus_ptr of newtask is the same with orig task's.When
dup_task_struct call dup_user_cpus_ptr(tsk, orig, node),it return 0
dircetly if src->user_cpus_ptris free by other task,in this case ,
the newtask's address of user_cpus_ptr is not changed. Finally,
wakup newtask to execute, call task_cpu_possible_mask-->
do_set_cpus_allowed to set new task's user_cpus_ptr(user_mask) which
call kfree user_mask at the end. So cause a slub double free panic.
Use pi_lock to protect content of user_cpus_ptr in dup_user_cpus_ptr and
clear dst->user_cpus_ptr when found src->user_cpus_ptr is null
kernel BUG at mm/slub.c:363!
Call trace:
__slab_free+0x230/0x28c
kfree+0x220/0x2cc
do_set_cpus_allowed+0x74/0xa4
select_fallback_rq+0x12c/0x200
wake_up_new_task+0x26c/0x304
kernel_clone+0x2c0/0x470
__arm64_sys_clone+0x5c/0x8c
invoke_syscall+0x60/0x150
el0_svc_common.llvm.13030543509303927816+0x98/0x114
do_el0_svc_compat+0x20/0x30
el0_svc_compat+0x28/0x90
el0t_32_sync_handler+0x7c/0xbc
el0t_32_sync+0x1b8/0x1bc
Signed-off-by: wangbiao3 <wangbiao3@...omi.com>
---
kernel/sched/core.c | 31 ++++++++++++++++++++-----------
1 file changed, 20 insertions(+), 11 deletions(-)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index daff72f00385..b013d8b777b4 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2584,29 +2584,38 @@ void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
__do_set_cpus_allowed(p, new_mask, 0);
}
+static inline struct cpumask *clear_user_cpus_ptr(struct task_struct *p)
+{
+ struct cpumask *user_mask = NULL;
+
+ swap(p->user_cpus_ptr, user_mask);
+
+ return user_mask;
+}
+
int dup_user_cpus_ptr(struct task_struct *dst, struct task_struct *src,
int node)
{
- if (!src->user_cpus_ptr)
- return 0;
+ unsigned long flags;
+ struct cpumask *user_mask = NULL;
dst->user_cpus_ptr = kmalloc_node(cpumask_size(), GFP_KERNEL, node);
if (!dst->user_cpus_ptr)
return -ENOMEM;
+ /* Use pi_lock to protect content of user_cpus_ptr */
+ raw_spin_lock_irqsave(&src->pi_lock, flags);
+ if (!src->user_cpus_ptr) {
+ user_mask = clear_user_cpus_ptr(dst);
+ raw_spin_unlock_irqrestore(&src->pi_lock, flags);
+ kfree(user_mask);
+ return 0;
+ }
cpumask_copy(dst->user_cpus_ptr, src->user_cpus_ptr);
+ raw_spin_unlock_irqrestore(&src->pi_lock, flags);
return 0;
}
-static inline struct cpumask *clear_user_cpus_ptr(struct task_struct *p)
-{
- struct cpumask *user_mask = NULL;
-
- swap(p->user_cpus_ptr, user_mask);
-
- return user_mask;
-}
-
void release_user_cpus_ptr(struct task_struct *p)
{
kfree(clear_user_cpus_ptr(p));
--
2.38.1
#/******本邮件及其附件含有小米公司的保密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制、或散发)本邮件中的信息。如果您错收了本邮件,请您立即电话或邮件通知发件人并删除本邮件! This e-mail and its attachments contain confidential information from XIAOMI, which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction, or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this e-mail in error, please notify the sender by phone or email immediately and delete it!******/#
Powered by blists - more mailing lists