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

Philip Reames via cfe-dev cfe-dev at lists.llvm.org
Wed Apr 22 09:53:44 PDT 2020


On 4/21/20 4:59 PM, Richard Smith wrote:
> On Tue, 21 Apr 2020 at 16:49, Philip Reames via cfe-dev 
> <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
>
>     On 4/21/20 3:11 PM, Richard Smith via cfe-dev wrote:
>
>>     What you're proposing is, without question, a language extension.
>>     Our policy on language extensions is documented here:
>>     http://clang.llvm.org/get_involved.html
>>
>>     Right now, this fails at point 4. We do not want to create or
>>     encourage the creation of language dialects and non-portable
>>     code, so the place to have this discussion is in the C and C++
>>     committees. Both committees have processes for specifying
>>     optional features these days, and they might be amenable to using
>>     those processes to standardize the behavior you're asking for. (I
>>     mean, maybe not, but our policy requires that you at least try.)
>>
>>     However, there is a variant on what you're proposing that might
>>     fare better: instead of guaranteeing zero-initialization, we
>>     could guarantee that any observation of an uninitialized variable
>>     *either* gives produces zero or results in a trap. That is: it's
>>     still undefined to read from uninitialized variables -- we still
>>     do not guarantee what will happen if you do, and will warn on
>>     uninitialized uses and so on -- but we would bound the damage
>>     that can result from such accesses. You would get the security
>>     hardening benefits with the modest binary size impact. That
>>     approach would not introduce the risk of creating a language
>>     dialect (at least, not to the same extent), so our policy on
>>     avoiding language extensions would not apply.
>
>     Richard, just to check here, it sounds to me like you're raising
>     more a point of specification then of implementation right?  That
>     is, you're not stating that the actual implementation must
>     sometimes trap (when producing a zero wouldn't), but that the
>     specification of the flags and docs must leave the possibility
>     there of?
>
> Well, I think it's not sufficient to merely say that we might do 
> something like trap, if our intent is that we never will. We would 
> need to reasonably agree that (for example) if someone came forward 
> with a patch that actually implemented said trapping behavior and 
> didn't introduce any significant code size or performance impact, that 
> we would consider such a change to be a quality of implementation 
> improvement. But I don't think we need anyone to have actually 
> committed themselves to producing such a patch, or any timeline or 
> expectation of when (or indeed whether) it would be done. Sorry if 
> this is splitting a hair, but I think it's an important hair to split.
Hair successfully split.  I agree it is a key distinction.
>
>     If I'm complete misinterpreting, please just say so.  I don't want
>     to start a tangent discussion here, I just spotted what sound like
>     it could be a "quick fix" which lets to OP achieve their objective
>     and wanted to call it out if in fact I'd read correctly.
>
>     Philip
>
>>
>>     On Tue, 21 Apr 2020 at 14:21, Kees Cook via cfe-dev
>>     <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.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.
>>
>>         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?
>>
>>
>>
>>         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
>>         _______________________________________________
>>         cfe-dev mailing list
>>         cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>
>>         https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>>
>>     _______________________________________________
>>     cfe-dev mailing list
>>     cfe-dev at lists.llvm.org  <mailto:cfe-dev at lists.llvm.org>
>>     https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>     _______________________________________________
>     cfe-dev mailing list
>     cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>
>     https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200422/2d897d39/attachment-0001.html>


More information about the cfe-dev mailing list