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

Merge tag 'hardening-v6.16-rc1-fix1-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull hardening fixes from Kees Cook:

- randstruct: gcc-plugin: Fix attribute addition with GCC 15

- ubsan: integer-overflow: depend on BROKEN to keep this out of CI

- overflow: Introduce __DEFINE_FLEX for having no initializer

- wifi: iwlwifi: mld: Work around Clang loop unrolling bug

[ Take two after a jump scare due to some repo rewriting by 'b4' - Linus ]

* tag 'hardening-v6.16-rc1-fix1-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
randstruct: gcc-plugin: Fix attribute addition
overflow: Introduce __DEFINE_FLEX for having no initializer
ubsan: integer-overflow: depend on BROKEN to keep this out of CI
wifi: iwlwifi: mld: Work around Clang loop unrolling bug

+67 -20
+1 -1
drivers/net/wireless/intel/iwlwifi/mld/d3.c
··· 1757 1757 1758 1758 addrconf_addr_solict_mult(&wowlan_data->target_ipv6_addrs[i], 1759 1759 &solicited_addr); 1760 - for (j = 0; j < c; j++) 1760 + for (j = 0; j < n_nsc && j < c; j++) 1761 1761 if (ipv6_addr_cmp(&nsc[j].dest_ipv6_addr, 1762 1762 &solicited_addr) == 0) 1763 1763 break;
+21 -8
include/linux/overflow.h
··· 389 389 struct_size((type *)NULL, member, count) 390 390 391 391 /** 392 + * __DEFINE_FLEX() - helper macro for DEFINE_FLEX() family. 393 + * Enables caller macro to pass arbitrary trailing expressions 394 + * 395 + * @type: structure type name, including "struct" keyword. 396 + * @name: Name for a variable to define. 397 + * @member: Name of the array member. 398 + * @count: Number of elements in the array; must be compile-time const. 399 + * @trailer: Trailing expressions for attributes and/or initializers. 400 + */ 401 + #define __DEFINE_FLEX(type, name, member, count, trailer...) \ 402 + _Static_assert(__builtin_constant_p(count), \ 403 + "onstack flex array members require compile-time const count"); \ 404 + union { \ 405 + u8 bytes[struct_size_t(type, member, count)]; \ 406 + type obj; \ 407 + } name##_u trailer; \ 408 + type *name = (type *)&name##_u 409 + 410 + /** 392 411 * _DEFINE_FLEX() - helper macro for DEFINE_FLEX() family. 393 412 * Enables caller macro to pass (different) initializer. 394 413 * ··· 418 399 * @initializer: Initializer expression (e.g., pass `= { }` at minimum). 419 400 */ 420 401 #define _DEFINE_FLEX(type, name, member, count, initializer...) \ 421 - _Static_assert(__builtin_constant_p(count), \ 422 - "onstack flex array members require compile-time const count"); \ 423 - union { \ 424 - u8 bytes[struct_size_t(type, member, count)]; \ 425 - type obj; \ 426 - } name##_u = { .obj initializer }; \ 427 - type *name = (type *)&name##_u 402 + __DEFINE_FLEX(type, name, member, count, = { .obj initializer }) 428 403 429 404 /** 430 405 * DEFINE_RAW_FLEX() - Define an on-stack instance of structure with a trailing ··· 437 424 * elements in array @member. 438 425 */ 439 426 #define DEFINE_RAW_FLEX(type, name, member, count) \ 440 - _DEFINE_FLEX(type, name, member, count, = {}) 427 + __DEFINE_FLEX(type, name, member, count, = { }) 441 428 442 429 /** 443 430 * DEFINE_FLEX() - Define an on-stack instance of structure with a trailing
+2
lib/Kconfig.ubsan
··· 118 118 119 119 config UBSAN_INTEGER_WRAP 120 120 bool "Perform checking for integer arithmetic wrap-around" 121 + # This is very experimental so drop the next line if you really want it 122 + depends on BROKEN 121 123 depends on !COMPILE_TEST 122 124 depends on $(cc-option,-fsanitize-undefined-ignore-overflow-pattern=all) 123 125 depends on $(cc-option,-fsanitize=signed-integer-overflow)
+32
scripts/gcc-plugins/gcc-common.h
··· 115 115 return cstr; 116 116 } 117 117 118 + static inline void __add_type_attr(tree type, const char *attr, tree args) 119 + { 120 + tree oldattr; 121 + 122 + if (type == NULL_TREE) 123 + return; 124 + oldattr = lookup_attribute(attr, TYPE_ATTRIBUTES(type)); 125 + if (oldattr != NULL_TREE) { 126 + gcc_assert(TREE_VALUE(oldattr) == args || TREE_VALUE(TREE_VALUE(oldattr)) == TREE_VALUE(args)); 127 + return; 128 + } 129 + 130 + TYPE_ATTRIBUTES(type) = copy_list(TYPE_ATTRIBUTES(type)); 131 + TYPE_ATTRIBUTES(type) = tree_cons(get_identifier(attr), args, TYPE_ATTRIBUTES(type)); 132 + } 133 + 134 + static inline void add_type_attr(tree type, const char *attr, tree args) 135 + { 136 + tree main_variant = TYPE_MAIN_VARIANT(type); 137 + 138 + __add_type_attr(TYPE_CANONICAL(type), attr, args); 139 + __add_type_attr(TYPE_CANONICAL(main_variant), attr, args); 140 + __add_type_attr(main_variant, attr, args); 141 + 142 + for (type = TYPE_NEXT_VARIANT(main_variant); type; type = TYPE_NEXT_VARIANT(type)) { 143 + if (!lookup_attribute(attr, TYPE_ATTRIBUTES(type))) 144 + TYPE_ATTRIBUTES(type) = TYPE_ATTRIBUTES(main_variant); 145 + 146 + __add_type_attr(TYPE_CANONICAL(type), attr, args); 147 + } 148 + } 149 + 118 150 #define PASS_INFO(NAME, REF, ID, POS) \ 119 151 struct register_pass_info NAME##_pass_info = { \ 120 152 .pass = make_##NAME##_pass(), \
+11 -11
scripts/gcc-plugins/randomize_layout_plugin.c
··· 73 73 74 74 if (TYPE_P(*node)) { 75 75 type = *node; 76 + } else if (TREE_CODE(*node) == FIELD_DECL) { 77 + *no_add_attrs = false; 78 + return NULL_TREE; 76 79 } else { 77 80 gcc_assert(TREE_CODE(*node) == TYPE_DECL); 78 81 type = TREE_TYPE(*node); ··· 351 348 TREE_CHAIN(newtree[i]) = newtree[i+1]; 352 349 TREE_CHAIN(newtree[num_fields - 1]) = NULL_TREE; 353 350 351 + add_type_attr(type, "randomize_performed", NULL_TREE); 352 + add_type_attr(type, "designated_init", NULL_TREE); 353 + if (has_flexarray) 354 + add_type_attr(type, "has_flexarray", NULL_TREE); 355 + 354 356 main_variant = TYPE_MAIN_VARIANT(type); 355 - for (variant = main_variant; variant; variant = TYPE_NEXT_VARIANT(variant)) { 357 + for (variant = main_variant; variant; variant = TYPE_NEXT_VARIANT(variant)) 356 358 TYPE_FIELDS(variant) = newtree[0]; 357 - TYPE_ATTRIBUTES(variant) = copy_list(TYPE_ATTRIBUTES(variant)); 358 - TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("randomize_performed"), NULL_TREE, TYPE_ATTRIBUTES(variant)); 359 - TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("designated_init"), NULL_TREE, TYPE_ATTRIBUTES(variant)); 360 - if (has_flexarray) 361 - TYPE_ATTRIBUTES(type) = tree_cons(get_identifier("has_flexarray"), NULL_TREE, TYPE_ATTRIBUTES(type)); 362 - } 363 359 364 360 /* 365 361 * force a re-layout of the main variant ··· 426 424 if (lookup_attribute("randomize_layout", TYPE_ATTRIBUTES(TYPE_MAIN_VARIANT(type))) || is_pure_ops_struct(type)) 427 425 relayout_struct(type); 428 426 429 - for (variant = TYPE_MAIN_VARIANT(type); variant; variant = TYPE_NEXT_VARIANT(variant)) { 430 - TYPE_ATTRIBUTES(type) = copy_list(TYPE_ATTRIBUTES(type)); 431 - TYPE_ATTRIBUTES(type) = tree_cons(get_identifier("randomize_considered"), NULL_TREE, TYPE_ATTRIBUTES(type)); 432 - } 427 + add_type_attr(type, "randomize_considered", NULL_TREE); 428 + 433 429 #ifdef __DEBUG_PLUGIN 434 430 fprintf(stderr, "Marking randomize_considered on struct %s\n", ORIG_TYPE_NAME(type)); 435 431 #ifdef __DEBUG_VERBOSE