Re: [PATCH v3 3/4] uaccess: Check no rescheduling function is called in unsafe region

From: Andy Lutomirski
Date: Wed Feb 13 2019 - 17:49:54 EST




> On Feb 13, 2019, at 2:21 PM, Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote:
>
> On Wed, Feb 13, 2019 at 10:51:24AM -0800, Andy Lutomirski wrote:
>>> On Feb 13, 2019, at 7:45 AM, Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote:
>
>>> Which I suppose means that GCC generates the PUSHF/POPF to preserve the
>>> EFLAGS, since we mark those explicitly clobbered.
>>>
>>
>> Not quite. A flags clobber doesnât save the control bits like AC
>> except on certain rather buggy llvm compilers. The change youâre
>> looking for is:
>>
>> http://git.kernel.org/tip/2c7577a7583747c9b71f26dced7f696b739da745
>
> Indeed, failed to find that.
>
>>> For a little bit of context; it turns out that user_access_begin() /
>>> user_access_end() sets EFLAGS.AC and scheduling in between there wrecks
>>> that because we're apparently not saving that anymore.
>>
>> But only explicit scheduling â preemption and sleepy page faults are
>> fine because the interrupt frame saves flags.
>
> No, like pointed out elsewhere in this thread, anything that does
> preempt_disable() is utterly broken with this.
>
> Because at that point the IRQ return path doesn't reschedule but
> preempt_enable() will, and that doesn't preserve EFLAGS again.
>
>>> Now, I'm tempted to add the PUSHF / POPF right back because of this, but
>>> first I suppose we need to figure out if that change was on purpose and
>>> why that went missing from the Changelog.
>>
>> Thatâs certainly the easy solution. Or we could teach the might_sleep
>> checks about this, but that could be a mess.
>
> That's not enough, we'd have to teach preempt_disable(), but worse,
> preempt_disable_notrace().
>
> Anything that lands in ftrace, which _will_ use
> preempt_disable_notrace(), will screw this thing up.

Ugh. Consider your patch acked. Do we need to backport this thing? The problem canât be too widespread or we would have heard of it before.