linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Al Viro <viro@zeniv.linux.org.uk>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Guenter Roeck <linux@roeck-us.net>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	linux-fsdevel <linux-fsdevel@vger.kernel.org>
Subject: Re: [PATCH] Convert filldir[64]() from __put_user() to unsafe_put_user()
Date: Tue, 8 Oct 2019 04:29:12 +0100	[thread overview]
Message-ID: <20191008032912.GQ26530@ZenIV.linux.org.uk> (raw)
In-Reply-To: <CAHk-=witTXMGsc9ZAK4hnKnd_O7u8b1eiou-6cfjt4aOcWvruQ@mail.gmail.com>

On Mon, Oct 07, 2019 at 11:26:35AM -0700, Linus Torvalds wrote:

> But on x86, if we move the STAC/CLAC out of the low-level copy
> routines and into the callers, we'll have a _lot_ of churn. I thought
> it would be mostly a "teach objtool" thing, but we have lots of
> different versions of it. Not just the 32-bit vs 64-bit, it's embedded
> in all the low-level asm implementations.
> 
> And we don't want the regular "copy_to/from_user()" to then have to
> add the STAC/CLAC at the call-site. So then we'd want to un-inline
> copy_to_user() entirely.

For x86?  Sure, why not...  Note, BTW, that for short constant-sized
copies we *do* STAC/CLAC at the call site - see those
		__uaccess_begin_nospec();
in raw_copy_{from,to}_user() in the switches...

> Which all sounds like a really good idea, don't get me wrong. I think
> we inline it way too aggressively now. But it'sa  _big_ job.
> 
> So we probably _should_
> 
>  - remove INLINE_COPY_TO/FROM_USER
> 
>  - remove all the "small constant size special cases".
> 
>  - make "raw_copy_to/from_user()" have the "unsafe" semantics and make
> the out-of-line copy in lib/usercopy.c be the only real interface
> 
>  - get rid of a _lot_ of oddities

Not that many, really.  All we need is a temporary cross-architecture
__uaccess_begin_nospec(), so that __copy_{to,from}_user() could have
that used, instead of having it done in (x86) raw_copy_..._...().

