* Fully initialized stack usage (was Re: [PATCH RFC v9 4/7] x86/entry: Erase kernel stack in syscall_trace_enter()) @ 2018-03-12 16:42 Kees Cook 2018-03-12 17:09 ` Linus Torvalds 0 siblings, 1 reply; 9+ messages in thread From: Kees Cook @ 2018-03-12 16:42 UTC (permalink / raw) To: Ingo Molnar, P J P, Florian Weimer Cc: Ard Biesheuvel, Linus Torvalds, Steven Rostedt, Arnd Bergmann, Daniel Micay, Dave Hansen, Alexander Popov, Kernel Hardening, PaX Team, Brad Spengler, Andy Lutomirski, Tycho Andersen, Laura Abbott, Mark Rutland, Borislav Petkov, Richard Sandiford, Thomas Gleixner, H . Peter Anvin, Peter Zijlstra, Dmitry V . Levin, Emese Revfy, Jonathan Corbet, Andrey Ryabinin, Kirill A . Shutemov, Thomas Garnier, Andrew Morton, Alexei Starovoitov, Josef Bacik, Masami Hiramatsu, Nicholas Piggin, Al Viro, David S . Miller, Ding Tianhong, David Woodhouse, Josh Poimboeuf, Dominik Brodowski, Juergen Gross, Greg Kroah-Hartman, Dan Williams, Mathias Krause, Vikas Shivappa, Kyle Huey, Dmitry Safonov, Will Deacon, X86 ML, LKML On Mon, Mar 12, 2018 at 2:21 AM, Ingo Molnar <mingo@kernel.org> wrote: > > * Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: > >> > Is it possible to implement this "safe automatic variable initialization" language >> > feature via a GCC plugin robustly, while still keeping code generation sane? (i.e. >> > no forced allocation of stack slots, etc.) It should be a superset of >> > CONFIG_GCC_PLUGIN_STRUCTLEAK=y. >> >> I think that should be feasible, yes. >> >> It would be worth trying whether the current code can be simplified, though: it >> currently takes care not to add such an initialization if it can already spot >> one, but I wonder whether just blindly adding one at the start and letting the >> compiler optimize it away again is safer. > > Absolutely - followed by: > > - a good look at the resulting code generation with a reasonably uptodate GCC > > - a look at the resulting code with older GCCs, to make sure there's no > pathological code generation > > ... because IMHO in the end it is the practical effects that will make (or break) > any such attempt. > > ( BTW., initializing all automatic variables might even speed up certain > optimization passes, FWIIW. ) [attempting to merge threads...] On Tue, Feb 27, 2018 at 3:15 AM, P J P <ppandit@redhat.com> wrote: > Please see: > -> https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00615.html > > This experimental patch by Florian Weimer(CC'd) adds an option > '-finit-local-vars' to gcc(1) compiler. When a program(or kernel) > is built using this option, its automatic(local) variables are > initialised with zero(0). This could significantly reduce the kernel > information leakage issues. > > A dnf(8) repository of the latest gcc-7.3.1 package built with the above > patch and kernel-4.15.5 package built using '-finit-local-vars' option > on Fedora-27 is available below > > -> https://pjp.fedorapeople.org/init-vars/ > > This same kernel is running on my F27 test machine as I write this. > There is no slowness or notice-able performance impact as such. Getting this implemented directly in the compiler would be preferred over a plugin. (Prototyping may be easier in the plugin, though.) Considerations: - the kernel needs a way to "opt out" of this for places where later functions will do the initialization. Something like __attribute__((no_automatic_variable_init)) ? - initialization _must include structure padding_. Without this, we're only solving part of the exposure. Does -finit-local-vars do this? - Can we retain the uninitialized variable usage warning? (with an updated text; maybe "variable used without explicit initialization, using zero-initialization"?) It sounds like Fedora-27's default kernel build is already using this option, is that correct? -Kees -- Kees Cook Pixel Security ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Fully initialized stack usage (was Re: [PATCH RFC v9 4/7] x86/entry: Erase kernel stack in syscall_trace_enter()) 2018-03-12 16:42 Fully initialized stack usage (was Re: [PATCH RFC v9 4/7] x86/entry: Erase kernel stack in syscall_trace_enter()) Kees Cook @ 2018-03-12 17:09 ` Linus Torvalds 2018-03-12 17:17 ` Kees Cook 2018-03-14 14:16 ` Florian Weimer 0 siblings, 2 replies; 9+ messages in thread From: Linus Torvalds @ 2018-03-12 17:09 UTC (permalink / raw) To: Kees Cook Cc: Ingo Molnar, P J P, Florian Weimer, Ard Biesheuvel, Steven Rostedt, Arnd Bergmann, Daniel Micay, Dave Hansen, Alexander Popov, Kernel Hardening, PaX Team, Brad Spengler, Andy Lutomirski, Tycho Andersen, Laura Abbott, Mark Rutland, Borislav Petkov, Richard Sandiford, Thomas Gleixner, H . Peter Anvin, Peter Zijlstra, Dmitry V . Levin, Emese Revfy, Jonathan Corbet, Andrey Ryabinin, Kirill A . Shutemov, Thomas Garnier, Andrew Morton, Alexei Starovoitov, Josef Bacik, Masami Hiramatsu, Nicholas Piggin, Al Viro, David S . Miller, Ding Tianhong, David Woodhouse, Josh Poimboeuf, Dominik Brodowski, Juergen Gross, Greg Kroah-Hartman, Dan Williams, Mathias Krause, Vikas Shivappa, Kyle Huey, Dmitry Safonov, Will Deacon, X86 ML, LKML On Mon, Mar 12, 2018 at 9:42 AM, Kees Cook <keescook@chromium.org> wrote: > > On Tue, Feb 27, 2018 at 3:15 AM, P J P <ppandit@redhat.com> wrote: >> Please see: >> -> https://gcc.gnu.org/ml/gcc-patches/2014-06/msg00615.html >> >> This experimental patch by Florian Weimer(CC'd) adds an option >> '-finit-local-vars' to gcc(1) compiler. When a program(or kernel) >> is built using this option, its automatic(local) variables are >> initialised with zero(0). This could significantly reduce the kernel >> information leakage issues. Oh, I love that patch. THAT is the kind of thing we should do. It's small, it's trivial, and it's done early in the parsing stage, so later stages will almost certainly end up optimizing things away. The only complaint I have is that the Fortran front-end already has (some of) that functionality, and calls it something else, and allows you to specify more exactly what you want to clear. Florian, are you aware of the Fortran flags? -finit-local-zero -finit-derived -finit-integer=n -finit-real=<zero|inf|-inf|nan|snan> -finit-logical=<true|false> -finit-character=n they aren't perfect for C, but some of them do make sense at least conceptually: things like being able to specify whether arrays and structures should be initialized (-finit-derived is kind of relevant) might make sense. In the kernel we'd likely always do it unconditionally (apart from optional per-function or per-declaration considerations) but I could easily see some other projects saying "do it for scalars but not for aggregate types". Because they might want the convenience, but not the expense. > Getting this implemented directly in the compiler would be preferred > over a plugin. (Prototyping may be easier in the plugin, though.) Absolutely. I think it's better in gcc simply because I suspect a number of other projects might use this flag too. A plugin is rather cumbersome. That said, the patch is literally right at the PLUGIN_FINISH_DECL, so doing it as a plugin for older compiler versions, or for just testing, might still be useful. > Considerations: > > - the kernel needs a way to "opt out" of this for places where later > functions will do the initialization. Something like > __attribute__((no_automatic_variable_init)) ? Yes, that's going to make it more palatable to some uses. However, somebody who knows gcc needs to verify that it does the right things when inlining happens. And honestly, it would be better to make it per-variable, not per function. That would fit the structure of that patch too, I think. It iterates over variables anyway to generate the initialization. > - initialization _must include structure padding_. Without this, we're > only solving part of the exposure. Does -finit-local-vars do this? Good point. It uses build_constructor() with an empty constructor, so it *should* be 100% equivalent to struct xyz var = { }; if I understand correctly, but I'm not sure what that will do with padding. > - Can we retain the uninitialized variable usage warning? (with an > updated text; maybe "variable used without explicit initialization, > using zero-initialization"?) I think that fundamentally goes away, because all later phases see fully initialized state. Linus ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Fully initialized stack usage (was Re: [PATCH RFC v9 4/7] x86/entry: Erase kernel stack in syscall_trace_enter()) 2018-03-12 17:09 ` Linus Torvalds @ 2018-03-12 17:17 ` Kees Cook 2018-03-12 17:45 ` Linus Torvalds 2018-03-14 14:16 ` Florian Weimer 1 sibling, 1 reply; 9+ messages in thread From: Kees Cook @ 2018-03-12 17:17 UTC (permalink / raw) To: Linus Torvalds Cc: Ingo Molnar, P J P, Florian Weimer, Ard Biesheuvel, Steven Rostedt, Arnd Bergmann, Daniel Micay, Dave Hansen, Alexander Popov, Kernel Hardening, PaX Team, Brad Spengler, Andy Lutomirski, Tycho Andersen, Laura Abbott, Mark Rutland, Borislav Petkov, Richard Sandiford, Thomas Gleixner, H . Peter Anvin, Peter Zijlstra, Dmitry V . Levin, Emese Revfy, Jonathan Corbet, Andrey Ryabinin, Kirill A . Shutemov, Thomas Garnier, Andrew Morton, Alexei Starovoitov, Josef Bacik, Masami Hiramatsu, Nicholas Piggin, Al Viro, David S . Miller, Ding Tianhong, David Woodhouse, Josh Poimboeuf, Dominik Brodowski, Juergen Gross, Greg Kroah-Hartman, Dan Williams, Mathias Krause, Vikas Shivappa, Kyle Huey, Dmitry Safonov, Will Deacon, X86 ML, LKML On Mon, Mar 12, 2018 at 10:09 AM, Linus Torvalds <torvalds@linux-foundation.org> wrote: > On Mon, Mar 12, 2018 at 9:42 AM, Kees Cook <keescook@chromium.org> wrote: >> - initialization _must include structure padding_. Without this, we're >> only solving part of the exposure. Does -finit-local-vars do this? > > Good point. It uses build_constructor() with an empty constructor, so > it *should* be 100% equivalent to > > struct xyz var = { }; > > if I understand correctly, but I'm not sure what that will do with padding. AIUI, this does not guarantee padding initialization (yet another "undefined behavior"). This is why we've had to sprinkle memset(&var, 0, sizeof(var)) in places where a structure has padding and got leaked. :( I assume this may be orthogonal to -finit-local-vars, and maybe we'll need some -finit-padding or something. (Though, honestly, is there anyone that wants to get _padding_ correct, but not variable initialization?) >> - Can we retain the uninitialized variable usage warning? (with an >> updated text; maybe "variable used without explicit initialization, >> using zero-initialization"?) > > I think that fundamentally goes away, because all later phases see > fully initialized state. I'm fine with it going away, though I share Jeff Law's observation in Florian's gcc thread that we lose some potentially useful warnings ("oops, it took a while to track down this bug, since that variable had been zero initialized; I wish I knew that had happened", etc.) And when the kernel entirely depends on auto-zero-init, we could just add -Wno-maybe-uninitialized. *shrug* -Kees -- Kees Cook Pixel Security ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Fully initialized stack usage (was Re: [PATCH RFC v9 4/7] x86/entry: Erase kernel stack in syscall_trace_enter()) 2018-03-12 17:17 ` Kees Cook @ 2018-03-12 17:45 ` Linus Torvalds 2018-03-14 14:21 ` Florian Weimer 0 siblings, 1 reply; 9+ messages in thread From: Linus Torvalds @ 2018-03-12 17:45 UTC (permalink / raw) To: Kees Cook Cc: Ingo Molnar, P J P, Florian Weimer, Ard Biesheuvel, Steven Rostedt, Arnd Bergmann, Daniel Micay, Dave Hansen, Alexander Popov, Kernel Hardening, PaX Team, Brad Spengler, Andy Lutomirski, Tycho Andersen, Laura Abbott, Mark Rutland, Borislav Petkov, Richard Sandiford, Thomas Gleixner, H . Peter Anvin, Peter Zijlstra, Dmitry V . Levin, Emese Revfy, Jonathan Corbet, Andrey Ryabinin, Kirill A . Shutemov, Thomas Garnier, Andrew Morton, Alexei Starovoitov, Josef Bacik, Masami Hiramatsu, Nicholas Piggin, Al Viro, David S . Miller, Ding Tianhong, David Woodhouse, Josh Poimboeuf, Dominik Brodowski, Juergen Gross, Greg Kroah-Hartman, Dan Williams, Mathias Krause, Vikas Shivappa, Kyle Huey, Dmitry Safonov, Will Deacon, X86 ML, LKML On Mon, Mar 12, 2018 at 10:17 AM, Kees Cook <keescook@chromium.org> wrote: > On Mon, Mar 12, 2018 at 10:09 AM, Linus Torvalds > <torvalds@linux-foundation.org> wrote: >> >> struct xyz var = { }; >> >> I'm not sure what that will do with padding. > > AIUI, this does not guarantee padding initialization (yet another > "undefined behavior"). This is why we've had to sprinkle memset(&var, > 0, sizeof(var)) in places where a structure has padding and got > leaked. :( > > I assume this may be orthogonal to -finit-local-vars, and maybe we'll > need some -finit-padding or something. (Though, honestly, is there > anyone that wants to get _padding_ correct, but not variable > initialization?) We would definitely have wanted it over the years, yes. And conceptually it's a separate issue, so a separate flag makes sense. But for the kernel, if we have -finit-local-vars, we'd just use that, so you're right that _we_ don't care, and I don't know if anybody else does either. Maybe some security-conscious project would, though. I can definitely see some project going "we always initialize our stuff ourselves, but we still worry about padding". So a separate flag for that would make a lot of sense. > I'm fine with it going away, though I share Jeff Law's observation in > Florian's gcc thread that we lose some potentially useful warnings > ("oops, it took a while to track down this bug, since that variable > had been zero initialized; I wish I knew that had happened", etc.) And > when the kernel entirely depends on auto-zero-init, we could just add > -Wno-maybe-uninitialized. *shrug* I think it's actually _fundamentally_ hard to give the "might be used uninitialized" warning together with "-finit-local-vars". You have to introduce a whole new "zero but counts as uninitialized" model. So I suspect the gcc people would be better off doing the reverse of what you suggest: tell people to simply do test builds without "-finit-local-vars". For example, for the kernel, we already have that "CONFIG_COMPILE_TEST" explicitly for the case of "build but don't use" for build coverage. So it would make sense for us to only use "-finit-local-vars" when COMPILE_TEST is _not_ set. That would give us the warnings for our coverage, but all "real" builds would be built with the initializations. Linus ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Fully initialized stack usage (was Re: [PATCH RFC v9 4/7] x86/entry: Erase kernel stack in syscall_trace_enter()) 2018-03-12 17:45 ` Linus Torvalds @ 2018-03-14 14:21 ` Florian Weimer 2018-03-14 15:52 ` Kees Cook 2018-03-14 16:29 ` Linus Torvalds 0 siblings, 2 replies; 9+ messages in thread From: Florian Weimer @ 2018-03-14 14:21 UTC (permalink / raw) To: Linus Torvalds, Kees Cook Cc: Ingo Molnar, P J P, Ard Biesheuvel, Steven Rostedt, Arnd Bergmann, Daniel Micay, Dave Hansen, Alexander Popov, Kernel Hardening, PaX Team, Brad Spengler, Andy Lutomirski, Tycho Andersen, Laura Abbott, Mark Rutland, Borislav Petkov, Richard Sandiford, Thomas Gleixner, H . Peter Anvin, Peter Zijlstra, Dmitry V . Levin, Emese Revfy, Jonathan Corbet, Andrey Ryabinin, Kirill A . Shutemov, Thomas Garnier, Andrew Morton, Alexei Starovoitov, Josef Bacik, Masami Hiramatsu, Nicholas Piggin, Al Viro, David S . Miller, Ding Tianhong, David Woodhouse, Josh Poimboeuf, Dominik Brodowski, Juergen Gross, Greg Kroah-Hartman, Dan Williams, Mathias Krause, Vikas Shivappa, Kyle Huey, Dmitry Safonov, Will Deacon, X86 ML, LKML On 03/12/2018 06:45 PM, Linus Torvalds wrote: > On Mon, Mar 12, 2018 at 10:17 AM, Kees Cook<keescook@chromium.org> wrote: >> On Mon, Mar 12, 2018 at 10:09 AM, Linus Torvalds >> <torvalds@linux-foundation.org> wrote: >>> struct xyz var = { }; >>> >>> I'm not sure what that will do with padding. >> AIUI, this does not guarantee padding initialization (yet another >> "undefined behavior"). This is why we've had to sprinkle memset(&var, >> 0, sizeof(var)) in places where a structure has padding and got >> leaked. :( >> >> I assume this may be orthogonal to -finit-local-vars, and maybe we'll >> need some -finit-padding or something. (Though, honestly, is there >> anyone that wants to get_padding_ correct, but not variable >> initialization?) > We would definitely have wanted it over the years, yes. And > conceptually it's a separate issue, so a separate flag makes sense. What would be the model for the kernel? Write zero to the padding initially, and on copying structs, make sure that you either copy the padding from the source, or clear the target? Clearing the padding while copying might be somewhat expensive. Thanks, Florian ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Fully initialized stack usage (was Re: [PATCH RFC v9 4/7] x86/entry: Erase kernel stack in syscall_trace_enter()) 2018-03-14 14:21 ` Florian Weimer @ 2018-03-14 15:52 ` Kees Cook 2018-03-14 16:29 ` Linus Torvalds 1 sibling, 0 replies; 9+ messages in thread From: Kees Cook @ 2018-03-14 15:52 UTC (permalink / raw) To: Florian Weimer Cc: Linus Torvalds, Ingo Molnar, P J P, Ard Biesheuvel, Steven Rostedt, Arnd Bergmann, Daniel Micay, Dave Hansen, Alexander Popov, Kernel Hardening, PaX Team, Brad Spengler, Andy Lutomirski, Tycho Andersen, Laura Abbott, Mark Rutland, Borislav Petkov, Richard Sandiford, Thomas Gleixner, H . Peter Anvin, Peter Zijlstra, Dmitry V . Levin, Emese Revfy, Jonathan Corbet, Andrey Ryabinin, Kirill A . Shutemov, Thomas Garnier, Andrew Morton, Alexei Starovoitov, Josef Bacik, Masami Hiramatsu, Nicholas Piggin, Al Viro, David S . Miller, Ding Tianhong, David Woodhouse, Josh Poimboeuf, Dominik Brodowski, Juergen Gross, Greg Kroah-Hartman, Dan Williams, Mathias Krause, Vikas Shivappa, Kyle Huey, Dmitry Safonov, Will Deacon, X86 ML, LKML On Wed, Mar 14, 2018 at 7:21 AM, Florian Weimer <fweimer@redhat.com> wrote: > On 03/12/2018 06:45 PM, Linus Torvalds wrote: >> >> On Mon, Mar 12, 2018 at 10:17 AM, Kees Cook<keescook@chromium.org> wrote: >>> >>> On Mon, Mar 12, 2018 at 10:09 AM, Linus Torvalds >>> <torvalds@linux-foundation.org> wrote: >>>> >>>> struct xyz var = { }; >>>> >>>> I'm not sure what that will do with padding. >>> >>> AIUI, this does not guarantee padding initialization (yet another >>> "undefined behavior"). This is why we've had to sprinkle memset(&var, >>> 0, sizeof(var)) in places where a structure has padding and got >>> leaked. :( >>> >>> I assume this may be orthogonal to -finit-local-vars, and maybe we'll >>> need some -finit-padding or something. (Though, honestly, is there >>> anyone that wants to get_padding_ correct, but not variable >>> initialization?) > > >> We would definitely have wanted it over the years, yes. And >> conceptually it's a separate issue, so a separate flag makes sense. > > > What would be the model for the kernel? Write zero to the padding > initially, and on copying structs, make sure that you either copy the > padding from the source, or clear the target? > > Clearing the padding while copying might be somewhat expensive. I think the common expectation is that copying does a full copy from the source. Zeroing of padding should be guaranteed by the constructor only, IMO. -Kees -- Kees Cook Pixel Security ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Fully initialized stack usage (was Re: [PATCH RFC v9 4/7] x86/entry: Erase kernel stack in syscall_trace_enter()) 2018-03-14 14:21 ` Florian Weimer 2018-03-14 15:52 ` Kees Cook @ 2018-03-14 16:29 ` Linus Torvalds 2018-03-14 16:38 ` Linus Torvalds 1 sibling, 1 reply; 9+ messages in thread From: Linus Torvalds @ 2018-03-14 16:29 UTC (permalink / raw) To: Florian Weimer Cc: Kees Cook, Ingo Molnar, P J P, Ard Biesheuvel, Steven Rostedt, Arnd Bergmann, Daniel Micay, Dave Hansen, Alexander Popov, Kernel Hardening, PaX Team, Brad Spengler, Andy Lutomirski, Tycho Andersen, Laura Abbott, Mark Rutland, Borislav Petkov, Richard Sandiford, Thomas Gleixner, H . Peter Anvin, Peter Zijlstra, Dmitry V . Levin, Emese Revfy, Jonathan Corbet, Andrey Ryabinin, Kirill A . Shutemov, Thomas Garnier, Andrew Morton, Alexei Starovoitov, Josef Bacik, Masami Hiramatsu, Nicholas Piggin, Al Viro, David S . Miller, Ding Tianhong, David Woodhouse, Josh Poimboeuf, Dominik Brodowski, Juergen Gross, Greg Kroah-Hartman, Dan Williams, Mathias Krause, Vikas Shivappa, Kyle Huey, Dmitry Safonov, Will Deacon, X86 ML, LKML On Wed, Mar 14, 2018 at 7:21 AM, Florian Weimer <fweimer@redhat.com> wrote: > > What would be the model for the kernel? Write zero to the padding > initially, and on copying structs, make sure that you either copy the > padding from the source, or clear the target? > > Clearing the padding while copying might be somewhat expensive. Oh, no, I wouldn't expect that at all. A structure copy assignment should act as a memcpy. I think the semantics should be that any padding is basically "unnamed content". So copying copies the whole struct, padding and all. Just as an example: struct a { char a; int b; }; int fn(struct a *); int test(struct a *dummy) { struct a a1 = { 1, 2 }; struct a a2 = { }; struct a a3 = *dummy; a2.b = 123; return fn(&a1) + fn(&a2) + fn(&a3); } and you can see examples of the bug, but also examples of right behavior. My current gcc (7.3.1-2 from F27) does movb $1, 8(%rsp) movl $2, 12(%rsp) for that first one - which is problematic because it will pass uninitialized state to 'fn()'. The second one results in good code: movl $0, 16(%rsp) movl $123, 20(%rsp) which is good and doesn't leave the padding uninitialized, and the third one results in movq (%rdi), %rax movq %rax, 24(%rsp) which is again fine. So it mostly works as expected, but things that initialize the structure one member at a time end up entirely skipping the padding, resulting in uninitialized parts on the stack being passed around. That's why I say that I think the semantics we would want is that padding acts as unnamed entries, ie it should _act_ as if the structure declaration was struct a { char a; char __padding[3]; int b; }; and that initialization of 'a1' then only iterated over the actual named entries, so that a1 = { 1, 2 } initializer would act like: struct a a1 = { .a = 1, .b = 2 }; which currently makes gcc generate movl $0, 8(%rsp) movl $2, 12(%rsp) movb $1, 8(%rsp) and initializes things properly. Ok, so gcc is admittedly oddly _stupid_ about it (a little bit clever, a little bit stupid), but that would still be quite acceptablke for the kernel. Note that the "unnamed padding" fields would automatically do the right thing for structure copies and everything else. It would literally only affect the case of assigning fields one by one, and force the padding to be zeroed too. So as far as implementation would go, I would suggest that one possible implementation is literally to create those dummy padding entries in the struct definition, and add a flag for "real" entries, and make unnamed initializers skip padding ones. But I haven't looked at how the initializer generation works in gcc, there may be some clever place that already knows about "oh, we skipped over padding, so let's just initialize it". Linus ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Fully initialized stack usage (was Re: [PATCH RFC v9 4/7] x86/entry: Erase kernel stack in syscall_trace_enter()) 2018-03-14 16:29 ` Linus Torvalds @ 2018-03-14 16:38 ` Linus Torvalds 0 siblings, 0 replies; 9+ messages in thread From: Linus Torvalds @ 2018-03-14 16:38 UTC (permalink / raw) To: Florian Weimer Cc: Kees Cook, Ingo Molnar, P J P, Ard Biesheuvel, Steven Rostedt, Arnd Bergmann, Daniel Micay, Dave Hansen, Alexander Popov, Kernel Hardening, PaX Team, Brad Spengler, Andy Lutomirski, Tycho Andersen, Laura Abbott, Mark Rutland, Borislav Petkov, Richard Sandiford, Thomas Gleixner, H . Peter Anvin, Peter Zijlstra, Dmitry V . Levin, Emese Revfy, Jonathan Corbet, Andrey Ryabinin, Kirill A . Shutemov, Thomas Garnier, Andrew Morton, Alexei Starovoitov, Josef Bacik, Masami Hiramatsu, Nicholas Piggin, Al Viro, David S . Miller, Ding Tianhong, David Woodhouse, Josh Poimboeuf, Dominik Brodowski, Juergen Gross, Greg Kroah-Hartman, Dan Williams, Mathias Krause, Vikas Shivappa, Kyle Huey, Dmitry Safonov, Will Deacon, X86 ML, LKML On Wed, Mar 14, 2018 at 9:29 AM, Linus Torvalds <torvalds@linux-foundation.org> wrote: > > The second one results in good code: > > movl $0, 16(%rsp) > movl $123, 20(%rsp) > > which is good and doesn't leave the padding uninitialized Side note: this obviously implies that your patch already fixes things, but funnily, it only if the structure didn't have an initializer. IOW, with your patch, struct a a; a = (struct a) ( 1, 2 }; would do the right thing for us because of an odd internal gcc implementation detail, because that initial definition of 'a' doesn't have an initializer, so your patch adds an empty one, and gcc seems to always treat that as "clear the whole stricture". After that, the structure assignment works fine and leaves the padding zero. But a plain struct a a = { 1, 2 }; doesn't DTRT, and leaves uninitialized bytes to be passed around. Of course, there might be other special cases that I simply didn't happen to trigger with my overly stupid example and testing. Maybe sometimes gcc does structure copies or clearing using the member-by-member model? My quick testing seems to indicate that it's _only_ initializers that cause this, whether they are part of the variable declaration or afterwards. Linus ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Fully initialized stack usage (was Re: [PATCH RFC v9 4/7] x86/entry: Erase kernel stack in syscall_trace_enter()) 2018-03-12 17:09 ` Linus Torvalds 2018-03-12 17:17 ` Kees Cook @ 2018-03-14 14:16 ` Florian Weimer 1 sibling, 0 replies; 9+ messages in thread From: Florian Weimer @ 2018-03-14 14:16 UTC (permalink / raw) To: Linus Torvalds, Kees Cook Cc: Ingo Molnar, P J P, Ard Biesheuvel, Steven Rostedt, Arnd Bergmann, Daniel Micay, Dave Hansen, Alexander Popov, Kernel Hardening, PaX Team, Brad Spengler, Andy Lutomirski, Tycho Andersen, Laura Abbott, Mark Rutland, Borislav Petkov, Richard Sandiford, Thomas Gleixner, H . Peter Anvin, Peter Zijlstra, Dmitry V . Levin, Emese Revfy, Jonathan Corbet, Andrey Ryabinin, Kirill A . Shutemov, Thomas Garnier, Andrew Morton, Alexei Starovoitov, Josef Bacik, Masami Hiramatsu, Nicholas Piggin, Al Viro, David S . Miller, Ding Tianhong, David Woodhouse, Josh Poimboeuf, Dominik Brodowski, Juergen Gross, Greg Kroah-Hartman, Dan Williams, Mathias Krause, Vikas Shivappa, Kyle Huey, Dmitry Safonov, Will Deacon, X86 ML, LKML On 03/12/2018 06:09 PM, Linus Torvalds wrote: > The only complaint I have is that the Fortran front-end already has > (some of) that functionality, and calls it something else, and allows > you to specify more exactly what you want to clear. > > Florian, are you aware of the Fortran flags? > > -finit-local-zero > -finit-derived > -finit-integer=n > -finit-real=<zero|inf|-inf|nan|snan> > -finit-logical=<true|false> > -finit-character=n > > they aren't perfect for C, but some of them do make sense at least > conceptually: things like being able to specify whether arrays and > structures should be initialized (-finit-derived is kind of relevant) > might make sense. I think I was aware of those when I put together the GCC patch, but it's been a while, so I don't know for sure. >> - the kernel needs a way to "opt out" of this for places where later >> functions will do the initialization. Something like >> __attribute__((no_automatic_variable_init)) ? > > Yes, that's going to make it more palatable to some uses. > > However, somebody who knows gcc needs to verify that it does the right > things when inlining happens. Given that the initializer is added in the parser, we should be able to look at the current function definition and get the attribute from there. Only if you want to do some special for nested functions, it's going to be tricky. Once the initializer is there, it will survive inlining, of course. > Good point. It uses build_constructor() with an empty constructor, so > it *should* be 100% equivalent to > > struct xyz var = { }; > > if I understand correctly, but I'm not sure what that will do with padding. There is no guarantee WRT padding if I understand this correctly. But not initializing padding would be less efficient, so GCC should do the right thing here. But this really needs to be careful checking by someone familiar with the middle-end and the relevant backends. Note that this patch was only for measuring the performance impact, so I didn't polish these finer points. >> - Can we retain the uninitialized variable usage warning? (with an >> updated text; maybe "variable used without explicit initialization, >> using zero-initialization"?) > > I think that fundamentally goes away, because all later phases see > fully initialized state. Yes, retaining the warning will need a completely different approach. Thanks, Florian ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2018-03-14 16:38 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-03-12 16:42 Fully initialized stack usage (was Re: [PATCH RFC v9 4/7] x86/entry: Erase kernel stack in syscall_trace_enter()) Kees Cook 2018-03-12 17:09 ` Linus Torvalds 2018-03-12 17:17 ` Kees Cook 2018-03-12 17:45 ` Linus Torvalds 2018-03-14 14:21 ` Florian Weimer 2018-03-14 15:52 ` Kees Cook 2018-03-14 16:29 ` Linus Torvalds 2018-03-14 16:38 ` Linus Torvalds 2018-03-14 14:16 ` Florian Weimer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®