|
Date: Fri, 7 Jul 2017 09:16:17 +0100 From: Ard Biesheuvel <ard.biesheuvel@...aro.org> To: Arnd Bergmann <arnd@...db.de> Cc: Kernel Hardening <kernel-hardening@...ts.openwall.com>, Kees Cook <keescook@...omium.org>, Linus Torvalds <torvalds@...ux-foundation.org> Subject: Re: [RFC/RFT PATCH] gcc-plugins: force initialize auto variables whose addresses are taken On 6 July 2017 at 23:08, Arnd Bergmann <arnd@...db.de> wrote: > On Thu, Jul 6, 2017 at 1:25 PM, Arnd Bergmann <arnd@...db.de> wrote: >> On Thu, Jul 6, 2017 at 1:09 PM, Arnd Bergmann <arnd@...db.de> wrote: >>> On Thu, Jul 6, 2017 at 12:13 PM, Ard Biesheuvel >> >> Sorry, bad example, that one is a bit less undefined than >> I thought, as it will produce the same result every time, >> regardless of the stack contents. I'll try to come up >> with another test program instead. > > I've tried a few more things, but couldn't actually come up with an example > that ends up using uninitialized stack values without also warning about it, > so your plugin may actually cover the most important cases. > > The remaining cases I found are either uninitialized uses that we get > a compile-time warning for, or other kinds of undefined behavior > (as in my earlier example). > Yes, so your original example is actually the opposite side of the same coin. The compiler notices that 'i' may be returned uninitialized, but since 0 is equally suitable as any other value in this case, it just makes the assignment unconditional. So imagine a function call h(&i) preceding the switch. This forces the compiler to return whatever value i happens to have, because it cannot know whether calling h() amounts to an initialization. This all comes back to the way we pass structs by reference only, which is why I retained the struct/union type test in the plugin, even though stack buffers (i.e, u8 buf[xxx]) would probably deserve the same treatment. I think we should be able to deal with this more elegantly by annotating function parameters that are guaranteed to be set by the function, e.g, extern h(int * __out i) where we would on the one hand enforce that every code path in the definition of h() contains an assignment of *i, and on the other hand, omit the forced initialization of variables that appear as __out parameters. Alternatively (or to complement the effort), we could at least start making the effort to convert byref initializers to struct assignment, in cases where the function is a void type to begin with.
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.