From a7eda6eddca559c1c3a897a35692f9d49d46c9dd Mon Sep 17 00:00:00 2001 From: "glider@google.com" Date: Tue, 16 Jun 2020 10:34:35 +0200 Subject: [PATCH] BACKPORT: security: allow using Clang's zero initialization for stack variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream commit f0fe00d4972a8cd4b98cc2c29758615e4d51cdfe. 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 Cc: Nick Desaulniers Cc: Greg Kroah-Hartman Signed-off-by: Alexander Potapenko Link: https://lore.kernel.org/r/20200616083435.223038-1-glider@google.com Reviewed-by: Maciej Żenczykowski Signed-off-by: Kees Cook Signed-off-by: Alexander Potapenko Change-Id: I2c76341a2b5f207b0b751293f2022b5ef99dbc45 --- Makefile | 14 +++++++++++--- init/main.c | 12 +++++++----- security/Kconfig.hardening | 19 ++++++++++++++++++- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 4a77831f18d9..a1014111cbdc 100644 --- a/Makefile +++ b/Makefile @@ -769,12 +769,20 @@ ifndef CONFIG_FUNCTION_TRACER 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 + KBUILD_CFLAGS += $(call cc-option, -fno-var-tracking-assignments) ifdef CONFIG_DEBUG_INFO diff --git a/init/main.c b/init/main.c index cef82a2957a0..20c6f2cc0f2b 100644 --- a/init/main.c +++ b/init/main.c @@ -493,14 +493,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"; diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening index 9cbecabd5600..80b3d4ba113f 100644 --- a/security/Kconfig.hardening +++ b/security/Kconfig.hardening @@ -25,7 +25,7 @@ choice classes 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)" help Initializes everything on the stack with a 0xAA @@ -34,6 +34,23 @@ 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)" + 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 INIT_ON_ALLOC_DEFAULT_ON