Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Tue, 6 Mar 2018 15:09:30 -0800
From: Linus Torvalds <>
To: Steven Rostedt <>
Cc: Arnd Bergmann <>, Ard Biesheuvel <>, 
	Daniel Micay <>, Ingo Molnar <>, 
	Kees Cook <>, 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 <>
Subject: Re: [PATCH RFC v9 4/7] x86/entry: Erase kernel stack in syscall_trace_enter()

On Tue, Mar 6, 2018 at 2:52 PM, Steven Rostedt <> wrote:
> I get your point. Basically you are saying that the language should
> have forced all local variables to be initialized to zero in the spec,
> and the compiler is free to optimize that initialization out if the
> variable is always initialized first.


> Just like it would optimize the below.
> int g(int c)
> {
>         int i = 0;
>         if (c < 10)
>                 i = 1;
>         else
>                 i = 2;
>         return i;
> };
> There's no reason to initialize i to zero because it will never return
> zero. But what you are saying is to make that implicit by just
> declaring 'i'.


And at the same time, it is certainly true that a compiler cannot
*always* remove the unnecessary initialization.

But with any half-way modern compiler, all the _normal_ cases would be
no-brainers, and the case where the compiler couldn't do so really is
code that almost certainly wants that initialization anyway, because a
_human_ generally wouldn't see that it's initialized either.

The obvious counter-example is literally

> int g(int c)
> {
>         int i = 0;
>         initialize_variable(&i);
>         if (c < 10)

where a *human* can tell that "hey, that initialization to zero is
pointless, because 'i' is clearly being initialized by that
'initialize_variable()' function call".

But the compiler often cannot see that "obvious" initialization, and
would have to spend the extra instruction to actually do that zero

So I'm not saying that it would always be entirely free to just have
the safe default.

But in the context of the kernel, I think that we can probably agree
that "oops, we've had exactly the kind of bug where a function
_didn't_ end up initializing the variable every time even though to a
human obviously thought it did" actually has happened.

Now, as mentioned, aggregate types are different.

They are _less_ different for the kernel than they are for user
programs (because we have to be careful about aggregate types on the
stack anyway just for stack size reasons), but they do have more
issues with the implicit initializers.

For aggregate types, initializers are obviously more expensive to
begin with, and the "initialize by passing a reference to an external
function" is much more common too. So there's a double hit.

At the same time, aggregate types are obviously where we tend to have
most problems, and I really think we should strive to avoid even
medium-sized aggregate types in the kernel anyway.

Which is why I'm much more willing to take a hit on those kinds of
things (that I think should be rare), than add things like "let's just
clear the stack after every system call" kinds of things.

But I do agree that for aggregate types, we almost certainly do want
to have some way to flag "this is explicitly not initialized".

Instead, right now, we're in the reverse situation, where we have to
add explicit initializers.

I think we'd be in a better situation if the *default* semantics was
the safe and well-defined behavior, and we'd have to do extra things
to get the undefined uninitialized behavior for when we know better,
and we really really care.


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.