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

Pull hardening updates from Kees Cook:
"Mostly small cleanups and various scattered annotations and flex array
warning fixes that we reviewed by unlanded in other trees. Introduces
new annotation for expanding counted_by to pointer members, now that
compiler behavior between GCC and Clang has been normalized.

- Various missed __counted_by annotations (Thorsten Blum)

- Various missed -Wflex-array-member-not-at-end fixes (Gustavo A. R.
Silva)

- Avoid leftover tempfiles for interrupted compile-time FORTIFY tests
(Nicolas Schier)

- Remove non-existant CONFIG_UBSAN_REPORT_FULL from docs (Stefan
Wiehler)

- fortify: Use C arithmetic not FIELD_xxx() in FORTIFY_REASON defines
(David Laight)

- Add __counted_by_ptr attribute, tests, and first user (Bill
Wendling, Kees Cook)

- Update MAINTAINERS file to make hardening section not include
pstore"

* tag 'hardening-v7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
MAINTAINERS: pstore: Remove L: entry
nfp: tls: Avoid -Wflex-array-member-not-at-end warnings
carl9170: Avoid -Wflex-array-member-not-at-end warning
coredump: Use __counted_by_ptr for struct core_name::corename
lkdtm/bugs: Add __counted_by_ptr() test PTR_BOUNDS
compiler_types.h: Attributes: Add __counted_by_ptr macro
fortify: Cleanup temp file also on non-successful exit
fortify: Rename temporary file to match ignore pattern
fortify: Use C arithmetic not FIELD_xxx() in FORTIFY_REASON defines
ecryptfs: Annotate struct ecryptfs_message with __counted_by
fs/xattr: Annotate struct simple_xattr with __counted_by
crypto: af_alg - Annotate struct af_alg_iv with __counted_by
Kconfig.ubsan: Remove CONFIG_UBSAN_REPORT_FULL from documentation
drm/nouveau: fifo: Avoid -Wflex-array-member-not-at-end warning

