lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 22 Nov 2022 13:18:14 +0000
From:   Quentin Perret <qperret@...gle.com>
To:     wangbiao3@...omi.com
Cc:     mingo@...hat.com, peterz@...radead.org, juri.lelli@...hat.com,
        vincent.guittot@...aro.org, brauner@...nel.org, bsegall@...gle.com,
        linux-kernel@...r.kernel.org, wenjieli@....qualcomm.com,
        chenguanyou@...omi.com, dietmar.eggemann@....com,
        rostedt@...dmis.org, mgorman@...e.de, bristot@...hat.com,
        vschneid@...hat.com
Subject: Re: [PATCH 1/1] sched: fix user_mask double free

+CC the missing people from get_maintainers.pl

On Monday 21 Nov 2022 at 18:04:20 (+0800), wangbiao3@...omi.com wrote:
> 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;

Removing this puts the kmalloc_node() (and kfree()) below on the fast
path for everyone. It wouldn't be surprising if this causes regressions
for some people ...

Can we optimize that?

> +       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!******/#

Note that this legalese must be removed from your email before anybody
can apply this patch, please see
Documentation/process/submitting-patches.rst.

Thanks,
Quentin

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