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-v6.14-rc1-fix1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull hardening fixes from Kees Cook:
"This is a fix for the soon to be released GCC 15 which has regressed
its initialization of unions when performing explicit initialization
(i.e. a general problem, not specifically a hardening problem; we're
just carrying the fix).

Details in the final patch, Acked by Masahiro, with updated selftests
to validate the fix"

* tag 'hardening-v6.14-rc1-fix1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
kbuild: Use -fzero-init-padding-bits=all
stackinit: Add union initialization to selftests
stackinit: Add old-style zero-init syntax to struct tests

+109
+106
lib/stackinit_kunit.c
··· 47 47 #define DO_NOTHING_TYPE_SCALAR(var_type) var_type 48 48 #define DO_NOTHING_TYPE_STRING(var_type) void 49 49 #define DO_NOTHING_TYPE_STRUCT(var_type) void 50 + #define DO_NOTHING_TYPE_UNION(var_type) void 50 51 51 52 #define DO_NOTHING_RETURN_SCALAR(ptr) *(ptr) 52 53 #define DO_NOTHING_RETURN_STRING(ptr) /**/ 53 54 #define DO_NOTHING_RETURN_STRUCT(ptr) /**/ 55 + #define DO_NOTHING_RETURN_UNION(ptr) /**/ 54 56 55 57 #define DO_NOTHING_CALL_SCALAR(var, name) \ 56 58 (var) = do_nothing_ ## name(&(var)) ··· 60 58 do_nothing_ ## name(var) 61 59 #define DO_NOTHING_CALL_STRUCT(var, name) \ 62 60 do_nothing_ ## name(&(var)) 61 + #define DO_NOTHING_CALL_UNION(var, name) \ 62 + do_nothing_ ## name(&(var)) 63 63 64 64 #define FETCH_ARG_SCALAR(var) &var 65 65 #define FETCH_ARG_STRING(var) var 66 66 #define FETCH_ARG_STRUCT(var) &var 67 + #define FETCH_ARG_UNION(var) &var 67 68 68 69 /* 69 70 * On m68k, if the leaf function test variable is longer than 8 bytes, ··· 82 77 #define INIT_CLONE_SCALAR /**/ 83 78 #define INIT_CLONE_STRING [FILL_SIZE_STRING] 84 79 #define INIT_CLONE_STRUCT /**/ 80 + #define INIT_CLONE_UNION /**/ 85 81 86 82 #define ZERO_CLONE_SCALAR(zero) memset(&(zero), 0x00, sizeof(zero)) 87 83 #define ZERO_CLONE_STRING(zero) memset(&(zero), 0x00, sizeof(zero)) ··· 98 92 zero.three = 0; \ 99 93 zero.four = 0; \ 100 94 } while (0) 95 + #define ZERO_CLONE_UNION(zero) ZERO_CLONE_STRUCT(zero) 101 96 102 97 #define INIT_SCALAR_none(var_type) /**/ 103 98 #define INIT_SCALAR_zero(var_type) = 0 ··· 108 101 109 102 #define INIT_STRUCT_none(var_type) /**/ 110 103 #define INIT_STRUCT_zero(var_type) = { } 104 + #define INIT_STRUCT_old_zero(var_type) = { 0 } 111 105 112 106 113 107 #define __static_partial { .two = 0, } ··· 153 145 154 146 #define INIT_STRUCT_assigned_copy(var_type) \ 155 147 ; var = *(arg) 148 + 149 + /* Union initialization is the same as structs. */ 150 + #define INIT_UNION_none(var_type) INIT_STRUCT_none(var_type) 151 + #define INIT_UNION_zero(var_type) INIT_STRUCT_zero(var_type) 152 + #define INIT_UNION_old_zero(var_type) INIT_STRUCT_old_zero(var_type) 153 + 154 + #define INIT_UNION_static_partial(var_type) \ 155 + INIT_STRUCT_static_partial(var_type) 156 + #define INIT_UNION_static_all(var_type) \ 157 + INIT_STRUCT_static_all(var_type) 158 + #define INIT_UNION_dynamic_partial(var_type) \ 159 + INIT_STRUCT_dynamic_partial(var_type) 160 + #define INIT_UNION_dynamic_all(var_type) \ 161 + INIT_STRUCT_dynamic_all(var_type) 162 + #define INIT_UNION_runtime_partial(var_type) \ 163 + INIT_STRUCT_runtime_partial(var_type) 164 + #define INIT_UNION_runtime_all(var_type) \ 165 + INIT_STRUCT_runtime_all(var_type) 166 + #define INIT_UNION_assigned_static_partial(var_type) \ 167 + INIT_STRUCT_assigned_static_partial(var_type) 168 + #define INIT_UNION_assigned_static_all(var_type) \ 169 + INIT_STRUCT_assigned_static_all(var_type) 170 + #define INIT_UNION_assigned_dynamic_partial(var_type) \ 171 + INIT_STRUCT_assigned_dynamic_partial(var_type) 172 + #define INIT_UNION_assigned_dynamic_all(var_type) \ 173 + INIT_STRUCT_assigned_dynamic_all(var_type) 174 + #define INIT_UNION_assigned_copy(var_type) \ 175 + INIT_STRUCT_assigned_copy(var_type) 156 176 157 177 /* 158 178 * @name: unique string name for the test ··· 330 294 unsigned long four; 331 295 }; 332 296 297 + /* No padding: all members are the same size. */ 298 + union test_same_sizes { 299 + unsigned long one; 300 + unsigned long two; 301 + unsigned long three; 302 + unsigned long four; 303 + }; 304 + 305 + /* Mismatched sizes, with one and two being small */ 306 + union test_small_start { 307 + char one:1; 308 + char two; 309 + short three; 310 + unsigned long four; 311 + struct big_struct { 312 + unsigned long array[8]; 313 + } big; 314 + }; 315 + 316 + /* Mismatched sizes, with one and two being small */ 317 + union test_small_end { 318 + short one; 319 + unsigned long two; 320 + char three:1; 321 + char four; 322 + }; 323 + 333 324 #define ALWAYS_PASS WANT_SUCCESS 334 325 #define ALWAYS_FAIL XFAIL 335 326 ··· 395 332 struct test_ ## name, STRUCT, init, \ 396 333 xfail) 397 334 335 + #define DEFINE_UNION_TEST(name, init, xfail) \ 336 + DEFINE_TEST(name ## _ ## init, \ 337 + union test_ ## name, STRUCT, init, \ 338 + xfail) 339 + 398 340 #define DEFINE_STRUCT_TESTS(init, xfail) \ 399 341 DEFINE_STRUCT_TEST(small_hole, init, xfail); \ 400 342 DEFINE_STRUCT_TEST(big_hole, init, xfail); \ ··· 411 343 xfail); \ 412 344 DEFINE_STRUCT_TESTS(base ## _ ## all, xfail) 413 345 346 + #define DEFINE_UNION_INITIALIZER_TESTS(base, xfail) \ 347 + DEFINE_UNION_TESTS(base ## _ ## partial, \ 348 + xfail); \ 349 + DEFINE_UNION_TESTS(base ## _ ## all, xfail) 350 + 351 + #define DEFINE_UNION_TESTS(init, xfail) \ 352 + DEFINE_UNION_TEST(same_sizes, init, xfail); \ 353 + DEFINE_UNION_TEST(small_start, init, xfail); \ 354 + DEFINE_UNION_TEST(small_end, init, xfail); 355 + 414 356 /* These should be fully initialized all the time! */ 415 357 DEFINE_SCALAR_TESTS(zero, ALWAYS_PASS); 416 358 DEFINE_STRUCT_TESTS(zero, ALWAYS_PASS); 359 + DEFINE_STRUCT_TESTS(old_zero, ALWAYS_PASS); 360 + DEFINE_UNION_TESTS(zero, ALWAYS_PASS); 361 + DEFINE_UNION_TESTS(old_zero, ALWAYS_PASS); 417 362 /* Struct initializers: padding may be left uninitialized. */ 418 363 DEFINE_STRUCT_INITIALIZER_TESTS(static, STRONG_PASS); 419 364 DEFINE_STRUCT_INITIALIZER_TESTS(dynamic, STRONG_PASS); ··· 434 353 DEFINE_STRUCT_INITIALIZER_TESTS(assigned_static, STRONG_PASS); 435 354 DEFINE_STRUCT_INITIALIZER_TESTS(assigned_dynamic, STRONG_PASS); 436 355 DEFINE_STRUCT_TESTS(assigned_copy, ALWAYS_FAIL); 356 + DEFINE_UNION_INITIALIZER_TESTS(static, STRONG_PASS); 357 + DEFINE_UNION_INITIALIZER_TESTS(dynamic, STRONG_PASS); 358 + DEFINE_UNION_INITIALIZER_TESTS(runtime, STRONG_PASS); 359 + DEFINE_UNION_INITIALIZER_TESTS(assigned_static, STRONG_PASS); 360 + DEFINE_UNION_INITIALIZER_TESTS(assigned_dynamic, STRONG_PASS); 361 + DEFINE_UNION_TESTS(assigned_copy, ALWAYS_FAIL); 437 362 /* No initialization without compiler instrumentation. */ 438 363 DEFINE_SCALAR_TESTS(none, STRONG_PASS); 439 364 DEFINE_STRUCT_TESTS(none, BYREF_PASS); ··· 523 436 KUNIT_CASE(test_trailing_hole_ ## init),\ 524 437 KUNIT_CASE(test_packed_ ## init) \ 525 438 439 + #define KUNIT_test_unions(init) \ 440 + KUNIT_CASE(test_same_sizes_ ## init), \ 441 + KUNIT_CASE(test_small_start_ ## init), \ 442 + KUNIT_CASE(test_small_end_ ## init) \ 443 + 526 444 static struct kunit_case stackinit_test_cases[] = { 527 445 /* These are explicitly initialized and should always pass. */ 528 446 KUNIT_test_scalars(zero), 529 447 KUNIT_test_structs(zero), 448 + KUNIT_test_structs(old_zero), 449 + KUNIT_test_unions(zero), 450 + KUNIT_test_unions(old_zero), 530 451 /* Padding here appears to be accidentally always initialized? */ 531 452 KUNIT_test_structs(dynamic_partial), 532 453 KUNIT_test_structs(assigned_dynamic_partial), 454 + KUNIT_test_unions(dynamic_partial), 455 + KUNIT_test_unions(assigned_dynamic_partial), 533 456 /* Padding initialization depends on compiler behaviors. */ 534 457 KUNIT_test_structs(static_partial), 535 458 KUNIT_test_structs(static_all), ··· 549 452 KUNIT_test_structs(assigned_static_partial), 550 453 KUNIT_test_structs(assigned_static_all), 551 454 KUNIT_test_structs(assigned_dynamic_all), 455 + KUNIT_test_unions(static_partial), 456 + KUNIT_test_unions(static_all), 457 + KUNIT_test_unions(dynamic_all), 458 + KUNIT_test_unions(runtime_partial), 459 + KUNIT_test_unions(runtime_all), 460 + KUNIT_test_unions(assigned_static_partial), 461 + KUNIT_test_unions(assigned_static_all), 462 + KUNIT_test_unions(assigned_dynamic_all), 552 463 /* Everything fails this since it effectively performs a memcpy(). */ 553 464 KUNIT_test_structs(assigned_copy), 465 + KUNIT_test_unions(assigned_copy), 554 466 /* STRUCTLEAK_BYREF_ALL should cover everything from here down. */ 555 467 KUNIT_test_scalars(none), 556 468 KUNIT_CASE(test_switch_1_none),
+3
scripts/Makefile.extrawarn
··· 77 77 # Warn if there is an enum types mismatch 78 78 KBUILD_CFLAGS += $(call cc-option,-Wenum-conversion) 79 79 80 + # Explicitly clear padding bits during variable initialization 81 + KBUILD_CFLAGS += $(call cc-option,-fzero-init-padding-bits=all) 82 + 80 83 KBUILD_CFLAGS += -Wextra 81 84 KBUILD_CFLAGS += -Wunused 82 85