+161 -44
-1
MAINTAINERS
··· 20996 20996 M: Kees Cook <kees@kernel.org> 20997 20997 R: Tony Luck <tony.luck@intel.com> 20998 20998 R: Guilherme G. Piccoli <gpiccoli@igalia.com> 20999 - L: linux-hardening@vger.kernel.org 21000 20999 S: Supported 21001 21000 T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore 21002 21001 F: Documentation/admin-guide/pstore-blk.rst
+6
Makefile
··· 952 952 endif 953 953 endif 954 954 955 + ifdef CONFIG_CC_IS_CLANG 956 + ifdef CONFIG_CC_HAS_COUNTED_BY_PTR 957 + KBUILD_CFLAGS += -fexperimental-late-parse-attributes 958 + endif 959 + endif 960 + 955 961 # Explicitly clear padding bits during variable initialization 956 962 KBUILD_CFLAGS += $(call cc-option,-fzero-init-padding-bits=all) 957 963
+2 -3
drivers/gpu/drm/nouveau/nvif/fifo.c
··· 25 25 nvif_fifo_runlists(struct nvif_device *device) 26 26 { 27 27 struct nvif_object *object = &device->object; 28 - struct { 29 - struct nv_device_info_v1 m; 28 + TRAILING_OVERLAP(struct nv_device_info_v1, m, data, 30 29 struct { 31 30 struct nv_device_info_v1_data runlists; 32 31 struct nv_device_info_v1_data runlist[64]; 33 32 } v; 34 - } *a; 33 + ) *a; 35 34 int ret, i; 36 35 37 36 if (device->runlist)
+82 -8
drivers/misc/lkdtm/bugs.c
··· 465 465 pr_expected_config(CONFIG_UBSAN_BOUNDS); 466 466 } 467 467 468 - struct lkdtm_annotated { 468 + struct lkdtm_cb_fam { 469 469 unsigned long flags; 470 470 int count; 471 471 int array[] __counted_by(count); 472 472 }; 473 473 474 - static volatile int fam_count = 4; 474 + static volatile int element_count = 4; 475 475 476 476 static void lkdtm_FAM_BOUNDS(void) 477 477 { 478 - struct lkdtm_annotated *inst; 478 + struct lkdtm_cb_fam *inst; 479 479 480 - inst = kzalloc(struct_size(inst, array, fam_count + 1), GFP_KERNEL); 480 + inst = kzalloc(struct_size(inst, array, element_count + 1), GFP_KERNEL); 481 481 if (!inst) { 482 482 pr_err("FAIL: could not allocate test struct!\n"); 483 483 return; 484 484 } 485 485 486 - inst->count = fam_count; 486 + inst->count = element_count; 487 487 pr_info("Array access within bounds ...\n"); 488 - inst->array[1] = fam_count; 488 + inst->array[1] = element_count; 489 489 ignored = inst->array[1]; 490 490 491 491 pr_info("Array access beyond bounds ...\n"); 492 - inst->array[fam_count] = fam_count; 493 - ignored = inst->array[fam_count]; 492 + inst->array[element_count] = element_count; 493 + ignored = inst->array[element_count]; 494 494 495 495 kfree(inst); 496 496 ··· 498 498 499 499 if (!IS_ENABLED(CONFIG_CC_HAS_COUNTED_BY)) 500 500 pr_warn("This is expected since this %s was built with a compiler that does not support __counted_by\n", 501 + lkdtm_kernel_info); 502 + else if (IS_ENABLED(CONFIG_UBSAN_BOUNDS)) 503 + pr_expected_config(CONFIG_UBSAN_TRAP); 504 + else 505 + pr_expected_config(CONFIG_UBSAN_BOUNDS); 506 + } 507 + 508 + struct lkdtm_extra { 509 + short a, b; 510 + u16 sixteen; 511 + u32 bigger; 512 + u64 biggest; 513 + }; 514 + 515 + struct lkdtm_cb_ptr { 516 + int a, b, c; 517 + int nr_extra; 518 + char *buf __counted_by_ptr(len); 519 + size_t len; 520 + struct lkdtm_extra *extra __counted_by_ptr(nr_extra); 521 + }; 522 + 523 + static noinline void check_ptr_len(struct lkdtm_cb_ptr *p, size_t len) 524 + { 525 + if (__member_size(p->buf) != len) 526 + pr_err("FAIL: could not determine size of inst->buf: %zu\n", 527 + __member_size(p->buf)); 528 + else 529 + pr_info("good: inst->buf length is %zu\n", len); 530 + } 531 + 532 + static void lkdtm_PTR_BOUNDS(void) 533 + { 534 + struct lkdtm_cb_ptr *inst; 535 + 536 + inst = kzalloc(sizeof(*inst), GFP_KERNEL); 537 + if (!inst) { 538 + pr_err("FAIL: could not allocate struct lkdtm_cb_ptr!\n"); 539 + return; 540 + } 541 + 542 + inst->buf = kzalloc(element_count, GFP_KERNEL); 543 + if (!inst->buf) { 544 + pr_err("FAIL: could not allocate inst->buf!\n"); 545 + return; 546 + } 547 + inst->len = element_count; 548 + 549 + /* Double element_count */ 550 + inst->extra = kcalloc(element_count * 2, sizeof(*inst->extra), GFP_KERNEL); 551 + inst->nr_extra = element_count * 2; 552 + 553 + pr_info("Pointer access within bounds ...\n"); 554 + check_ptr_len(inst, 4); 555 + /* All 4 bytes */ 556 + inst->buf[0] = 'A'; 557 + inst->buf[1] = 'B'; 558 + inst->buf[2] = 'C'; 559 + inst->buf[3] = 'D'; 560 + /* Halfway into the array */ 561 + inst->extra[element_count].biggest = 0x1000; 562 + 563 + pr_info("Pointer access beyond bounds ...\n"); 564 + ignored = inst->extra[inst->nr_extra].b; 565 + 566 + kfree(inst->extra); 567 + kfree(inst->buf); 568 + kfree(inst); 569 + 570 + pr_err("FAIL: survived access of invalid pointer member offset!\n"); 571 + 572 + if (!IS_ENABLED(CONFIG_CC_HAS_COUNTED_BY_PTR)) 573 + pr_warn("This is expected since this %s was built with a compiler that does not support __counted_by_ptr\n", 501 574 lkdtm_kernel_info); 502 575 else if (IS_ENABLED(CONFIG_UBSAN_BOUNDS)) 503 576 pr_expected_config(CONFIG_UBSAN_TRAP); ··· 842 769 CRASHTYPE(OVERFLOW_UNSIGNED), 843 770 CRASHTYPE(ARRAY_BOUNDS), 844 771 CRASHTYPE(FAM_BOUNDS), 772 + CRASHTYPE(PTR_BOUNDS), 845 773 CRASHTYPE(CORRUPT_LIST_ADD), 846 774 CRASHTYPE(CORRUPT_LIST_DEL), 847 775 CRASHTYPE(STACK_GUARD_PAGE_LEADING),
+15 -9
drivers/net/ethernet/netronome/nfp/crypto/fw.h
··· 32 32 #define NFP_NET_TLS_VLAN_UNUSED 4095 33 33 34 34 struct nfp_crypto_req_add_front { 35 - struct nfp_ccm_hdr hdr; 36 - __be32 ep_id; 37 - u8 resv[3]; 38 - u8 opcode; 39 - u8 key_len; 40 - __be16 ipver_vlan __packed; 41 - u8 l4_proto; 35 + /* New members MUST be added within the struct_group() macro below. */ 36 + struct_group_tagged(nfp_crypto_req_add_front_hdr, __hdr, 37 + struct nfp_ccm_hdr hdr; 38 + __be32 ep_id; 39 + u8 resv[3]; 40 + u8 opcode; 41 + u8 key_len; 42 + __be16 ipver_vlan __packed; 43 + u8 l4_proto; 44 + ); 42 45 #define NFP_NET_TLS_NON_ADDR_KEY_LEN 8 43 46 u8 l3_addrs[]; 44 47 }; 48 + static_assert(offsetof(struct nfp_crypto_req_add_front, l3_addrs) == 49 + sizeof(struct nfp_crypto_req_add_front_hdr), 50 + "struct member likely outside of struct_group_tagged()"); 45 51 46 52 struct nfp_crypto_req_add_back { 47 53 __be16 src_port; ··· 61 55 }; 62 56 63 57 struct nfp_crypto_req_add_v4 { 64 - struct nfp_crypto_req_add_front front; 58 + struct nfp_crypto_req_add_front_hdr front; 65 59 __be32 src_ip; 66 60 __be32 dst_ip; 67 61 struct nfp_crypto_req_add_back back; 68 62 }; 69 63 70 64 struct nfp_crypto_req_add_v6 { 71 - struct nfp_crypto_req_add_front front; 65 + struct nfp_crypto_req_add_front_hdr front; 72 66 __be32 src_ip[4]; 73 67 __be32 dst_ip[4]; 74 68 struct nfp_crypto_req_add_back back;
+6 -2
drivers/net/ethernet/netronome/nfp/crypto/tls.c
··· 180 180 req->front.key_len += sizeof(__be32) * 2; 181 181 182 182 if (direction == TLS_OFFLOAD_CTX_DIR_TX) { 183 - nfp_net_tls_assign_conn_id(nn, &req->front); 183 + nfp_net_tls_assign_conn_id(nn, 184 + container_of(&req->front, 185 + struct nfp_crypto_req_add_front, __hdr)); 184 186 } else { 185 187 req->src_ip = inet->inet_daddr; 186 188 req->dst_ip = inet->inet_saddr; ··· 201 199 req->front.key_len += sizeof(struct in6_addr) * 2; 202 200 203 201 if (direction == TLS_OFFLOAD_CTX_DIR_TX) { 204 - nfp_net_tls_assign_conn_id(nn, &req->front); 202 + nfp_net_tls_assign_conn_id(nn, 203 + container_of(&req->front, 204 + struct nfp_crypto_req_add_front, __hdr)); 205 205 } else { 206 206 memcpy(req->src_ip, &sk->sk_v6_daddr, sizeof(req->src_ip)); 207 207 memcpy(req->dst_ip, &np->saddr, sizeof(req->dst_ip));
+7 -5
drivers/net/wireless/ath/carl9170/carl9170.h
··· 375 375 u8 *readbuf; 376 376 spinlock_t cmd_lock; 377 377 struct completion cmd_wait; 378 - union { 379 - __le32 cmd_buf[PAYLOAD_MAX + 1]; 380 - struct carl9170_cmd cmd; 381 - struct carl9170_rsp rsp; 382 - }; 383 378 384 379 /* statistics */ 385 380 unsigned int tx_dropped; ··· 458 463 unsigned int cache_idx; 459 464 } rng; 460 465 #endif /* CONFIG_CARL9170_HWRNG */ 466 + 467 + /* Must be last as it ends in a flexible-array member. */ 468 + union { 469 + __le32 cmd_buf[PAYLOAD_MAX + 1]; 470 + struct carl9170_cmd cmd; 471 + struct carl9170_rsp rsp; 472 + }; 461 473 }; 462 474 463 475 enum carl9170_ps_off_override_reasons {
+4 -4
fs/coredump.c
··· 92 92 }; 93 93 94 94 struct core_name { 95 - char *corename; 95 + char *corename __counted_by_ptr(size); 96 96 int used, size; 97 97 unsigned int core_pipe_limit; 98 98 bool core_dumped; ··· 106 106 107 107 size = kmalloc_size_roundup(size); 108 108 corename = krealloc(cn->corename, size, GFP_KERNEL); 109 - 110 109 if (!corename) 111 110 return -ENOMEM; 111 + 112 + cn->corename = corename; 113 + cn->size = size; 112 114 113 115 if (size > core_name_size) /* racy but harmless */ 114 116 core_name_size = size; 115 117 116 - cn->size = size; 117 - cn->corename = corename; 118 118 return 0; 119 119 } 120 120
+1 -1
fs/ecryptfs/ecryptfs_kernel.h
··· 359 359 /* Inherits from msg_ctx->index */ 360 360 u32 index; 361 361 u32 data_len; 362 - u8 data[]; 362 + u8 data[] __counted_by(data_len); 363 363 }; 364 364 365 365 struct ecryptfs_msg_ctx {
+17 -1
include/linux/compiler_types.h
··· 369 369 * Optional: only supported since clang >= 18 370 370 * 371 371 * gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896 372 - * clang: https://github.com/llvm/llvm-project/pull/76348 372 + * clang: https://clang.llvm.org/docs/AttributeReference.html#counted-by-counted-by-or-null-sized-by-sized-by-or-null 373 373 * 374 374 * __bdos on clang < 19.1.2 can erroneously return 0: 375 375 * https://github.com/llvm/llvm-project/pull/110497 ··· 381 381 # define __counted_by(member) __attribute__((__counted_by__(member))) 382 382 #else 383 383 # define __counted_by(member) 384 + #endif 385 + 386 + /* 387 + * Runtime track number of objects pointed to by a pointer member for use by 388 + * CONFIG_FORTIFY_SOURCE and CONFIG_UBSAN_BOUNDS. 389 + * 390 + * Optional: only supported since gcc >= 16 391 + * Optional: only supported since clang >= 22 392 + * 393 + * gcc: https://gcc.gnu.org/pipermail/gcc-patches/2025-April/681727.html 394 + * clang: https://clang.llvm.org/docs/AttributeReference.html#counted-by-counted-by-or-null-sized-by-sized-by-or-null 395 + */ 396 + #ifdef CONFIG_CC_HAS_COUNTED_BY_PTR 397 + #define __counted_by_ptr(member) __attribute__((__counted_by__(member))) 398 + #else 399 + #define __counted_by_ptr(member) 384 400 #endif 385 401 386 402 /*
+3 -5
include/linux/fortify-string.h
··· 2 2 #ifndef _LINUX_FORTIFY_STRING_H_ 3 3 #define _LINUX_FORTIFY_STRING_H_ 4 4 5 - #include <linux/bitfield.h> 6 5 #include <linux/bug.h> 7 6 #include <linux/const.h> 8 7 #include <linux/limits.h> ··· 9 10 #define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable 10 11 #define __RENAME(x) __asm__(#x) 11 12 12 - #define FORTIFY_REASON_DIR(r) FIELD_GET(BIT(0), r) 13 - #define FORTIFY_REASON_FUNC(r) FIELD_GET(GENMASK(7, 1), r) 14 - #define FORTIFY_REASON(func, write) (FIELD_PREP(BIT(0), write) | \ 15 - FIELD_PREP(GENMASK(7, 1), func)) 13 + #define FORTIFY_REASON_DIR(r) ((r) & 1) 14 + #define FORTIFY_REASON_FUNC(r) ((r) >> 1) 15 + #define FORTIFY_REASON(func, write) ((func) << 1 | (write)) 16 16 17 17 /* Overridden by KUnit tests. */ 18 18 #ifndef fortify_panic
+1 -1
include/linux/xattr.h
··· 114 114 struct rb_node rb_node; 115 115 char *name; 116 116 size_t size; 117 - char value[]; 117 + char value[] __counted_by(size); 118 118 }; 119 119 120 120 void simple_xattrs_init(struct simple_xattrs *xattrs);
+1 -1
include/uapi/linux/if_alg.h
··· 42 42 43 43 struct af_alg_iv { 44 44 __u32 ivlen; 45 - __u8 iv[]; 45 + __u8 iv[] __counted_by(ivlen); 46 46 }; 47 47 48 48 /* Socket options */
+4
include/uapi/linux/stddef.h
··· 72 72 #define __counted_by_be(m) 73 73 #endif 74 74 75 + #ifndef __counted_by_ptr 76 + #define __counted_by_ptr(m) 77 + #endif 78 + 75 79 #ifdef __KERNEL__ 76 80 #define __kernel_nonstring __nonstring 77 81 #else
+7
init/Kconfig
··· 143 143 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896 144 144 default y if CC_IS_GCC && GCC_VERSION >= 150100 145 145 146 + config CC_HAS_COUNTED_BY_PTR 147 + bool 148 + # supported since clang 22 149 + default y if CC_IS_CLANG && CLANG_VERSION >= 220000 150 + # supported since gcc 16.0.0 151 + default y if CC_IS_GCC && GCC_VERSION >= 160000 152 + 146 153 config CC_HAS_MULTIDIMENSIONAL_NONSTRING 147 154 def_bool $(success,echo 'char tag[][4] __attribute__((__nonstring__)) = { };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror) 148 155
+1 -1
lib/Kconfig.ubsan
··· 104 104 This option enables -fsanitize=integer-divide-by-zero which checks 105 105 for integer division by zero. This is effectively redundant with the 106 106 kernel's existing exception handling, though it can provide greater 107 - debugging information under CONFIG_UBSAN_REPORT_FULL. 107 + debugging information. 108 108 109 109 config UBSAN_UNREACHABLE 110 110 bool "Perform checking for unreachable code"
+2 -2
lib/test_fortify/test_fortify.sh
··· 17 17 # Argument 2: Where to write the build log. 18 18 OUT="$1" 19 19 shift 20 - TMP="${OUT}.tmp" 20 + TMP="${OUT%/*}/.${OUT##*/}.tmp" 21 21 22 22 # Argument 3: Path to "nm" tool. 23 23 NM="$1" ··· 29 29 __cleanup() { 30 30 rm -f "$TMP" 31 31 } 32 - trap __cleanup EXIT 32 + trap __cleanup EXIT HUP INT QUIT TERM 33 33 34 34 # Function names in warnings are wrapped in backticks under UTF-8 locales. 35 35 # Run the commands with LANG=C so that grep output will not change.
+2
tools/testing/selftests/lkdtm/tests.txt
··· 11 11 #CORRUPT_STACK Crashes entire system on success 12 12 #CORRUPT_STACK_STRONG Crashes entire system on success 13 13 ARRAY_BOUNDS call trace:|UBSAN: array-index-out-of-bounds 14 + FAM_BOUNDS call trace:|UBSAN: array-index-out-of-bounds 15 + PTR_BOUNDS call trace:|UBSAN: array-index-out-of-bounds 14 16 CORRUPT_LIST_ADD list_add corruption 15 17 CORRUPT_LIST_DEL list_del corruption 16 18 STACK_GUARD_PAGE_LEADING