Skip to content

Commit 85f24b0

Browse files
committed
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
2 parents bffce9b + 44dd7cf commit 85f24b0

18 files changed

Lines changed: 161 additions & 44 deletions

File tree

MAINTAINERS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20996,7 +20996,6 @@ PSTORE FILESYSTEM
2099620996
M: Kees Cook <kees@kernel.org>
2099720997
R: Tony Luck <tony.luck@intel.com>
2099820998
R: Guilherme G. Piccoli <gpiccoli@igalia.com>
20999-
L: linux-hardening@vger.kernel.org
2100020999
S: Supported
2100121000
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore
2100221001
F: Documentation/admin-guide/pstore-blk.rst

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,12 @@ KBUILD_CFLAGS += $(CC_AUTO_VAR_INIT_ZERO_ENABLER)
952952
endif
953953
endif
954954

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+
955961
# Explicitly clear padding bits during variable initialization
956962
KBUILD_CFLAGS += $(call cc-option,-fzero-init-padding-bits=all)
957963

drivers/gpu/drm/nouveau/nvif/fifo.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,12 @@ static int
2525
nvif_fifo_runlists(struct nvif_device *device)
2626
{
2727
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,
3029
struct {
3130
struct nv_device_info_v1_data runlists;
3231
struct nv_device_info_v1_data runlist[64];
3332
} v;
34-
} *a;
33+
) *a;
3534
int ret, i;
3635

3736
if (device->runlist)

drivers/misc/lkdtm/bugs.c

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -465,32 +465,32 @@ static void lkdtm_ARRAY_BOUNDS(void)
465465
pr_expected_config(CONFIG_UBSAN_BOUNDS);
466466
}
467467

468-
struct lkdtm_annotated {
468+
struct lkdtm_cb_fam {
469469
unsigned long flags;
470470
int count;
471471
int array[] __counted_by(count);
472472
};
473473

474-
static volatile int fam_count = 4;
474+
static volatile int element_count = 4;
475475

476476
static void lkdtm_FAM_BOUNDS(void)
477477
{
478-
struct lkdtm_annotated *inst;
478+
struct lkdtm_cb_fam *inst;
479479

480-
inst = kzalloc(struct_size(inst, array, fam_count + 1), GFP_KERNEL);
480+
inst = kzalloc(struct_size(inst, array, element_count + 1), GFP_KERNEL);
481481
if (!inst) {
482482
pr_err("FAIL: could not allocate test struct!\n");
483483
return;
484484
}
485485

486-
inst->count = fam_count;
486+
inst->count = element_count;
487487
pr_info("Array access within bounds ...\n");
488-
inst->array[1] = fam_count;
488+
inst->array[1] = element_count;
489489
ignored = inst->array[1];
490490

491491
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];
494494

495495
kfree(inst);
496496

@@ -505,6 +505,79 @@ static void lkdtm_FAM_BOUNDS(void)
505505
pr_expected_config(CONFIG_UBSAN_BOUNDS);
506506
}
507507

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",
574+
lkdtm_kernel_info);
575+
else if (IS_ENABLED(CONFIG_UBSAN_BOUNDS))
576+
pr_expected_config(CONFIG_UBSAN_TRAP);
577+
else
578+
pr_expected_config(CONFIG_UBSAN_BOUNDS);
579+
}
580+
508581
static void lkdtm_CORRUPT_LIST_ADD(void)
509582
{
510583
/*
@@ -769,6 +842,7 @@ static struct crashtype crashtypes[] = {
769842
CRASHTYPE(OVERFLOW_UNSIGNED),
770843
CRASHTYPE(ARRAY_BOUNDS),
771844
CRASHTYPE(FAM_BOUNDS),
845+
CRASHTYPE(PTR_BOUNDS),
772846
CRASHTYPE(CORRUPT_LIST_ADD),
773847
CRASHTYPE(CORRUPT_LIST_DEL),
774848
CRASHTYPE(STACK_GUARD_PAGE_LEADING),

drivers/net/ethernet/netronome/nfp/crypto/fw.h

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,22 @@ struct nfp_crypto_req_reset {
3232
#define NFP_NET_TLS_VLAN_UNUSED 4095
3333

3434
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+
);
4245
#define NFP_NET_TLS_NON_ADDR_KEY_LEN 8
4346
u8 l3_addrs[];
4447
};
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()");
4551

4652
struct nfp_crypto_req_add_back {
4753
__be16 src_port;
@@ -55,14 +61,14 @@ struct nfp_crypto_req_add_back {
5561
};
5662

5763
struct nfp_crypto_req_add_v4 {
58-
struct nfp_crypto_req_add_front front;
64+
struct nfp_crypto_req_add_front_hdr front;
5965
__be32 src_ip;
6066
__be32 dst_ip;
6167
struct nfp_crypto_req_add_back back;
6268
};
6369

6470
struct nfp_crypto_req_add_v6 {
65-
struct nfp_crypto_req_add_front front;
71+
struct nfp_crypto_req_add_front_hdr front;
6672
__be32 src_ip[4];
6773
__be32 dst_ip[4];
6874
struct nfp_crypto_req_add_back back;

drivers/net/ethernet/netronome/nfp/crypto/tls.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,9 @@ nfp_net_tls_set_ipv4(struct nfp_net *nn, struct nfp_crypto_req_add_v4 *req,
180180
req->front.key_len += sizeof(__be32) * 2;
181181

182182
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));
184186
} else {
185187
req->src_ip = inet->inet_daddr;
186188
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,
199201
req->front.key_len += sizeof(struct in6_addr) * 2;
200202

201203
if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
202-
nfp_net_tls_assign_conn_id(nn, &req->front);
204+
nfp_net_tls_assign_conn_id(nn,
205+
container_of(&req->front,
206+
struct nfp_crypto_req_add_front, __hdr));
203207
} else {
204208
memcpy(req->src_ip, &sk->sk_v6_daddr, sizeof(req->src_ip));
205209
memcpy(req->dst_ip, &np->saddr, sizeof(req->dst_ip));

drivers/net/wireless/ath/carl9170/carl9170.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -375,11 +375,6 @@ struct ar9170 {
375375
u8 *readbuf;
376376
spinlock_t cmd_lock;
377377
struct completion cmd_wait;
378-
union {
379-
__le32 cmd_buf[PAYLOAD_MAX + 1];
380-
struct carl9170_cmd cmd;
381-
struct carl9170_rsp rsp;
382-
};
383378

384379
/* statistics */
385380
unsigned int tx_dropped;
@@ -463,6 +458,13 @@ struct ar9170 {
463458
unsigned int cache_idx;
464459
} rng;
465460
#endif /* CONFIG_CARL9170_HWRNG */
461+
462+
/* Must be last as it ends in a flexible-array member. */
463+
union {
464+
__le32 cmd_buf[PAYLOAD_MAX + 1];
465+
struct carl9170_cmd cmd;
466+
struct carl9170_rsp rsp;
467+
};
466468
};
467469

