[cfe-dev] making -ftrivial-auto-var-init=zero a first-class option

JF Bastien via cfe-dev cfe-dev at lists.llvm.org
Tue Apr 21 20:43:07 PDT 2020



> On Apr 21, 2020, at 2:20 PM, Kees Cook <keescook at chromium.org> wrote:
> 
> Hi,
> 
> tl;dr: I'd like to revisit making -ftrivial-auto-var-init=zero an expressly
> supported option. To do this, I think we need to either entirely remove
> "-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang"
> or rename it to something more directly reflecting the issue, like
> "-enable-trivial-auto-var-init-zero-knowing-it-forks-the-language".
> 
> This is currently open as https://bugs.llvm.org/show_bug.cgi?id=45497
> 
> Here is the situation: -ftrivial-auto-var-init=pattern is great for
> debugging, but -ftrivial-auto-var-init=zero is needed for production
> systems for mainly two reasons, each of which I will try to express context
> for:
> 
> 1) performance and size
> 
> As measured by various Google folks across a few projects and in
> various places, there's a fairly significant performance impact of
> using pattern-init over zero-init. I can let other folks chime in
> with their exact numbers, but I can at least share some measurements
> Alexander Potapenko made with the Linux kernel (see "Performance costs"):
> https://clangbuiltlinux.github.io/CBL-meetup-2020-slides/glider/Fighting_uninitialized_memory_%40_CBL_Meetup_2020.pdf
> tl;dr: zero-init tended to be half the cost of pattern-init, though it
> varied based on workload, and binary size impact fell over 95% going
> from pattern-init to zero-init.

The main reason folks were OK with me putting in zero init *at all* was to compare performance between 1) no init 2) zero init 3) pattern init, and *then* tune pattern init to the “floor” set by zero init. In other words: try to get to as low a cost as possible. I and other optimizer folks put significant efforts towards this, and we still are, but we’ve only done so for our binaries, and only on front-end / middle-end / ARM64. There’s still very low-lying fruit for pattern init on x86, and there’s more to be optimized on ARM64 and general middle-end. I’m therefore not sure we’re honoring the spirit of the agreement without putting in more optimization effort. To clarify: the performance got better, but we haven’t tried enough to declare “pattern init will definitely never get acceptably close to zero init”.

At the same time, it’s pretty obvious that synthesizing zero will always be cheaper than synthesizing repeated bytes. The question we’ve still to answer is: does this matter?

I’d like to see the remainder of the optimization work happen. It benefits generic code, not just pattern init. I don’t think it’s a mountain of work.


> 2) security
> 
> Another driving factor (see below from various vendors/projects), is the
> security stance. Putting non-zero values into most variables types ends
> up making them arguably more dangerous than if they were zero-filled.
> Most notably, sizes and indexes and less likely to be used out of bounds
> if they are zero-initialized. The same holds for bool values that tend
> to indicate success instead of failing safe with a false value. While
> pointers in the non-canonical range are nice, zero tends to be just
> as good. There are certainly exceptions here, but the bulk of the
> historical record on how "uninitialized" variables have been used in
> real world exploitation involve their being non-zero, and analysis of
> those bugs support that conclusion.
> 
> 
> Various positions from vendors and projects:
> 
> Google (Android, Chrome OS)
> 
> Both Android and Chrome OS initially started using pattern-init, but due
> to each of: the performance characteristics, the binary size changes, and
> the less robust security stance, both projects have recently committed
> to switching to zero-init.
> 
> 
> Microsoft (Windows)
> 
> I'm repeating what Joe Bialek has told me, so he can clarify if I'm not
> representing this correctly... While not using Clang/LLVM, Microsoft is
> part of the larger C/C++ ecosystem and has implemented both zero-init
> (for production builds) and pattern-init (for debug builds) in their
> compiler too. They also chose zero-init for production expressly due
> to the security benefits.
> 
> Some details of their work:
> https://github.com/microsoft/MSRC-Security-Research/blob/master/presentations/2019_09_CppCon/CppCon2019%20-%20Killing%20Uninitialized%20Memory.pdf
> 
> 
> Upstream Linux kernel
> 
> Linus Torvalds has directly stated that he wants zero-init:
> "So I'd like the zeroing of local variables to be a native compiler
> option..."
> "This, btw, is why I also think that the "initialize with poison" is
> pointless and wrong."
> https://lore.kernel.org/lkml/CAHk-=wgTM+cN7zyUZacGQDv3DuuoA4LORNPWgb1Y_Z1p4iedNQ@mail.gmail.com/
> Unsurprisingly, I strongly agree. ;)
> 
> 
> GrapheneOS is using zero-init (rather than patching Clang as it used to, to get
> the same result):
> https://twitter.com/DanielMicay/status/1248384468181643272
> 
> 
> GCC
> There's been mostly silence on the entire topic of automatic variable
> initialization, though there have been patches proposed in the past for
> zero-init:
> https://gcc.gnu.org/legacy-ml/gcc-patches/2014-06/msg00615.html
> 
> 
> Apple
> 
> I can't speak meaningfully here, but I've heard rumors that they are
> depending on zero-init as well. Perhaps someone there can clarify how
> they are using these features?

What I can easily share is in my LLVM dev meeting talk: https://www.youtube.com/watch?v=I-XUHPimq3o <https://www.youtube.com/watch?v=I-XUHPimq3o>
There I say that we’ve at least deployed it in Secure Enclave code, and XNU. I’ve seen people on the internet find other places we seem to have deployed it :-)


> So, while I understand the earlier objections to zero-init from a
> "language fork" concern, I think this isn't a position that can really
> stand up to the reality of how many projects are using the feature (even
> via non-Clang compilers). Given that so much code is going to be built
> using zero-init, what's the best way for Clang to adapt here? I would
> prefer to just drop the -enable... option entirely, but I think just
> renaming it would be fine too.
> 
> Thoughts/flames? ;)
> 
> -- 
> Kees Cook

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200421/78892191/attachment.html>


More information about the cfe-dev mailing list