[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CA+55aFztF9D1yK5zbbG9PiQufQU+6BX-hc4toDS_MHx4ieeYqQ@mail.gmail.com>
Date: Mon, 6 Apr 2015 10:26:17 -0700
From: Linus Torvalds <torvalds@...ux-foundation.org>
To: Sasha Levin <sasha.levin@...cle.com>
Cc: LKML <linux-kernel@...r.kernel.org>,
Rusty Russell <rusty@...tcorp.com.au>,
Dave Jones <davej@...hat.com>, Michal Hocko <mhocko@...e.cz>,
Borislav Petkov <bp@...en8.de>,
"the arch/x86 maintainers" <x86@...nel.org>
Subject: Re: Hang on large copy_from_user with PREEMPT_NONE
On Sun, Apr 5, 2015 at 8:59 PM, Sasha Levin <sasha.levin@...cle.com> wrote:
>
> This is the result of getting copy_user_handle_tail to zero out a large block of
> kernel memory very inefficiently:
Ugh.
Normally we should be able to just do
if (zerorest)
memset(to, 0, len);
and be done with it.
The only reason we don't do that actually looks like a buglet in
'copy_in_user()', which can have a source fault but should *not*
necessarily try to clear the rest of the destination buffer. But it
uses the shared "copy_user_generic()" logic, so it doesn't even
realize that.
I call it a "buglet", because there's not necessarily anything
horribly wrong with clearing the tail, it's just completely wasted
work. And it makes the "oops, source is bad" case unnecessarily
horribly slow.
In fact, the whole "zerorest" thing is garbage, I think. The
copy_user_generic() code seems to always set it to just 'len', and
it's because it doesn't even know or care about the actual direction.
The *real* test should just be "is the destination a kernel space
buffer" (we have done the "access_ok()" things independently). And
that test we can do without any 'zerorest' parameter.
So the attached (untested) patch should
(a) remove the pointless 'zerorest' parameter
(b) fix the 'copy_in_user()' buglet
(c) make the kernel destination case be much more efficient with just
a simple 'memset()'
Hmm? Comments? Sasha, do you have the initial random number state to
recreate this easily?
Linus
View attachment "patch.diff" of type "text/plain" (1577 bytes)
Powered by blists - more mailing lists