All of lore.kernel.org
 help / color / mirror / Atom feed
From: Linus Torvalds <torvalds@linux-foundation.org>
To: David Laight <David.Laight@aculab.com>
Cc: Andy Lutomirski <luto@amacapital.net>,
	Ingo Molnar <mingo@kernel.org>, Al Viro <viro@zeniv.linux.org.uk>,
	Thomas Gleixner <tglx@linutronix.de>, X86 ML <x86@kernel.org>,
	LKML <linux-kernel@vger.kernel.org>,
	Borislav Petkov <bp@alien8.de>
Subject: Re: [RFC][PATCH 01/22] x86 user stack frame reads: switch to explicit __get_user()
Date: Sun, 29 Mar 2020 11:16:19 -0700	[thread overview]
Message-ID: <CAHk-=wjEf+0sBkPFKWpYZK_ygS9=ig3KTZkDe5jkDj+v8i7B+w@mail.gmail.com> (raw)
In-Reply-To: <9352bc55302d4589aaf2461c7b85fb6b@AcuMS.aculab.com>

On Sun, Mar 29, 2020 at 11:03 AM David Laight <David.Laight@aculab.com> wrote:
>
> > That's how get_user() already works.
> >
> > It is a polymorphic function (done using macros, sizeof() and ugly
> > compiler tricks) that generates a call, yes. But it's not a normal C
> > call. On x86-64, it returns the error code in %rax, and the value in
> > %rdx
>
> I must be mis-remembering the object code from last time
> I looked at it.

On an object code level, the end result actually almost looks like a
normal call, until you start looking at the exact register passing
details.

On a source level, it's anything but.

This is "get_user()" on x86:

  #define get_user(x, ptr)                                              \
  ({                                                                    \
        int __ret_gu;                                                   \
        register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX);            \
        __chk_user_ptr(ptr);                                            \
        might_fault();                                                  \
        asm volatile("call __get_user_%P4"                              \
                     : "=a" (__ret_gu), "=r" (__val_gu),                \
                        ASM_CALL_CONSTRAINT                             \
                     : "0" (ptr), "i" (sizeof(*(ptr))));                \
        (x) = (__force __typeof__(*(ptr))) __val_gu;                    \
        __builtin_expect(__ret_gu, 0);                                  \
  })

and all it actually *generates* is that single "call" instruction, so
the only code you see from the above mess in the object file (assuming
you don't have debugging enabled that expands "might_fault()" into a
lot of checking code) is something like this:

        call __get_user_4

with the input address being in %rax (which is also the returning
error code), and the value of 'x' being in %rdx.

The above macro looks a bit messy, but that's actually hiding some of
the real complexity (that "__inttype()" thing is a mess of compiler
tricks in itself, as is the magical ASM_CALL_CONSTRAINT thing, along
with the magic that goes into a 64-bit return value on x86-32 which is
implicit in the magical register asm() definition).

The uaccess code is a lot of complex macros and inline functions to
make it all work well.

Al's uaccess cleanups (which should be in the next merge window) help
a _lot_. Not with the get_user() above (that is already about as
simple as it can get), but with a lot of the other crazy special cases
that we had grown over the years.

My current "unsafe_get_user() using clang and 'asm goto' with outpus"
patch is on top of Al's patches exactly because it was cleaner to do
with all of his cleanups.

But that magical asm-goto-with-outputs patch probably won't land
upstream for a couple of years.

