[cfe-dev] [EXTERNAL] Re: making -ftrivial-auto-var-init=zero a first-class option
Joe Bialek via cfe-dev
cfe-dev at lists.llvm.org
Wed Apr 22 10:05:15 PDT 2020
We currently do not document the automatic initialization flags because we haven’t had customers ask for it through our official channels.
You are correct though, if we shipped this to customers they could do whatever they wanted with the flags. I’m simply stating how we are using the automatic initialization in our build environment.
From my perspective, all compilers already handle undefined behavior differently. i.e. in MSVC we don’t optimize away signed overflows in many cases due to security consequences of doing so. If people want to take a dependency on undefined behavior in the compiler they already can (and this makes this code less portable). We can give them the tools to avoid it though. In this case, if someone wants to make their code completely unportable by depending on zero init they can. It is their code though so I don’t really feel too bad about that. The recommendation should be to not take this dependency though, and to use different pattern settings for debug/retail builds to ensure you aren’t taking a dependency.
Clang could also ban zero-init for debug builds and only allow it for retail. This does potentially make it harder to debug actual issues though.
From: David Blaikie <dblaikie at gmail.com>
Sent: Wednesday, April 22, 2020 9:56 AM
To: Joe Bialek <jobialek at microsoft.com>
Cc: Kees Cook <keescook at chromium.org>; Hubert Tong <hubert.reinterpretcast at gmail.com>; Clang Dev <cfe-dev at lists.llvm.org>
Subject: Re: [cfe-dev] [EXTERNAL] Re: making -ftrivial-auto-var-init=zero a first-class option
On Tue, Apr 21, 2020 at 9:18 PM Joe Bialek via cfe-dev <cfe-dev at lists.llvm.org<mailto:cfe-dev at lists.llvm.org>> wrote:
To add in, we (Microsoft) currently use zero initialization technology in Visual Studio in a large amount of production code we ship to customers (all kernel components, a number of user-mode components). This code is both C and C++.
We already have had multiple vulnerabilities killed because we shipped this technology in production. We received bug reports with repros that worked on older versions of Windows without the mitigation and new versions of Windows that do have it. The new versions don't repro, the old ones do.
Using this sort of technology only in development (and not in production) is not sufficient. Some of these bugs will never produce crashes, the uninitialized data is copied across a trust boundary (i.e. from the kernel in to a untrusted user-mode process). This will never result in a crash but does result in a security issue. This is why shipping in production is a requirement even if you had perfect test coverage that exercises all code paths (which nobody has).
We do enable pattern initialization for debug builds and internal retail builds (using a developer mode in the build environment). We do this to help prevent "forking of the language" and also to force non-determinism. If your code relies on the zero-init, it won't work when we do pattern init. If your code only works with a non-zero value but doesn't care what that value is (Booleans, certain bit tests, etc.), it won't work with zero-init. Developers cannot depend on the automatic initialization for program correctness.
How is this, as a compiler feature, shipped to users? Users don't have a direct toggle available, but they say "I want memory init" with some compiler flag, then if they're building in debug (any unoptimized build, or only those with debug information emitted?) that translates to pattern, and in a build with any optimizations enabled (even the lowest level) they get zero init?
While in a constrained environment within a company I can see how you could hold that bar - once you ship that to end users I'd be afraid that some of them would figure out the least-optimizing (most debuggable) way to get zero init and avoid the pattern init behavior & write code that depended on that zero init - thus forking the language.
From: Kees Cook <keescook at chromium.org<mailto:keescook at chromium.org>>
Sent: Tuesday, April 21, 2020 4:20 PM
To: Hubert Tong <hubert.reinterpretcast at gmail.com<mailto:hubert.reinterpretcast at gmail.com>>
Cc: Clang Dev <cfe-dev at lists.llvm.org<mailto:cfe-dev at lists.llvm.org>>; Joe Bialek <jobialek at microsoft.com<mailto:jobialek at microsoft.com>>
Subject: [EXTERNAL] Re: [cfe-dev] making -ftrivial-auto-var-init=zero a first-class option
On Tue, Apr 21, 2020 at 06:29:07PM -0400, Hubert Tong wrote:
> On Tue, Apr 21, 2020 at 5:20 PM Kees Cook via cfe-dev <cfe-dev at lists.llvm.org<mailto:cfe-dev at lists.llvm.org>> wrote:
> > https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fcl
> > angbuiltlinux.github.io<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fangbuiltlinux.github.io%2F&data=02%7C01%7Cjobialek%40microsoft.com%7C781cef573d6548f6066a08d7e6de16ab%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637231714923718204&sdata=J5a%2B038vvTIxuhVZCdQo6DHP4K1N0tknWEqmuM2ZGX0%3D&reserved=0>%2FCBL-meetup-2020-slides%2Fglider%2FFighting
> > _uninitialized_memory_%2540_CBL_Meetup_2020.pdf&data=02%7C01%7Cj
> > obialek%40microsoft.com<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2F40microsoft.com%2F&data=02%7C01%7Cjobialek%40microsoft.com%7C781cef573d6548f6066a08d7e6de16ab%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637231714923728200&sdata=9kjsGbW2k9IvCpwxKa7p64nwnltKEr8Oelr1Zu8t7Mg%3D&reserved=0>%7C4bce6c76554b4dcf4c2b08d7e64a7848%7C72f988b
> > f86f141af91ab2d7cd011db47%7C1%7C0%7C637231080235713420&sdata=uMZ
> > PAiQvnjfLxORQNOAdUHGLY8czk8Mlsxc8dXpLSYg%3D&reserved=0
> > 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.
> This does not seem to indicate why zero-init is preferred over a
> default of using no explicit policy in production.
Do you mean "leaving things uninitialized" when you say "no explicit policy"? Maybe I've misunderstood. Google's goal of using auto-init is to eliminate uninitialized variables in production as a security defense. When examining zero-init vs pattern-init, there is a clear advantage on performance and size for zero-init.
> > as good. There are certainly exceptions here, but the bulk of the
> > historical record on how "uninitialized" variables have been used in
> Maybe an explanation of the scare quotes around "uninitialized" would
> help clarify your position.
Ah, sorry, I always use quotes (they are not intended to scare but to
clarify) when discussing uninitialized variables in real-world contexts, because they are, of course, not uninitialized in the sense of them not having a value. The RAM contents have a value. Many people without compiler backgrounds think of such variables as being uncontrollable or meaningless, when in fact they are usually highly controllable by an attacker, etc.
> > 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.
> I'm not sure that this is clear in terms of whether the statements
> apply to debug/development or production. I don't think pattern-init
> is meant to be a tool for production builds, which leads me to think
> that the above statement is about debug builds, at which point I'm
> thinking that using zero-init only serves to hide problems.
The context for Google's use of zero-init was meant here to be about production builds.
> > 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://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Flo
> > re.kernel.org<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fre.kernel.org%2F&data=02%7C01%7Cjobialek%40microsoft.com%7C781cef573d6548f6066a08d7e6de16ab%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637231714923728200&sdata=DeChhM5lA7Fe%2F9FEtvdlQoC%2Ft7DWyyTLPLjXPwkTPo8%3D&reserved=0>%2Flkml%2FCAHk-%3DwgTM%2BcN7zyUZacGQDv3DuuoA4LORNPWgb1Y
> > _Z1p4iedNQ%40mail.gmail.com<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2F40mail.gmail.com%2F&data=02%7C01%7Cjobialek%40microsoft.com%7C781cef573d6548f6066a08d7e6de16ab%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637231714923738196&sdata=mhHTUphR%2BGDt1yZYKPgdxE9SY8dvJFaZ3CVN2xW11LM%3D&reserved=0>%2F&data=02%7C01%7Cjobialek%40microso
> > ft.com<https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fft.com%2F&data=02%7C01%7Cjobialek%40microsoft.com%7C781cef573d6548f6066a08d7e6de16ab%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637231714923748191&sdata=QEjJwPKL1Tni68%2FtdomtwPclj%2FmlI%2BfTrzOpB6O0jdA%3D&reserved=0>%7C4bce6c76554b4dcf4c2b08d7e64a7848%7C72f988bf86f141af91ab2d7c
> > d011db47%7C1%7C0%7C637231080235723408&sdata=256CyAUusLIf8IetQfyd
> > 3KNAlIqVwV8uvjuPc6daP14%3D&reserved=0
> > Unsurprisingly, I strongly agree. ;)
> I don't see why claiming that pattern-init is bad helps make the case
> for zero-init.
Perhaps I did not express it well enough, but both have meaningful and important uses. My goal here is to illustrate how zero-init is being used (or preferred) in many real situations, as an argument for why it should not be hidden behind what some might see as a scary enable flag.
> > 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?
> There's a difference between "depending on zero-init" (as in, the
> group in question is okay with relying on implicit zeroing on code
> reviews, etc.) and the use of zero-init as some sort of
> defence-in-depth approach. Are these rumours clear as to which?
My understanding was the latter, but I hope to find out for real via this thread! :) It's not clear to me either.
> > 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?
> It happens that there is zero-init and it's at least close enough to
> what these projects want, but it is actually what they need?
Yes, it's expressly what is desired from a security perspective. (And quite to the relief of that same community, comes with the least performance impact, which is an unfortunately uncommon scenario in security flaw mitigations.) I tried to detail that earlier in my email where it's directly what is indicated as a meaningful defense against the long history of real-world "uninitialized" variable attacks: setting everything to zero is the best defense for the entire class of flaws.
cfe-dev mailing list
cfe-dev at lists.llvm.org<mailto:cfe-dev at lists.llvm.org>
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the cfe-dev