tl;dr: Turn on gcc/clang compiler option in kernel to fully initialize all kernel stack variables, as zero on release builds and nonzero pattern in current builds, to systematically plug kernel stack memory disclosure leaks with almost zero performance impact?
BACKGROUND gcc>=12 and clang>=8 have an option -ftrivial-auto-var-init=zero or -ftrivial-auto-var-init=pattern that initializes all variables with automatic storage duration (i.e., local variables in a function) with all-zero or all-some-pattern (currently 0xfe for gcc but might be changed, not sure for clang). https://gcc.gnu.org/onlinedocs/gcc-12.5.0/gcc/Optimize-Options.html#index-ftrivial-auto-var-init https://releases.llvm.org/8.0.0/tools/clang/docs/ClangCommandLineReference.html#cmdoption-clang-ftrivial-auto-var-init The option -ftrivial-auto-var-init=zero for clang>=8<16 also requires -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang-arg but in clang>=16 they assented to accepting it as first-class so it won't be necessary when we next update clang: https://releases.llvm.org/8.0.0/tools/clang/docs/ClangCommandLineReference.html#cmdoption-clang-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang-arg LIMITATIONS -ftrivial-auto-var-init does not work for variables declared before any cases in a switch, like: switch (foo) { int x; case 0: ... } The warning option -Wtrivial-auto-var-init reports such cases so we can make sure to avoid them. SECURITY BENEFIT Turning this on would essentially eliminate kernel stack disclosure vulnerabilities. CODE HYGIENE IMPACT In gcc, -ftrivial-auto-var-init does not change -Wuninitialized or -Wanalyzer-use-of-uninitialized-value warnings, so we would still get alerted if gcc can prove a variable would be affected by this option in case it appears in code that gets copied & pasted elsewhere -- in other words, turning this on doesn't reduce our build-time uninitialized variable hygiene; it just prevents mistakes from turning into kernel memory disclosure vulnerabilities. (Not sure offhand if it affects -Wuninitialized warnings in clang; the clang documentation, as usual, is infuriatingly terse.) PERFORMANCE IMPACT There is a small performance impact around 0-5% but these options are routinely used in large code bases at, e.g., Google and Microsoft these days -- we would not be the only ones trying out an experiment. For objects where the compiler can prove they are fully initialized where they are used, there's no change in code -- so it only will generally only have an impact on code that isn't obviously safe from kernel memory disclosure vulnerabilities in the first place, where we might be inclined to insert an explicit memset anyway. For Clang in the Linux kernel, the cost of -ftrivial-auto-var-init=pattern is approximately double the cost of -ftrivial-auto-var-init=zero -- and in some cases, zero-init actually made code _faster_ on arm64. Reference: https://clangbuiltlinux.github.io/CBL-meetup-2020-slides/glider/Fighting_uninitialized_memory_%40_CBL_Meetup_2020.pdf#page=27 I expect the impact is similar for gcc. FreeBSD turned this option on a while ago: <https://reviews.freebsd.org/D40208>. PROPOSAL -ftrivial-auto-var-init=pattern is more likely to provoke crashes in buggy code, while -ftrivial-auto-var-init=zero is more likely to to lead to silent inaction, since anything used as an array index or length will tend to lead to loops that run off the end when nonzero but lead to loops to do nothing when zero. So I propose that we: 1. Enable -ftrivial-auto-var-init=zero in the kernel for release builds with gcc and clang. 2. Enable -ftrivial-auto-var-init=pattern in the kernel for current builds with gcc and clang. 3. Enable -Wtrivial-auto-var-init in the kernel for builds with gcc.
