Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'hardening-v5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull hardening updates from Kees Cook:

- Expand lib/test_stackinit to include more initialization styles

- Improve Kconfig for CLang's auto-var-init feature

- Introduce support for GCC's zero-call-used-regs feature

* tag 'hardening-v5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
lib/test_stackinit: Add assigned initializers
lib/test_stackinit: Allow building stand-alone
lib/test_stackinit: Fix static initializer test
hardening: Clarify Kconfig text for auto-var-init
hardening: Introduce CONFIG_ZERO_CALL_USED_REGS

+241 -86
+5
Makefile
··· 841 841 # for the randomize_kstack_offset feature. Disable it for all compilers. 842 842 KBUILD_CFLAGS += $(call cc-option, -fno-stack-clash-protection) 843 843 844 + # Clear used registers at func exit (to reduce data lifetime and ROP gadgets). 845 + ifdef CONFIG_ZERO_CALL_USED_REGS 846 + KBUILD_CFLAGS += -fzero-call-used-regs=used-gpr 847 + endif 848 + 844 849 DEBUG_CFLAGS := 845 850 846 851 # Workaround for GCC versions < 5.0
+186 -67
lib/test_stackinit.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 2 /* 3 - * Test cases for compiler-based stack variable zeroing via future 4 - * compiler flags or CONFIG_GCC_PLUGIN_STRUCTLEAK*. 3 + * Test cases for compiler-based stack variable zeroing via 4 + * -ftrivial-auto-var-init={zero,pattern} or CONFIG_GCC_PLUGIN_STRUCTLEAK*. 5 + * 6 + * External build example: 7 + * clang -O2 -Wall -ftrivial-auto-var-init=pattern \ 8 + * -o test_stackinit test_stackinit.c 5 9 */ 10 + #ifdef __KERNEL__ 6 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7 12 8 13 #include <linux/init.h> 9 14 #include <linux/kernel.h> 10 15 #include <linux/module.h> 11 16 #include <linux/string.h> 17 + 18 + #else 19 + 20 + /* Userspace headers. */ 21 + #include <stdio.h> 22 + #include <stdint.h> 23 + #include <string.h> 24 + #include <stdbool.h> 25 + #include <errno.h> 26 + #include <sys/types.h> 27 + 28 + /* Linux kernel-ism stubs for stand-alone userspace build. */ 29 + #define KBUILD_MODNAME "stackinit" 30 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 31 + #define pr_err(fmt, ...) fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__) 32 + #define pr_warn(fmt, ...) fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__) 33 + #define pr_info(fmt, ...) fprintf(stdout, pr_fmt(fmt), ##__VA_ARGS__) 34 + #define __init /**/ 35 + #define __exit /**/ 36 + #define __user /**/ 37 + #define noinline __attribute__((__noinline__)) 38 + #define __aligned(x) __attribute__((__aligned__(x))) 39 + #ifdef __clang__ 40 + # define __compiletime_error(message) /**/ 41 + #else 42 + # define __compiletime_error(message) __attribute__((__error__(message))) 43 + #endif 44 + #define __compiletime_assert(condition, msg, prefix, suffix) \ 45 + do { \ 46 + extern void prefix ## suffix(void) __compiletime_error(msg); \ 47 + if (!(condition)) \ 48 + prefix ## suffix(); \ 49 + } while (0) 50 + #define _compiletime_assert(condition, msg, prefix, suffix) \ 51 + __compiletime_assert(condition, msg, prefix, suffix) 52 + #define compiletime_assert(condition, msg) \ 53 + _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) 54 + #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) 55 + #define BUILD_BUG_ON(condition) \ 56 + BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition) 57 + typedef uint8_t u8; 58 + typedef uint16_t u16; 59 + typedef uint32_t u32; 60 + typedef uint64_t u64; 61 + 62 + #define module_init(func) static int (*do_init)(void) = func 63 + #define module_exit(func) static void (*do_exit)(void) = func 64 + #define MODULE_LICENSE(str) int main(void) { \ 65 + int rc; \ 66 + /* License: str */ \ 67 + rc = do_init(); \ 68 + if (rc == 0) \ 69 + do_exit(); \ 70 + return rc; \ 71 + } 72 + 73 + #endif /* __KERNEL__ */ 12 74 13 75 /* Exfiltration buffer. */ 14 76 #define MAX_VAR_SIZE 128 ··· 94 32 return true; 95 33 return false; 96 34 } 35 + 36 + /* Whether the test is expected to fail. */ 37 + #define WANT_SUCCESS 0 38 + #define XFAIL 1 97 39 98 40 #define DO_NOTHING_TYPE_SCALAR(var_type) var_type 99 41 #define DO_NOTHING_TYPE_STRING(var_type) void ··· 124 58 #define INIT_CLONE_STRING [FILL_SIZE_STRING] 125 59 #define INIT_CLONE_STRUCT /**/ 126 60 127 - #define INIT_SCALAR_none /**/ 128 - #define INIT_SCALAR_zero = 0 61 + #define ZERO_CLONE_SCALAR(zero) memset(&(zero), 0x00, sizeof(zero)) 62 + #define ZERO_CLONE_STRING(zero) memset(&(zero), 0x00, sizeof(zero)) 63 + /* 64 + * For the struct, intentionally poison padding to see if it gets 65 + * copied out in direct assignments. 66 + * */ 67 + #define ZERO_CLONE_STRUCT(zero) \ 68 + do { \ 69 + memset(&(zero), 0xFF, sizeof(zero)); \ 70 + zero.one = 0; \ 71 + zero.two = 0; \ 72 + zero.three = 0; \ 73 + zero.four = 0; \ 74 + } while (0) 129 75 130 - #define INIT_STRING_none [FILL_SIZE_STRING] /**/ 131 - #define INIT_STRING_zero [FILL_SIZE_STRING] = { } 76 + #define INIT_SCALAR_none(var_type) /**/ 77 + #define INIT_SCALAR_zero(var_type) = 0 132 78 133 - #define INIT_STRUCT_none /**/ 134 - #define INIT_STRUCT_zero = { } 135 - #define INIT_STRUCT_static_partial = { .two = 0, } 136 - #define INIT_STRUCT_static_all = { .one = arg->one, \ 137 - .two = arg->two, \ 138 - .three = arg->three, \ 139 - .four = arg->four, \ 79 + #define INIT_STRING_none(var_type) [FILL_SIZE_STRING] /**/ 80 + #define INIT_STRING_zero(var_type) [FILL_SIZE_STRING] = { } 81 + 82 + #define INIT_STRUCT_none(var_type) /**/ 83 + #define INIT_STRUCT_zero(var_type) = { } 84 + 85 + 86 + #define __static_partial { .two = 0, } 87 + #define __static_all { .one = 0, \ 88 + .two = 0, \ 89 + .three = 0, \ 90 + .four = 0, \ 140 91 } 141 - #define INIT_STRUCT_dynamic_partial = { .two = arg->two, } 142 - #define INIT_STRUCT_dynamic_all = { .one = arg->one, \ 143 - .two = arg->two, \ 144 - .three = arg->three, \ 145 - .four = arg->four, \ 92 + #define __dynamic_partial { .two = arg->two, } 93 + #define __dynamic_all { .one = arg->one, \ 94 + .two = arg->two, \ 95 + .three = arg->three, \ 96 + .four = arg->four, \ 146 97 } 147 - #define INIT_STRUCT_runtime_partial ; \ 148 - var.two = 0 149 - #define INIT_STRUCT_runtime_all ; \ 150 - var.one = 0; \ 98 + #define __runtime_partial var.two = 0 99 + #define __runtime_all var.one = 0; \ 151 100 var.two = 0; \ 152 101 var.three = 0; \ 153 - memset(&var.four, 0, \ 154 - sizeof(var.four)) 102 + var.four = 0 103 + 104 + #define INIT_STRUCT_static_partial(var_type) \ 105 + = __static_partial 106 + #define INIT_STRUCT_static_all(var_type) \ 107 + = __static_all 108 + #define INIT_STRUCT_dynamic_partial(var_type) \ 109 + = __dynamic_partial 110 + #define INIT_STRUCT_dynamic_all(var_type) \ 111 + = __dynamic_all 112 + #define INIT_STRUCT_runtime_partial(var_type) \ 113 + ; __runtime_partial 114 + #define INIT_STRUCT_runtime_all(var_type) \ 115 + ; __runtime_all 116 + 117 + #define INIT_STRUCT_assigned_static_partial(var_type) \ 118 + ; var = (var_type)__static_partial 119 + #define INIT_STRUCT_assigned_static_all(var_type) \ 120 + ; var = (var_type)__static_all 121 + #define INIT_STRUCT_assigned_dynamic_partial(var_type) \ 122 + ; var = (var_type)__dynamic_partial 123 + #define INIT_STRUCT_assigned_dynamic_all(var_type) \ 124 + ; var = (var_type)__dynamic_all 125 + 126 + #define INIT_STRUCT_assigned_copy(var_type) \ 127 + ; var = *(arg) 155 128 156 129 /* 157 130 * @name: unique string name for the test ··· 211 106 BUILD_BUG_ON(sizeof(zero) > MAX_VAR_SIZE); \ 212 107 \ 213 108 /* Fill clone type with zero for per-field init. */ \ 214 - memset(&zero, 0x00, sizeof(zero)); \ 109 + ZERO_CLONE_ ## which(zero); \ 215 110 /* Clear entire check buffer for 0xFF overlap test. */ \ 216 111 memset(check_buf, 0x00, sizeof(check_buf)); \ 217 112 /* Fill stack with 0xFF. */ \ ··· 254 149 return (xfail) ? 0 : 1; \ 255 150 } \ 256 151 } 257 - #define DEFINE_TEST(name, var_type, which, init_level) \ 152 + #define DEFINE_TEST(name, var_type, which, init_level, xfail) \ 258 153 /* no-op to force compiler into ignoring "uninitialized" vars */\ 259 154 static noinline __init DO_NOTHING_TYPE_ ## which(var_type) \ 260 155 do_nothing_ ## name(var_type *ptr) \ ··· 270 165 var_type *arg) \ 271 166 { \ 272 167 char buf[VAR_BUFFER]; \ 273 - var_type var INIT_ ## which ## _ ## init_level; \ 168 + var_type var \ 169 + INIT_ ## which ## _ ## init_level(var_type); \ 274 170 \ 275 171 target_start = &var; \ 276 172 target_size = sizeof(var); \ ··· 297 191 \ 298 192 return (int)buf[0] | (int)buf[sizeof(buf) - 1]; \ 299 193 } \ 300 - DEFINE_TEST_DRIVER(name, var_type, which, 0) 194 + DEFINE_TEST_DRIVER(name, var_type, which, xfail) 301 195 302 196 /* Structure with no padding. */ 303 197 struct test_packed { ··· 316 210 unsigned long four; 317 211 }; 318 212 319 - /* Try to trigger unhandled padding in a structure. */ 320 - struct test_aligned { 321 - u32 internal1; 322 - u64 internal2; 323 - } __aligned(64); 324 - 213 + /* Trigger unhandled padding in a structure. */ 325 214 struct test_big_hole { 326 215 u8 one; 327 216 u8 two; 328 217 u8 three; 329 218 /* 61 byte padding hole here. */ 330 - struct test_aligned four; 219 + u8 four __aligned(64); 331 220 } __aligned(64); 332 221 333 222 struct test_trailing_hole { ··· 341 240 unsigned long four; 342 241 }; 343 242 344 - #define DEFINE_SCALAR_TEST(name, init) \ 345 - DEFINE_TEST(name ## _ ## init, name, SCALAR, init) 243 + #define DEFINE_SCALAR_TEST(name, init, xfail) \ 244 + DEFINE_TEST(name ## _ ## init, name, SCALAR, \ 245 + init, xfail) 346 246 347 - #define DEFINE_SCALAR_TESTS(init) \ 348 - DEFINE_SCALAR_TEST(u8, init); \ 349 - DEFINE_SCALAR_TEST(u16, init); \ 350 - DEFINE_SCALAR_TEST(u32, init); \ 351 - DEFINE_SCALAR_TEST(u64, init); \ 352 - DEFINE_TEST(char_array_ ## init, unsigned char, STRING, init) 247 + #define DEFINE_SCALAR_TESTS(init, xfail) \ 248 + DEFINE_SCALAR_TEST(u8, init, xfail); \ 249 + DEFINE_SCALAR_TEST(u16, init, xfail); \ 250 + DEFINE_SCALAR_TEST(u32, init, xfail); \ 251 + DEFINE_SCALAR_TEST(u64, init, xfail); \ 252 + DEFINE_TEST(char_array_ ## init, unsigned char, \ 253 + STRING, init, xfail) 353 254 354 - #define DEFINE_STRUCT_TEST(name, init) \ 255 + #define DEFINE_STRUCT_TEST(name, init, xfail) \ 355 256 DEFINE_TEST(name ## _ ## init, \ 356 - struct test_ ## name, STRUCT, init) 257 + struct test_ ## name, STRUCT, init, \ 258 + xfail) 357 259 358 - #define DEFINE_STRUCT_TESTS(init) \ 359 - DEFINE_STRUCT_TEST(small_hole, init); \ 360 - DEFINE_STRUCT_TEST(big_hole, init); \ 361 - DEFINE_STRUCT_TEST(trailing_hole, init); \ 362 - DEFINE_STRUCT_TEST(packed, init) 260 + #define DEFINE_STRUCT_TESTS(init, xfail) \ 261 + DEFINE_STRUCT_TEST(small_hole, init, xfail); \ 262 + DEFINE_STRUCT_TEST(big_hole, init, xfail); \ 263 + DEFINE_STRUCT_TEST(trailing_hole, init, xfail); \ 264 + DEFINE_STRUCT_TEST(packed, init, xfail) 265 + 266 + #define DEFINE_STRUCT_INITIALIZER_TESTS(base) \ 267 + DEFINE_STRUCT_TESTS(base ## _ ## partial, \ 268 + WANT_SUCCESS); \ 269 + DEFINE_STRUCT_TESTS(base ## _ ## all, \ 270 + WANT_SUCCESS) 363 271 364 272 /* These should be fully initialized all the time! */ 365 - DEFINE_SCALAR_TESTS(zero); 366 - DEFINE_STRUCT_TESTS(zero); 367 - /* Static initialization: padding may be left uninitialized. */ 368 - DEFINE_STRUCT_TESTS(static_partial); 369 - DEFINE_STRUCT_TESTS(static_all); 370 - /* Dynamic initialization: padding may be left uninitialized. */ 371 - DEFINE_STRUCT_TESTS(dynamic_partial); 372 - DEFINE_STRUCT_TESTS(dynamic_all); 373 - /* Runtime initialization: padding may be left uninitialized. */ 374 - DEFINE_STRUCT_TESTS(runtime_partial); 375 - DEFINE_STRUCT_TESTS(runtime_all); 273 + DEFINE_SCALAR_TESTS(zero, WANT_SUCCESS); 274 + DEFINE_STRUCT_TESTS(zero, WANT_SUCCESS); 275 + /* Struct initializers: padding may be left uninitialized. */ 276 + DEFINE_STRUCT_INITIALIZER_TESTS(static); 277 + DEFINE_STRUCT_INITIALIZER_TESTS(dynamic); 278 + DEFINE_STRUCT_INITIALIZER_TESTS(runtime); 279 + DEFINE_STRUCT_INITIALIZER_TESTS(assigned_static); 280 + DEFINE_STRUCT_INITIALIZER_TESTS(assigned_dynamic); 281 + DEFINE_STRUCT_TESTS(assigned_copy, XFAIL); 376 282 /* No initialization without compiler instrumentation. */ 377 - DEFINE_SCALAR_TESTS(none); 378 - DEFINE_STRUCT_TESTS(none); 379 - DEFINE_TEST(user, struct test_user, STRUCT, none); 283 + DEFINE_SCALAR_TESTS(none, WANT_SUCCESS); 284 + DEFINE_STRUCT_TESTS(none, WANT_SUCCESS); 285 + /* Initialization of members with __user attribute. */ 286 + DEFINE_TEST(user, struct test_user, STRUCT, none, WANT_SUCCESS); 380 287 381 288 /* 382 289 * Check two uses through a variable declaration outside either path, ··· 394 285 static int noinline __leaf_switch_none(int path, bool fill) 395 286 { 396 287 switch (path) { 288 + /* 289 + * This is intentionally unreachable. To silence the 290 + * warning, build with -Wno-switch-unreachable 291 + */ 397 292 uint64_t var; 398 293 399 294 case 1: ··· 447 334 * non-code areas (i.e. in a switch statement before the first "case"). 448 335 * https://bugs.llvm.org/show_bug.cgi?id=44916 449 336 */ 450 - DEFINE_TEST_DRIVER(switch_1_none, uint64_t, SCALAR, 1); 451 - DEFINE_TEST_DRIVER(switch_2_none, uint64_t, SCALAR, 1); 337 + DEFINE_TEST_DRIVER(switch_1_none, uint64_t, SCALAR, XFAIL); 338 + DEFINE_TEST_DRIVER(switch_2_none, uint64_t, SCALAR, XFAIL); 452 339 453 340 static int __init test_stackinit_init(void) 454 341 { ··· 474 361 test_structs(zero); 475 362 /* Padding here appears to be accidentally always initialized? */ 476 363 test_structs(dynamic_partial); 364 + test_structs(assigned_dynamic_partial); 477 365 /* Padding initialization depends on compiler behaviors. */ 478 366 test_structs(static_partial); 479 367 test_structs(static_all); 480 368 test_structs(dynamic_all); 481 369 test_structs(runtime_partial); 482 370 test_structs(runtime_all); 371 + test_structs(assigned_static_partial); 372 + test_structs(assigned_static_all); 373 + test_structs(assigned_dynamic_all); 374 + /* Everything fails this since it effectively performs a memcpy(). */ 375 + test_structs(assigned_copy); 483 376 484 377 /* STRUCTLEAK_BYREF_ALL should cover everything from here down. */ 485 378 test_scalars(none);
+50 -19
security/Kconfig.hardening
··· 29 29 prompt "Initialize kernel stack variables at function entry" 30 30 default GCC_PLUGIN_STRUCTLEAK_BYREF_ALL if COMPILE_TEST && GCC_PLUGINS 31 31 default INIT_STACK_ALL_PATTERN if COMPILE_TEST && CC_HAS_AUTO_VAR_INIT_PATTERN 32 + default INIT_STACK_ALL_ZERO if CC_HAS_AUTO_VAR_INIT_PATTERN 32 33 default INIT_STACK_NONE 33 34 help 34 35 This option enables initialization of stack variables at ··· 40 39 syscalls. 41 40 42 41 This chooses the level of coverage over classes of potentially 43 - uninitialized variables. The selected class will be 42 + uninitialized variables. The selected class of variable will be 44 43 initialized before use in a function. 45 44 46 45 config INIT_STACK_NONE 47 - bool "no automatic initialization (weakest)" 46 + bool "no automatic stack variable initialization (weakest)" 48 47 help 49 48 Disable automatic stack variable initialization. 50 49 This leaves the kernel vulnerable to the standard ··· 81 80 and is disallowed. 82 81 83 82 config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL 84 - bool "zero-init anything passed by reference (very strong)" 83 + bool "zero-init everything passed by reference (very strong)" 85 84 depends on GCC_PLUGINS 86 85 depends on !(KASAN && KASAN_STACK) 87 86 select GCC_PLUGIN_STRUCTLEAK ··· 92 91 of uninitialized stack variable exploits and information 93 92 exposures. 94 93 94 + As a side-effect, this keeps a lot of variables on the 95 + stack that can otherwise be optimized out, so combining 96 + this with CONFIG_KASAN_STACK can lead to a stack overflow 97 + and is disallowed. 98 + 95 99 config INIT_STACK_ALL_PATTERN 96 - bool "0xAA-init everything on the stack (strongest)" 100 + bool "pattern-init everything (strongest)" 97 101 depends on CC_HAS_AUTO_VAR_INIT_PATTERN 98 102 help 99 - Initializes everything on the stack with a 0xAA 100 - pattern. This is intended to eliminate all classes 101 - of uninitialized stack variable exploits and information 102 - exposures, even variables that were warned to have been 103 - left uninitialized. 103 + Initializes everything on the stack (including padding) 104 + with a specific debug value. This is intended to eliminate 105 + all classes of uninitialized stack variable exploits and 106 + information exposures, even variables that were warned about 107 + having been left uninitialized. 104 108 105 109 Pattern initialization is known to provoke many existing bugs 106 110 related to uninitialized locals, e.g. pointers receive 107 - non-NULL values, buffer sizes and indices are very big. 111 + non-NULL values, buffer sizes and indices are very big. The 112 + pattern is situation-specific; Clang on 64-bit uses 0xAA 113 + repeating for all types and padding except float and double 114 + which use 0xFF repeating (-NaN). Clang on 32-bit uses 0xFF 115 + repeating for all types and padding. 108 116 109 117 config INIT_STACK_ALL_ZERO 110 - bool "zero-init everything on the stack (strongest and safest)" 118 + bool "zero-init everything (strongest and safest)" 111 119 depends on CC_HAS_AUTO_VAR_INIT_ZERO 112 120 help 113 - Initializes everything on the stack with a zero 114 - value. This is intended to eliminate all classes 115 - of uninitialized stack variable exploits and information 116 - exposures, even variables that were warned to have been 117 - left uninitialized. 121 + Initializes everything on the stack (including padding) 122 + with a zero value. This is intended to eliminate all 123 + classes of uninitialized stack variable exploits and 124 + information exposures, even variables that were warned 125 + about having been left uninitialized. 118 126 119 - Zero initialization provides safe defaults for strings, 120 - pointers, indices and sizes, and is therefore 121 - more suitable as a security mitigation measure. 127 + Zero initialization provides safe defaults for strings 128 + (immediately NUL-terminated), pointers (NULL), indices 129 + (index 0), and sizes (0 length), so it is therefore more 130 + suitable as a production security mitigation than pattern 131 + initialization. 122 132 123 133 endchoice 124 134 ··· 228 216 than "init_on_alloc" due to the negative cache effects of 229 217 touching "cold" memory areas. Most cases see 3-5% impact. Some 230 218 synthetic workloads have measured as high as 8%. 219 + 220 + config CC_HAS_ZERO_CALL_USED_REGS 221 + def_bool $(cc-option,-fzero-call-used-regs=used-gpr) 222 + 223 + config ZERO_CALL_USED_REGS 224 + bool "Enable register zeroing on function exit" 225 + depends on CC_HAS_ZERO_CALL_USED_REGS 226 + help 227 + At the end of functions, always zero any caller-used register 228 + contents. This helps ensure that temporary values are not 229 + leaked beyond the function boundary. This means that register 230 + contents are less likely to be available for side channels 231 + and information exposures. Additionally, this helps reduce the 232 + number of useful ROP gadgets by about 20% (and removes compiler 233 + generated "write-what-where" gadgets) in the resulting kernel 234 + image. This has a less than 1% performance impact on most 235 + workloads. Image size growth depends on architecture, and should 236 + be evaluated for suitability. For example, x86_64 grows by less 237 + than 1%, and arm64 grows by about 5%. 231 238 232 239 endmenu 233 240