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, 29 Nov 2022 10:32:49 -0500
From:   Waiman Long <longman@...hat.com>
To:     Will Deacon <will@...nel.org>
Cc:     Ingo Molnar <mingo@...hat.com>,
        Peter Zijlstra <peterz@...radead.org>,
        Juri Lelli <juri.lelli@...hat.com>,
        Vincent Guittot <vincent.guittot@...aro.org>,
        Dietmar Eggemann <dietmar.eggemann@....com>,
        Steven Rostedt <rostedt@...dmis.org>,
        Ben Segall <bsegall@...gle.com>, Mel Gorman <mgorman@...e.de>,
        Daniel Bristot de Oliveira <bristot@...hat.com>,
        Phil Auld <pauld@...hat.com>,
        Wenjie Li <wenjieli@....qualcomm.com>,
        David Wang 王标 <wangbiao3@...omi.com>,
        linux-kernel@...r.kernel.org
Subject: Re: [PATCH-tip v4] sched: Fix NULL user_cpus_ptr check in
 dup_user_cpus_ptr()

On 11/29/22 09:07, Will Deacon wrote:
> On Mon, Nov 28, 2022 at 10:11:52AM -0500, Waiman Long wrote:
>> On 11/28/22 07:00, Will Deacon wrote:
>>> On Sun, Nov 27, 2022 at 08:43:27PM -0500, Waiman Long wrote:
>>>> On 11/24/22 21:39, Waiman Long wrote:
>>>>> In general, a non-null user_cpus_ptr will remain set until the task dies.
>>>>> A possible exception to this is the fact that do_set_cpus_allowed()
>>>>> will clear a non-null user_cpus_ptr. To allow this possible racing
>>>>> condition, we need to check for NULL user_cpus_ptr under the pi_lock
>>>>> before duping the user mask.
>>>>>
>>>>> Fixes: 851a723e45d1 ("sched: Always clear user_cpus_ptr in do_set_cpus_allowed()")
>>>>> Signed-off-by: Waiman Long <longman@...hat.com>
>>>> This is actually a pre-existing use-after-free bug since commit 07ec77a1d4e8
>>>> ("sched: Allow task CPU affinity to be restricted on asymmetric systems").
>>>> So it needs to be fixed in the stable release as well. Will resend the patch
>>>> with an additional fixes tag and updated commit log.
>>> Please can you elaborate on the use-after-free here? Looking at
>>> 07ec77a1d4e8, the mask is only freed in free_task() when the usage refcount
>>> has dropped to zero and I can't see how that can race with fork().
>>>
>>> What am I missing?
>> I missed that at first. The current task cloning process copies the content
>> of the task structure over to the newly cloned/forked task. IOW, if
>> user_cpus_ptr had been set up previously, it will be copied over to the
>> cloned task. Now if user_cpus_ptr of the source task is cleared right after
>> that and before dup_user_cpus_ptr() is called. The obsolete user_cpus_ptr
>> value in the cloned task will remain and get used even if it has been freed.
>> That is what I call as use-after-free and double-free.
> If the parent task can be modified concurrently with dup_task_struct() then
> surely we'd have bigger issues because that's not going to be atomic? At the
> very least we'd have a data race, but it also feels like we could end up
> with inconsistent task state in the child. In fact, couldn't the normal
> 'cpus_mask' be corrupted by a concurrent set_cpus_allowed_common()?
>
> Or am I still failing to understand the race?
>
> Will

A major difference between cpus_mask and user_cpus_ptr is that for 
cpus_mask, the bitmap is embedded into task_struct whereas user_cpus_ptr 
is a pointer to an external bitmap. So there is no issue of 
use-after-free wrt cpus_mask. That is not the case where the memory of 
the user_cpus_ptr of the parent task is freed, but then a reference to 
that memory is still available in the child's task struct and may be used.

Note that the problematic concurrence is not between the copying of task 
struct and changing of the task struct. It is what will happen after the 
task struct copying has already been done with an extra reference 
present in the child's task struct.

Cheers,
Longman

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