I had the unsafe_put_user() patches to use 'asm goto' in a local
branch for almost three years before I made them official. See commit
a959dc88f9c8 ("Use __put_user_goto in __put_user_size() and
unsafe_put_user()") and notice how it has an author date of May, 2016,
but was only committed January 2019.

I basically waited until "asm goto" was something we could rely on
(and used for other reasons).

I suspect something very similar will happen with unsafe_get_user(). I
have a patch if people want to play with it, but right now it's a
"this relies on an unreleased version of clang to even work".

                      Linus

  reply	other threads:[~2020-03-29 18:16 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-23 18:36 [RFC][PATCHSET] x86 uaccess cleanups Al Viro
2020-03-23 18:37 ` [RFC][PATCH 01/22] x86 user stack frame reads: switch to explicit __get_user() Al Viro
2020-03-23 18:37   ` [RFC][PATCH 02/22] x86 kvm page table walks: " Al Viro
2020-03-23 18:38   ` [RFC][PATCH 03/22] x86: switch sigframe sigset handling to explict __get_user()/__put_user() Al Viro
2020-03-23 18:38   ` [RFC][PATCH 04/22] x86: get rid of small constant size cases in raw_copy_{to,from}_user() Al Viro
2020-03-23 18:38   ` [RFC][PATCH 05/22] vm86: get rid of get_user_ex() use Al Viro
2020-03-23 18:38   ` [RFC][PATCH 06/22] x86: get rid of get_user_ex() in ia32_restore_sigcontext() Al Viro
2020-03-23 18:38   ` [RFC][PATCH 07/22] x86: get rid of get_user_ex() in restore_sigcontext() Al Viro
2020-03-23 18:38   ` [RFC][PATCH 08/22] x86: kill get_user_{try,catch,ex} Al Viro
2020-03-23 18:38   ` [RFC][PATCH 09/22] x86: switch save_v86_state() to unsafe_put_user() Al Viro
2020-03-23 18:38   ` [RFC][PATCH 10/22] x86: switch setup_sigcontext() " Al Viro
2020-03-23 18:38   ` [RFC][PATCH 11/22] x86: switch ia32_setup_sigcontext() " Al Viro
2020-03-23 18:38   ` [RFC][PATCH 12/22] x86: get rid of put_user_try in {ia32,x32}_setup_rt_frame() Al Viro
2020-03-23 18:38   ` [RFC][PATCH 13/22] x86: ia32_setup_sigcontext(): lift user_access_{begin,end}() into the callers Al Viro
2020-03-23 18:53     ` Linus Torvalds
2020-03-23 21:42       ` Al Viro
2020-03-23 18:38   ` [RFC][PATCH 14/22] x86: ia32_setup_frame(): consolidate uaccess areas Al Viro
2020-03-23 18:38   ` [RFC][PATCH 15/22] x86: ia32_setup_rt_frame(): " Al Viro
2020-03-23 18:38   ` [RFC][PATCH 16/22] x86: get rid of put_user_try in __setup_rt_frame() (both 32bit and 64bit) Al Viro
2020-03-23 18:38   ` [RFC][PATCH 17/22] x86: setup_sigcontext(): list user_access_{begin,end}() into callers Al Viro
2020-03-23 18:56     ` Linus Torvalds
2020-03-23 18:38   ` [RFC][PATCH 18/22] x86: __setup_frame(): consolidate uaccess areas Al Viro
2020-03-23 18:38   ` [RFC][PATCH 19/22] x86: __setup_rt_frame(): " Al Viro
2020-03-23 18:38   ` [RFC][PATCH 20/22] x86: x32_setup_rt_frame(): " Al Viro
2020-03-23 18:38   ` [RFC][PATCH 21/22] x86: unsafe_put_... macros for sigcontext and sigmask Al Viro
2020-03-23 18:38   ` [RFC][PATCH 22/22] kill uaccess_try() Al Viro
2020-03-24 15:15   ` [RFC][PATCH 01/22] x86 user stack frame reads: switch to explicit __get_user() Peter Zijlstra
2020-03-28 10:48   ` Ingo Molnar
2020-03-28 11:59     ` Al Viro
2020-03-29  9:26       ` Ingo Molnar
2020-03-29 16:50         ` Andy Lutomirski
2020-03-29 17:05           ` Linus Torvalds
2020-03-29 17:41           ` David Laight
2020-03-29 17:56             ` Linus Torvalds
2020-03-29 18:03               ` David Laight
2020-03-29 18:16                 ` Linus Torvalds [this message]
2020-03-29 18:32                   ` David Laight
2020-03-29 18:55                     ` Linus Torvalds
2020-03-29 21:21                   ` Andy Lutomirski
2020-03-29 22:06                     ` Linus Torvalds
2020-03-29 22:12                       ` Linus Torvalds
2020-03-29 18:16               ` Al Viro
2020-03-29 18:19                 ` Linus Torvalds
2020-03-29 17:57         ` Al Viro
2020-03-30 15:54           ` David Laight
2020-03-23 19:16 ` [RFC][PATCHSET] x86 uaccess cleanups Linus Torvalds
2020-03-27  2:24 ` [RFC][PATCHSET v2] " Al Viro
2020-03-27  2:26   ` Al Viro
2020-03-27  2:30     ` Al Viro
2020-03-27  2:31       ` [RFC][PATCH v2 01/22] x86 user stack frame reads: switch to explicit __get_user() Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 02/22] x86 kvm page table walks: " Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 03/22] x86: switch sigframe sigset handling to explict __get_user()/__put_user() Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 04/22] x86: get rid of small constant size cases in raw_copy_{to,from}_user() Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 05/22] vm86: get rid of get_user_ex() use Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 06/22] x86: get rid of get_user_ex() in ia32_restore_sigcontext() Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 07/22] x86: get rid of get_user_ex() in restore_sigcontext() Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 08/22] x86: kill get_user_{try,catch,ex} Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 09/22] x86: switch save_v86_state() to unsafe_put_user() Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 10/22] x86: switch setup_sigcontext() " Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 11/22] x86: switch ia32_setup_sigcontext() " Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 12/22] x86: get rid of put_user_try in {ia32,x32}_setup_rt_frame() Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 13/22] x86: ia32_setup_sigcontext(): lift user_access_{begin,end}() into the callers Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 14/22] x86: ia32_setup_frame(): consolidate uaccess areas Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 15/22] x86: ia32_setup_rt_frame(): " Al Viro
2020-03-27  2:31         ` [RFC][PATCH v2 16/22] x86: get rid of put_user_try in __setup_rt_frame() (both 32bit and 64bit) Al Viro
2020-03-27  2:32         ` [RFC][PATCH v2 17/22] x86: setup_sigcontext(): list user_access_{begin,end}() into callers Al Viro
2020-03-27  2:32         ` [RFC][PATCH v2 18/22] x86: __setup_frame(): consolidate uaccess areas Al Viro
2020-03-27  2:32         ` [RFC][PATCH v2 19/22] x86: __setup_rt_frame(): " Al Viro
2020-03-27  2:32         ` [RFC][PATCH v2 20/22] x86: x32_setup_rt_frame(): " Al Viro
2020-03-27  2:32         ` [RFC][PATCH v2 21/22] x86: unsafe_put-style macro for sigmask Al Viro
2020-03-27  2:32         ` [RFC][PATCH v2 22/22] kill uaccess_try() Al Viro

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='CAHk-=wjEf+0sBkPFKWpYZK_ygS9=ig3KTZkDe5jkDj+v8i7B+w@mail.gmail.com' \
    --to=torvalds@linux-foundation.org \
    --cc=David.Laight@aculab.com \
    --cc=bp@alien8.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=mingo@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=viro@zeniv.linux.org.uk \
    --cc=x86@kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.