]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
security: allow using Clang's zero initialization for stack variables
authorglider@google.com <glider@google.com>
Tue, 16 Jun 2020 08:34:35 +0000 (10:34 +0200)
committerKees Cook <keescook@chromium.org>
Tue, 16 Jun 2020 09:06:23 +0000 (02:06 -0700)
In addition to -ftrivial-auto-var-init=pattern (used by
CONFIG_INIT_STACK_ALL now) Clang also supports zero initialization for
locals enabled by -ftrivial-auto-var-init=zero. The future of this flag
is still being debated (see https://bugs.llvm.org/show_bug.cgi?id=45497).
Right now it is guarded by another flag,
-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang,
which means it may not be supported by future Clang releases. Another
possible resolution is that -ftrivial-auto-var-init=zero will persist
(as certain users have already started depending on it), but the name
of the guard flag will change.

In the meantime, zero initialization has proven itself as a good
production mitigation measure against uninitialized locals. Unlike pattern
initialization, which has a higher chance of triggering existing bugs,
zero initialization provides safe defaults for strings, pointers, indexes,
and sizes. On the other hand, pattern initialization remains safer for
return values. Chrome OS and Android are moving to using zero
initialization for production builds.

Performance-wise, the difference between pattern and zero initialization
is usually negligible, although the generated code for zero
initialization is more compact.

This patch renames CONFIG_INIT_STACK_ALL to CONFIG_INIT_STACK_ALL_PATTERN
and introduces another config option, CONFIG_INIT_STACK_ALL_ZERO, that
enables zero initialization for locals if the corresponding flags are
supported by Clang.

Cc: Kees Cook <keescook@chromium.org>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Alexander Potapenko <glider@google.com>
Link: https://lore.kernel.org/r/20200616083435.223038-1-glider@google.com
Reviewed-by: Maciej Żenczykowski <maze@google.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Makefile
init/main.c
security/Kconfig.hardening

index ae5d8220f4310dd64a1d5086e105b65b7668628e..d1cfbe5abc493b6f375d8a0a66494c94d81d37dc 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -802,11 +802,20 @@ KBUILD_CFLAGS     += -fomit-frame-pointer
 endif
 endif
 
-# Initialize all stack variables with a pattern, if desired.
-ifdef CONFIG_INIT_STACK_ALL
+# Initialize all stack variables with a 0xAA pattern.
+ifdef CONFIG_INIT_STACK_ALL_PATTERN
 KBUILD_CFLAGS  += -ftrivial-auto-var-init=pattern
 endif
 
+# Initialize all stack variables with a zero value.
+ifdef CONFIG_INIT_STACK_ALL_ZERO
+# Future support for zero initialization is still being debated, see
+# https://bugs.llvm.org/show_bug.cgi?id=45497. These flags are subject to being
+# renamed or dropped.
+KBUILD_CFLAGS  += -ftrivial-auto-var-init=zero
+KBUILD_CFLAGS  += -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang
+endif
+
 DEBUG_CFLAGS   := $(call cc-option, -fno-var-tracking-assignments)
 
 ifdef CONFIG_DEBUG_INFO
index 0ead83e86b5aa298e769b51be5de2f6a94a7c44b..9127b240fd26b89815901082b80dffc8ac23f8c4 100644 (file)
@@ -779,14 +779,16 @@ static void __init report_meminit(void)
 {
        const char *stack;
 
-       if (IS_ENABLED(CONFIG_INIT_STACK_ALL))
-               stack = "all";
+       if (IS_ENABLED(CONFIG_INIT_STACK_ALL_PATTERN))
+               stack = "all(pattern)";
+       else if (IS_ENABLED(CONFIG_INIT_STACK_ALL_ZERO))
+               stack = "all(zero)";
        else if (IS_ENABLED(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL))
-               stack = "byref_all";
+               stack = "byref_all(zero)";
        else if (IS_ENABLED(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF))
-               stack = "byref";
+               stack = "byref(zero)";
        else if (IS_ENABLED(CONFIG_GCC_PLUGIN_STRUCTLEAK_USER))
-               stack = "__user";
+               stack = "__user(zero)";
        else
                stack = "off";
 
index af4c979b38eedb80411654f140a11f6312861dc2..269967c4fc1b67e81b403e9925497620974c68f8 100644 (file)
@@ -19,13 +19,16 @@ config GCC_PLUGIN_STRUCTLEAK
 
 menu "Memory initialization"
 
-config CC_HAS_AUTO_VAR_INIT
+config CC_HAS_AUTO_VAR_INIT_PATTERN
        def_bool $(cc-option,-ftrivial-auto-var-init=pattern)
 
+config CC_HAS_AUTO_VAR_INIT_ZERO
+       def_bool $(cc-option,-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang)
+
 choice
        prompt "Initialize kernel stack variables at function entry"
        default GCC_PLUGIN_STRUCTLEAK_BYREF_ALL if COMPILE_TEST && GCC_PLUGINS
-       default INIT_STACK_ALL if COMPILE_TEST && CC_HAS_AUTO_VAR_INIT
+       default INIT_STACK_ALL_PATTERN if COMPILE_TEST && CC_HAS_AUTO_VAR_INIT_PATTERN
        default INIT_STACK_NONE
        help
          This option enables initialization of stack variables at
@@ -88,9 +91,9 @@ choice
                  of uninitialized stack variable exploits and information
                  exposures.
 
-       config INIT_STACK_ALL
+       config INIT_STACK_ALL_PATTERN
                bool "0xAA-init everything on the stack (strongest)"
-               depends on CC_HAS_AUTO_VAR_INIT
+               depends on CC_HAS_AUTO_VAR_INIT_PATTERN
                help
                  Initializes everything on the stack with a 0xAA
                  pattern. This is intended to eliminate all classes
@@ -98,6 +101,24 @@ choice
                  exposures, even variables that were warned to have been
                  left uninitialized.
 
+                 Pattern initialization is known to provoke many existing bugs
+                 related to uninitialized locals, e.g. pointers receive
+                 non-NULL values, buffer sizes and indices are very big.
+
+       config INIT_STACK_ALL_ZERO
+               bool "zero-init everything on the stack (strongest and safest)"
+               depends on CC_HAS_AUTO_VAR_INIT_ZERO
+               help
+                 Initializes everything on the stack with a zero
+                 value. This is intended to eliminate all classes
+                 of uninitialized stack variable exploits and information
+                 exposures, even variables that were warned to have been
+                 left uninitialized.
+
+                 Zero initialization provides safe defaults for strings,
+                 pointers, indices and sizes, and is therefore
+                 more suitable as a security mitigation measure.
+
 endchoice
 
 config GCC_PLUGIN_STRUCTLEAK_VERBOSE