Other callers of raw_copy_...() would simply wrap it into user_access_begin()/
user_access_end() pairs; this kludge is needed only in __copy_from_user()
and __copy_to_user(), and only until we kill their callers outside of
arch/*.  Which we can do, in a cycle or two.  _ANY_ use of
that temporary kludge outside of those two functions will be grepped
for and LARTed into the ground.

> I hope you prove me wrong. But I'll look at a smaller change to just
> make x86 use the current special copy loop (as
> "unsafe_copy_to_user()") and have everybody else do the trivial
> wrapper.
> 
> Because we definitely should do that cleanup (it also fixes the whole
> "atomic copy in kernel space" issue that you pointed to that doesn't
> actually want STAC/CLAC at all), but it just looks fairly massive to
> me.

AFAICS, it splits nicely.

1) cross-architecture user_access_begin_dont_use(): on everything
except x86 it's empty, on x86 - __uaccess_begin_nospec().

2) stac/clac lifted into x86 raw_copy_..._user() out of
copy_user_generic_unrolled(), copy_user_generic_string() and
copy_user_enhanced_fast_string().  Similar lift out of
__copy_user_nocache().

3) lifting that thing as user_access_begin_dont_use() into
__copy_..._user...() and as user_access_begin() into other
generic callers, consuming access_ok() in the latter.
__copy_to_user_inatomic() can die at the same stage.

4) possibly uninlining on x86 (and yes, killing the special
size handling off).  We don't need to touch the inlining
decisions for any other architectures.

At that point raw_copy_to_user() is available for e.g.
readdir.c to play with.

And up to that point only x86 sees any kind of code changes,
so we don't have to worry about other architectures.

5) kill the __copy_...() users outside of arch/*, alone with
quite a few other weird shits in there.  A cycle or two,
with the final goal being to kill the damn things off.

6) arch/* users get arch-by-arch treatment - mostly
it's sigframe handling.  Won't affect the generic code
and would be independent for different architectures.
Can happen in parallel with (5), actually.

7) ... at that point user_access_begin_dont_user() gets
removed and thrown into the pile of mangled fingers of
those who'd ignored all warnings and used it somewhere
else.

I don't believe that (5) would be doable entirely in
this cycle, but quite a few bits might be.

On a somewhat related note, do you see any problems with

void *copy_mount_options(const void __user * data)
{
        unsigned offs, size;
        char *copy;

        if (!data)
                return NULL;

        copy = kmalloc(PAGE_SIZE, GFP_KERNEL);
        if (!copy)
                return ERR_PTR(-ENOMEM);

        offs = (unsigned long)untagged_addr(data) & (PAGE_SIZE - 1);

	if (copy_from_user(copy, data, PAGE_SIZE - offs)) {
                kfree(copy);
                return ERR_PTR(-EFAULT);
	}
	if (offs) {
		if (copy_from_user(copy, data + PAGE_SIZE - offs, offs))
			memset(copy + PAGE_SIZE - offs, 0, offs);
	}
        return copy;
}

on the theory that any fault halfway through a page means a race with
munmap/mprotect/etc. and we can just pretend we'd lost the race entirely.
And to hell with exact_copy_from_user(), byte-by-byte copying, etc.

  parent reply	other threads:[~2019-10-08  3:29 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-06 22:20 [PATCH] Convert filldir[64]() from __put_user() to unsafe_put_user() Guenter Roeck
2019-10-06 23:06 ` Linus Torvalds
2019-10-06 23:35   ` Linus Torvalds
2019-10-07  0:04     ` Guenter Roeck
2019-10-07  1:17       ` Linus Torvalds
2019-10-07  1:24         ` Al Viro
2019-10-07  2:06           ` Linus Torvalds
2019-10-07  2:50             ` Al Viro
2019-10-07  3:11               ` Linus Torvalds
2019-10-07 15:40                 ` David Laight
2019-10-07 18:11                   ` Linus Torvalds
2019-10-08  9:58                     ` David Laight
2019-10-07 17:34                 ` Al Viro
2019-10-07 18:13                   ` Linus Torvalds
2019-10-07 18:22                     ` Al Viro
2019-10-07 18:26                 ` Linus Torvalds
2019-10-07 18:36                   ` Tony Luck
2019-10-07 19:08                     ` Linus Torvalds
2019-10-07 19:49                       ` Tony Luck
2019-10-07 20:04                         ` Linus Torvalds
2019-10-08  3:29                   ` Al Viro [this message]
2019-10-08  4:09                     ` Linus Torvalds
2019-10-08  4:14                       ` Linus Torvalds
2019-10-08  5:02                         ` Al Viro
2019-10-08  4:24                       ` Linus Torvalds
2019-10-10 19:55                         ` Al Viro
2019-10-10 22:12                           ` Linus Torvalds
2019-10-11  0:11                             ` Al Viro
2019-10-11  0:31                               ` Linus Torvalds
2019-10-13 18:13                                 ` Al Viro
2019-10-13 18:43                                   ` Linus Torvalds
2019-10-13 19:10                                     ` Al Viro
2019-10-13 19:22                                       ` Linus Torvalds
2019-10-13 19:59                                         ` Al Viro
2019-10-13 20:20                                           ` Linus Torvalds
2019-10-15  3:46                                             ` Michael Ellerman
2019-10-15 18:08                                           ` Al Viro
2019-10-15 19:00                                             ` Linus Torvalds
2019-10-15 19:40                                               ` Al Viro
2019-10-15 20:18                                                 ` Al Viro
2019-10-16 12:12                                             ` [RFC] change of calling conventions for arch_futex_atomic_op_inuser() Al Viro
2019-10-16 12:24                                               ` Thomas Gleixner
2019-10-16 20:25                                         ` [PATCH] Convert filldir[64]() from __put_user() to unsafe_put_user() Al Viro
2019-10-18  0:27                                           ` [RFC] csum_and_copy_from_user() semantics Al Viro
2019-10-25 14:01                                       ` [PATCH] Convert filldir[64]() from __put_user() to unsafe_put_user() Thomas Gleixner
2019-10-08  4:57                       ` Al Viro
2019-10-08 13:14                         ` Greg KH
2019-10-08 15:29                           ` Al Viro
2019-10-08 15:38                             ` Greg KH
2019-10-08 17:06                               ` Al Viro
2019-10-08 19:58                   ` Al Viro
2019-10-08 20:16                     ` Al Viro
2019-10-08 20:34                     ` Al Viro
2019-10-07  2:30         ` Guenter Roeck
2019-10-07  3:12           ` Linus Torvalds
2019-10-07  0:23   ` Guenter Roeck
2019-10-07  4:04 ` Max Filippov
2019-10-07 12:16   ` Guenter Roeck
2019-10-07 19:21 ` Linus Torvalds
2019-10-07 20:29   ` Guenter Roeck
2019-10-07 23:27   ` Guenter Roeck
2019-10-08  6:28     ` Geert Uytterhoeven

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191008032912.GQ26530@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).