468470
enum carl9170_ps_off_override_reasons {

fs/coredump.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ enum coredump_type_t {
9292
};
9393

9494
struct core_name {
95-
char *corename;
95+
char *corename __counted_by_ptr(size);
9696
int used, size;
9797
unsigned int core_pipe_limit;
9898
bool core_dumped;
@@ -106,15 +106,15 @@ static int expand_corename(struct core_name *cn, int size)
106106

107107
size = kmalloc_size_roundup(size);
108108
corename = krealloc(cn->corename, size, GFP_KERNEL);
109-
110109
if (!corename)
111110
return -ENOMEM;
112111

112+
cn->corename = corename;
113+
cn->size = size;
114+
113115
if (size > core_name_size) /* racy but harmless */
114116
core_name_size = size;
115117

116-
cn->size = size;
117-
cn->corename = corename;
118118
return 0;
119119
}
120120

fs/ecryptfs/ecryptfs_kernel.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ struct ecryptfs_message {
359359
/* Inherits from msg_ctx->index */
360360
u32 index;
361361
u32 data_len;
362-
u8 data[];
362+
u8 data[] __counted_by(data_len);
363363
};
364364

365365
struct ecryptfs_msg_ctx {

include/linux/compiler_types.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ struct ftrace_likely_data {
369369
* Optional: only supported since clang >= 18
370370
*
371371
* 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
373373
*
374374
* __bdos on clang < 19.1.2 can erroneously return 0:
375375
* https://github.com/llvm/llvm-project/pull/110497
@@ -383,6 +383,22 @@ struct ftrace_likely_data {
383383
# define __counted_by(member)
384384
#endif
385385

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)
400+
#endif
401+
386402
/*
387403
* Optional: only supported since gcc >= 15
388404
* Optional: not supported by Clang

0 commit comments

Comments
 (0)