Re: [SPARSE] noderef & ASM statements

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Jan 16, 2019 at 10:59 AM Luc Van Oostenryck
<luc.vanoostenryck@xxxxxxxxx> wrote:
> *) I've always considered __noderef as really meaning "must not be
>    dereferenced except by some special purpose operation which
>    effectively do the real deref". In the present case (percpu &
>    uaccess (on x86)), it's clear that the special operation is
>    the asm memory op but isn't this essentially incidental?

I agree that it's somewhat incidental rather than anything hugely by design.

That said, the *design* of __noderef was literally to make sure that
the *compiler* never derefences things, and the "special thing" that
does dereference was literally meant to be an inline asm. The
"{get,put}_user()" case was exactly what __noderef was designed for.

So it *is* very much by design, but then the implementation not
*checking* inline asm arguments was kind of an incidental thing.

Which is why I very much admit that it's annoying.

The good news is that the asm constraints aren't really all that
architecture-specific. Yes, all the various  register classes etc
obviously are, but within the concept of "the compiler never
dereferences it", the only asm constraints that matter are "m" and
"p", I think.

"m" means "memory", and "p" means "address". They are kind of the
same, except for a gcc memory access ordering situation, I think.

>  Thinking a bit more about it and looking at some dumps I made:
>    It seems that most of these these 'noderef in asm operand'
>    warnings (99.5%) come from percpu operations (which have an API
>    using an lvalue and not a pointer, unlike the uaccess API).
>
>    I begin to suspect that the warnings occuring with an uaccess
>    operation come from some other kind of error (possibly a missing
>    call to degenerate()).

Hmm. The uaccess cases definitely pass the lvalue in some cases. Not
the cases where we just end up doing a special "call" sequence (the
normal get_user/put_user() case). But look closer: the cases where we
actaully inline the access itself, we generate a "LKmode" lvalue with
that "__m(addr)" thing, and the actual access is done by the inline
asm.

See __get_user_asm(), __get_user_asm_nozero(), __get_user_asm_ex() and
__put_user_goto().

(Some of this has changed recently, so __put_user_goto() is a new
version of __put_user_asm(), so if you don't look at current kernel
-git, that's what you'll see instead).

               Linus



[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux