diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-10 08:54:13 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-10 08:54:13 -0800 |
| commit | 85f24b0ace9aa79142f632fc3ccc730a8d2a4a28 (patch) | |
| tree | 29cd3fd0b191f3de84af9f5700823cc135f0b824 /drivers | |
| parent | bffce9b427b37e2f54416a695ec5d7f030ba610f (diff) | |
| parent | 44dd7cfbd1db5199cf7afe03158a578a64b55800 (diff) | |
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
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nvif/fifo.c | 5 | ||||
| -rw-r--r-- | drivers/misc/lkdtm/bugs.c | 90 | ||||
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/crypto/fw.h | 24 | ||||
| -rw-r--r-- | drivers/net/ethernet/netronome/nfp/crypto/tls.c | 8 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/carl9170.h | 12 |
5 files changed, 112 insertions, 27 deletions
diff --git a/drivers/gpu/drm/nouveau/nvif/fifo.c b/drivers/gpu/drm/nouveau/nvif/fifo.c index a463289962b2..b0ab80995d98 100644 --- a/drivers/gpu/drm/nouveau/nvif/fifo.c +++ b/drivers/gpu/drm/nouveau/nvif/fifo.c @@ -25,13 +25,12 @@ static int nvif_fifo_runlists(struct nvif_device *device) { struct nvif_object *object = &device->object; - struct { - struct nv_device_info_v1 m; + TRAILING_OVERLAP(struct nv_device_info_v1, m, data, struct { struct nv_device_info_v1_data runlists; struct nv_device_info_v1_data runlist[64]; } v; - } *a; + ) *a; int ret, i; if (device->runlist) diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c index 502059078b45..b2aee36b956d 100644 --- a/drivers/misc/lkdtm/bugs.c +++ b/drivers/misc/lkdtm/bugs.c @@ -465,32 +465,32 @@ static void lkdtm_ARRAY_BOUNDS(void) pr_expected_config(CONFIG_UBSAN_BOUNDS); } -struct lkdtm_annotated { +struct lkdtm_cb_fam { unsigned long flags; int count; int array[] __counted_by(count); }; -static volatile int fam_count = 4; +static volatile int element_count = 4; static void lkdtm_FAM_BOUNDS(void) { - struct lkdtm_annotated *inst; + struct lkdtm_cb_fam *inst; - inst = kzalloc(struct_size(inst, array, fam_count + 1), GFP_KERNEL); + inst = kzalloc(struct_size(inst, array, element_count + 1), GFP_KERNEL); if (!inst) { pr_err("FAIL: could not allocate test struct!\n"); return; } - inst->count = fam_count; + inst->count = element_count; pr_info("Array access within bounds ...\n"); - inst->array[1] = fam_count; + inst->array[1] = element_count; ignored = inst->array[1]; pr_info("Array access beyond bounds ...\n"); - inst->array[fam_count] = fam_count; - ignored = inst->array[fam_count]; + inst->array[element_count] = element_count; + ignored = inst->array[element_count]; kfree(inst); @@ -505,6 +505,79 @@ static void lkdtm_FAM_BOUNDS(void) pr_expected_config(CONFIG_UBSAN_BOUNDS); } +struct lkdtm_extra { + short a, b; + u16 sixteen; + u32 bigger; + u64 biggest; +}; + +struct lkdtm_cb_ptr { + int a, b, c; + int nr_extra; + char *buf __counted_by_ptr(len); + size_t len; + struct lkdtm_extra *extra __counted_by_ptr(nr_extra); +}; + +static noinline void check_ptr_len(struct lkdtm_cb_ptr *p, size_t len) +{ + if (__member_size(p->buf) != len) + pr_err("FAIL: could not determine size of inst->buf: %zu\n", + __member_size(p->buf)); + else + pr_info("good: inst->buf length is %zu\n", len); +} + +static void lkdtm_PTR_BOUNDS(void) +{ + struct lkdtm_cb_ptr *inst; + + inst = kzalloc(sizeof(*inst), GFP_KERNEL); + if (!inst) { + pr_err("FAIL: could not allocate struct lkdtm_cb_ptr!\n"); + return; + } + + inst->buf = kzalloc(element_count, GFP_KERNEL); + if (!inst->buf) { + pr_err("FAIL: could not allocate inst->buf!\n"); + return; + } + inst->len = element_count; + + /* Double element_count */ + inst->extra = kcalloc(element_count * 2, sizeof(*inst->extra), GFP_KERNEL); + inst->nr_extra = element_count * 2; + + pr_info("Pointer access within bounds ...\n"); + check_ptr_len(inst, 4); + /* All 4 bytes */ + inst->buf[0] = 'A'; + inst->buf[1] = 'B'; + inst->buf[2] = 'C'; + inst->buf[3] = 'D'; + /* Halfway into the array */ + inst->extra[element_count].biggest = 0x1000; + + pr_info("Pointer access beyond bounds ...\n"); + ignored = inst->extra[inst->nr_extra].b; + + kfree(inst->extra); + kfree(inst->buf); + kfree(inst); + + pr_err("FAIL: survived access of invalid pointer member offset!\n"); + + if (!IS_ENABLED(CONFIG_CC_HAS_COUNTED_BY_PTR)) + pr_warn("This is expected since this %s was built with a compiler that does not support __counted_by_ptr\n", + lkdtm_kernel_info); + else if (IS_ENABLED(CONFIG_UBSAN_BOUNDS)) + pr_expected_config(CONFIG_UBSAN_TRAP); + else + pr_expected_config(CONFIG_UBSAN_BOUNDS); +} + static void lkdtm_CORRUPT_LIST_ADD(void) { /* @@ -769,6 +842,7 @@ static struct crashtype crashtypes[] = { CRASHTYPE(OVERFLOW_UNSIGNED), CRASHTYPE(ARRAY_BOUNDS), CRASHTYPE(FAM_BOUNDS), + CRASHTYPE(PTR_BOUNDS), CRASHTYPE(CORRUPT_LIST_ADD), CRASHTYPE(CORRUPT_LIST_DEL), CRASHTYPE(STACK_GUARD_PAGE_LEADING), diff --git a/drivers/net/ethernet/netronome/nfp/crypto/fw.h b/drivers/net/ethernet/netronome/nfp/crypto/fw.h index dcb67c2b5e5e..1e869599febb 100644 --- a/drivers/net/ethernet/netronome/nfp/crypto/fw.h +++ b/drivers/net/ethernet/netronome/nfp/crypto/fw.h @@ -32,16 +32,22 @@ struct nfp_crypto_req_reset { #define NFP_NET_TLS_VLAN_UNUSED 4095 struct nfp_crypto_req_add_front { - struct nfp_ccm_hdr hdr; - __be32 ep_id; - u8 resv[3]; - u8 opcode; - u8 key_len; - __be16 ipver_vlan __packed; - u8 l4_proto; + /* New members MUST be added within the struct_group() macro below. */ + struct_group_tagged(nfp_crypto_req_add_front_hdr, __hdr, + struct nfp_ccm_hdr hdr; + __be32 ep_id; + u8 resv[3]; + u8 opcode; + u8 key_len; + __be16 ipver_vlan __packed; + u8 l4_proto; + ); #define NFP_NET_TLS_NON_ADDR_KEY_LEN 8 u8 l3_addrs[]; }; +static_assert(offsetof(struct nfp_crypto_req_add_front, l3_addrs) == + sizeof(struct nfp_crypto_req_add_front_hdr), + "struct member likely outside of struct_group_tagged()"); struct nfp_crypto_req_add_back { __be16 src_port; @@ -55,14 +61,14 @@ struct nfp_crypto_req_add_back { }; struct nfp_crypto_req_add_v4 { - struct nfp_crypto_req_add_front front; + struct nfp_crypto_req_add_front_hdr front; __be32 src_ip; __be32 dst_ip; struct nfp_crypto_req_add_back back; }; struct nfp_crypto_req_add_v6 { - struct nfp_crypto_req_add_front front; + struct nfp_crypto_req_add_front_hdr front; __be32 src_ip[4]; __be32 dst_ip[4]; struct nfp_crypto_req_add_back back; diff --git a/drivers/net/ethernet/netronome/nfp/crypto/tls.c b/drivers/net/ethernet/netronome/nfp/crypto/tls.c index f252ecdcd2cd..9983d7aa2b9c 100644 --- a/drivers/net/ethernet/netronome/nfp/crypto/tls.c +++ b/drivers/net/ethernet/netronome/nfp/crypto/tls.c @@ -180,7 +180,9 @@ nfp_net_tls_set_ipv4(struct nfp_net *nn, struct nfp_crypto_req_add_v4 *req, req->front.key_len += sizeof(__be32) * 2; if (direction == TLS_OFFLOAD_CTX_DIR_TX) { - nfp_net_tls_assign_conn_id(nn, &req->front); + nfp_net_tls_assign_conn_id(nn, + container_of(&req->front, + struct nfp_crypto_req_add_front, __hdr)); } else { req->src_ip = inet->inet_daddr; req->dst_ip = inet->inet_saddr; @@ -199,7 +201,9 @@ nfp_net_tls_set_ipv6(struct nfp_net *nn, struct nfp_crypto_req_add_v6 *req, req->front.key_len += sizeof(struct in6_addr) * 2; if (direction == TLS_OFFLOAD_CTX_DIR_TX) { - nfp_net_tls_assign_conn_id(nn, &req->front); + nfp_net_tls_assign_conn_id(nn, + container_of(&req->front, + struct nfp_crypto_req_add_front, __hdr)); } else { memcpy(req->src_ip, &sk->sk_v6_daddr, sizeof(req->src_ip)); memcpy(req->dst_ip, &np->saddr, sizeof(req->dst_ip)); diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index ba29b4aebe9f..b13685e22a0d 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -375,11 +375,6 @@ struct ar9170 { u8 *readbuf; spinlock_t cmd_lock; struct completion cmd_wait; - union { - __le32 cmd_buf[PAYLOAD_MAX + 1]; - struct carl9170_cmd cmd; - struct carl9170_rsp rsp; - }; /* statistics */ unsigned int tx_dropped; @@ -463,6 +458,13 @@ struct ar9170 { unsigned int cache_idx; } rng; #endif /* CONFIG_CARL9170_HWRNG */ + + /* Must be last as it ends in a flexible-array member. */ + union { + __le32 cmd_buf[PAYLOAD_MAX + 1]; + struct carl9170_cmd cmd; + struct carl9170_rsp rsp; + }; }; enum carl9170_ps_off_override_reasons { |
