* [PATCH v6 0/5] asdf
@ 2025-12-03 23:30 Kees Cook
2025-12-03 23:30 ` [PATCH v6 1/5] slab: Introduce kmalloc_obj() and family Kees Cook
` (5 more replies)
0 siblings, 6 replies; 9+ messages in thread
From: Kees Cook @ 2025-12-03 23:30 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Kees Cook, Linus Torvalds, Randy Dunlap, Miguel Ojeda,
Przemek Kitszel, Gustavo A. R. Silva, Matthew Wilcox,
John Hubbard, Joe Perches, Christoph Lameter, Marco Elver,
Vegard Nossum, Pekka Enberg, David Rientjes, Joonsoo Kim,
Andrew Morton, Roman Gushchin, Harry Yoo, Bill Wendling,
Justin Stitt, Jann Horn, Greg Kroah-Hartman, Sasha Levin,
linux-mm, Nathan Chancellor, Peter Zijlstra, Nick Desaulniers,
Jonathan Corbet, Jakub Kicinski, Yafang Shao, Tony Ambardar,
Alexander Lobakin, Jan Hendrik Farr, Alexander Potapenko,
linux-kernel, linux-hardening, linux-doc, llvm
Hi,
Here's an update for the kmalloc_obj() API proposal based on Linus's
feedback. I normally wouldn't send this during the merge window,
but I wanted to have it updated for discussion at LPC[1] (and here in
email). Please see patches 1 and 4 for the bulk of the details. This is
obviously not v6.19 material! :)
Replacing[2] all existing simple code patterns found via Coccinelle
shows what could be replaced immediately (also saving roughly 1000 lines):
7971 files changed, 19880 insertions(+), 20752 deletions(-)
This would take us from 24515 size-based k*alloc assignments to 7682:
$ git grep ' = kv\?[mzcv]alloc\(\|_array\)(' | wc -l
24515
$ git reset --hard HEAD^
HEAD is now at 8bccc91e6cdf treewide: kmalloc_obj conversion
$ git grep ' = kv\?[mzcv]alloc\(\|_array\)(' | wc -l
7682
This treewide change could be done at the end of the merge window just
before -rc1 is released (as is common for treewide changes). Handling
this API change in backports to -stable should be possible without much
hassle by backporting the __flex_counter() patch and this patch, while
taking conversions as-needed.
The impact on my bootable testing image size (with the treewide patch
applied) is tiny. With both GCC 13 (no __counted_by support) and GCC 15
(with __counted_by) the images are actually very slightly smaller:
$ size -G gcc-boot/vmlinux.gcc*
text data bss total filename
29975593 21527689 16601200 68104482 gcc-boot/vmlinux.gcc13-before
29969263 21528663 16601112 68099038 gcc-boot/vmlinux.gcc13-after
30555626 21291299 17086620 68933545 gcc-boot/vmlinux.gcc15-before
30550144 21292039 17086540 68928723 gcc-boot/vmlinux.gcc15-after
Thanks!
-Kees
[1] https://lpc.events/event/19/contributions/2136/
[2] https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/commit/?h=dev/v6.18-rc6/alloc_obj/v5&id=f79ee96ad6a3cafdb274fe15d3ae067724e72327
v6:
- Drop _sz() helpers and simplify the resulting internals
- Split _flex() helper into its own patch to make review easier
- Explicitly use TYPE within the internals to make things more readable
- Move treewide change details into the cover letter
v5: https://lore.kernel.org/lkml/20251122014258.do.018-kees@kernel.org/
v4: https://lore.kernel.org/lkml/20250315025852.it.568-kees@kernel.org/
v3: https://lore.kernel.org/lkml/20240822231324.make.666-kees@kernel.org/
v2: https://lore.kernel.org/lkml/20240807235433.work.317-kees@kernel.org/
v1: https://lore.kernel.org/lkml/20240719192744.work.264-kees@kernel.org/
Kees Cook (5):
slab: Introduce kmalloc_obj() and family
checkpatch: Suggest kmalloc_obj family for sizeof allocations
compiler_types: Introduce __flex_counter() and family
slab: Introduce kmalloc_flex() and family
coccinelle: Add kmalloc_objs conversion script
scripts/checkpatch.pl | 39 ++++++--
scripts/coccinelle/api/kmalloc_objs.cocci | 109 ++++++++++++++++++++++
Documentation/process/deprecated.rst | 31 ++++++
include/linux/compiler_types.h | 31 ++++++
include/linux/overflow.h | 42 +++++++++
include/linux/slab.h | 106 +++++++++++++++++++++
6 files changed, 352 insertions(+), 6 deletions(-)
create mode 100644 scripts/coccinelle/api/kmalloc_objs.cocci
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v6 1/5] slab: Introduce kmalloc_obj() and family
2025-12-03 23:30 [PATCH v6 0/5] asdf Kees Cook
@ 2025-12-03 23:30 ` Kees Cook
2025-12-03 23:30 ` [PATCH v6 2/5] checkpatch: Suggest kmalloc_obj family for sizeof allocations Kees Cook
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Kees Cook @ 2025-12-03 23:30 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Kees Cook, Christoph Lameter, Pekka Enberg, David Rientjes,
Joonsoo Kim, Andrew Morton, Roman Gushchin, Hyeonggon Yoo,
Gustavo A . R . Silva, Bill Wendling, Justin Stitt, Jann Horn,
Przemek Kitszel, Marco Elver, Linus Torvalds, Greg Kroah-Hartman,
Sasha Levin, linux-mm, Randy Dunlap, Miguel Ojeda,
Matthew Wilcox, John Hubbard, Joe Perches, Vegard Nossum,
Harry Yoo, Nathan Chancellor, Peter Zijlstra, Nick Desaulniers,
Jonathan Corbet, Jakub Kicinski, Yafang Shao, Tony Ambardar,
Alexander Lobakin, Jan Hendrik Farr, Alexander Potapenko,
linux-kernel, linux-hardening, linux-doc, llvm
Introduce type-aware kmalloc-family helpers to replace the common
idioms for single object and arrays of objects allocation:
ptr = kmalloc(sizeof(*ptr), gfp);
ptr = kmalloc(sizeof(struct some_obj_name), gfp);
ptr = kzalloc(sizeof(*ptr), gfp);
ptr = kmalloc_array(count, sizeof(*ptr), gfp);
ptr = kcalloc(count, sizeof(*ptr), gfp);
These become, respectively:
ptr = kmalloc_obj(*ptr, gfp);
ptr = kmalloc_obj(*ptr, gfp);
ptr = kzalloc_obj(*ptr, gfp);
ptr = kmalloc_objs(*ptr, count, gfp);
ptr = kzalloc_objs(*ptr, count, gfp);
Beyond the other benefits outlined below, the primary ergonomic benefit
is the elimination of needing "sizeof" nor the type name, and the
enforcement of assignment types (they do not return "void *", but rather
a pointer to the type of the first argument). The type name _can_ be
used, though, in the case where an assignment is indirect (e.g. via
"return"). This additionally allows[1] variables to be declared via
__auto_type:
__auto_type ptr = kmalloc_obj(struct foo, gfp);
Internal introspection of the allocated type now becomes possible,
allowing for future alignment-aware choices to be made by the allocator
and future hardening work that can be type sensitive. For example,
adding __alignof(*ptr) as an argument to the internal allocators so that
appropriate/efficient alignment choices can be made, or being able to
correctly choose per-allocation offset randomization within a bucket
that does not break alignment requirements.
Link: https://lore.kernel.org/all/CAHk-=wiCOTW5UftUrAnvJkr6769D29tF7Of79gUjdQHS_TkF5A@mail.gmail.com/ [1]
Signed-off-by: Kees Cook <kees@kernel.org>
---
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Hyeonggon Yoo <42.hyeyoo@gmail.com>
Cc: Gustavo A. R. Silva <gustavoars@kernel.org>
Cc: Bill Wendling <morbo@google.com>
Cc: Justin Stitt <justinstitt@google.com>
Cc: Jann Horn <jannh@google.com>
Cc: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Cc: Marco Elver <elver@google.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Sasha Levin <sashal@kernel.org>
Cc: linux-mm@kvack.org
---
Documentation/process/deprecated.rst | 24 ++++++++++++
include/linux/slab.h | 58 ++++++++++++++++++++++++++++
2 files changed, 82 insertions(+)
diff --git a/Documentation/process/deprecated.rst b/Documentation/process/deprecated.rst
index 1f7f3e6c9cda..91c628fa2d59 100644
--- a/Documentation/process/deprecated.rst
+++ b/Documentation/process/deprecated.rst
@@ -372,3 +372,27 @@ The helper must be used::
DECLARE_FLEX_ARRAY(struct type2, two);
};
};
+
+Open-coded kmalloc assignments for struct objects
+-------------------------------------------------
+Performing open-coded kmalloc()-family allocation assignments prevents
+the kernel (and compiler) from being able to examine the type of the
+variable being assigned, which limits any related introspection that
+may help with alignment, wrap-around, or additional hardening. The
+kmalloc_obj()-family of macros provide this introspection, which can be
+used for the common code patterns for single, array, and flexible object
+allocations. For example, these open coded assignments::
+
+ ptr = kmalloc(sizeof(*ptr), gfp);
+ ptr = kzalloc(sizeof(*ptr), gfp);
+ ptr = kmalloc_array(count, sizeof(*ptr), gfp);
+ ptr = kcalloc(count, sizeof(*ptr), gfp);
+ ptr = kmalloc(sizeof(struct foo, gfp);
+
+become, respectively::
+
+ ptr = kmalloc_obj(*ptr, gfp);
+ ptr = kzalloc_obj(*ptr, gfp);
+ ptr = kmalloc_objs(*ptr, count, gfp);
+ ptr = kzalloc_objs(*ptr, count, gfp);
+ __auto_type ptr = kmalloc_obj(struct foo, gfp);
diff --git a/include/linux/slab.h b/include/linux/slab.h
index cf443f064a66..726457daedbd 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -12,6 +12,7 @@
#ifndef _LINUX_SLAB_H
#define _LINUX_SLAB_H
+#include <linux/bug.h>
#include <linux/cache.h>
#include <linux/gfp.h>
#include <linux/overflow.h>
@@ -965,6 +966,63 @@ static __always_inline __alloc_size(1) void *kmalloc_noprof(size_t size, gfp_t f
void *kmalloc_nolock_noprof(size_t size, gfp_t gfp_flags, int node);
#define kmalloc_nolock(...) alloc_hooks(kmalloc_nolock_noprof(__VA_ARGS__))
+/**
+ * __alloc_objs - Allocate objects of a given type using
+ * @KMALLOC: which size-based kmalloc wrapper to allocate with.
+ * @GFP: GFP flags for the allocation.
+ * @TYPE: type to allocate space for.
+ * @COUNT: how many @TYPE objects to allocate.
+ *
+ * Returns: Newly allocated pointer to (first) @TYPE of @COUNT-many
+ * allocated @TYPE objects, or NULL on failure.
+ */
+#define __alloc_objs(KMALLOC, GFP, TYPE, COUNT) \
+({ \
+ const size_t __obj_size = size_mul(sizeof(TYPE), COUNT); \
+ (TYPE *)KMALLOC(__obj_size, GFP); \
+})
+
+/**
+ * kmalloc_obj - Allocate a single instance of the given type
+ * @VAR_OR_TYPE: Variable or type to allocate.
+ * @GFP: GFP flags for the allocation.
+ *
+ * Returns: newly allocated pointer to a @VAR_OR_TYPE on success, or NULL
+ * on failure.
+ */
+#define kmalloc_obj(VAR_OR_TYPE, GFP) \
+ __alloc_objs(kmalloc, GFP, typeof(VAR_OR_TYPE), 1)
+
+/**
+ * kmalloc_objs - Allocate an array of the given type
+ * @VAR_OR_TYPE: Variable or type to allocate an array of.
+ * @COUNT: How many elements in the array.
+ * @FLAGS: GFP flags for the allocation.
+ *
+ * Returns: newly allocated pointer to array of @VAR_OR_TYPE on success,
+ * or NULL on failure.
+ */
+#define kmalloc_objs(VAR_OR_TYPE, COUNT, GFP) \
+ __alloc_objs(kmalloc, GFP, typeof(VAR_OR_TYPE), COUNT)
+
+/* All kzalloc aliases for kmalloc_(obj|objs|flex). */
+#define kzalloc_obj(P, GFP) \
+ __alloc_objs(kzalloc, GFP, typeof(P), 1)
+#define kzalloc_objs(P, COUNT, GFP) \
+ __alloc_objs(kzalloc, GFP, typeof(P), COUNT)
+
+/* All kvmalloc aliases for kmalloc_(obj|objs|flex). */
+#define kvmalloc_obj(P, GFP) \
+ __alloc_objs(kvmalloc, GFP, typeof(P), 1)
+#define kvmalloc_objs(P, COUNT, GFP) \
+ __alloc_objs(kvmalloc, GFP, typeof(P), COUNT)
+
+/* All kvzalloc aliases for kmalloc_(obj|objs|flex). */
+#define kvzalloc_obj(P, GFP) \
+ __alloc_objs(kvzalloc, GFP, typeof(P), 1)
+#define kvzalloc_objs(P, COUNT, GFP) \
+ __alloc_objs(kvzalloc, GFP, typeof(P), COUNT)
+
#define kmem_buckets_alloc(_b, _size, _flags) \
alloc_hooks(__kmalloc_node_noprof(PASS_BUCKET_PARAMS(_size, _b), _flags, NUMA_NO_NODE))
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v6 2/5] checkpatch: Suggest kmalloc_obj family for sizeof allocations
2025-12-03 23:30 [PATCH v6 0/5] asdf Kees Cook
2025-12-03 23:30 ` [PATCH v6 1/5] slab: Introduce kmalloc_obj() and family Kees Cook
@ 2025-12-03 23:30 ` Kees Cook
2025-12-03 23:30 ` [PATCH v6 3/5] compiler_types: Introduce __flex_counter() and family Kees Cook
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Kees Cook @ 2025-12-03 23:30 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Kees Cook, Andy Whitcroft, Joe Perches, Dwaipayan Ray,
Lukas Bulwahn, Linus Torvalds, Randy Dunlap, Miguel Ojeda,
Przemek Kitszel, Gustavo A. R. Silva, Matthew Wilcox,
John Hubbard, Christoph Lameter, Marco Elver, Vegard Nossum,
Pekka Enberg, David Rientjes, Joonsoo Kim, Andrew Morton,
Roman Gushchin, Harry Yoo, Bill Wendling, Justin Stitt,
Jann Horn, Greg Kroah-Hartman, Sasha Levin, linux-mm,
Nathan Chancellor, Peter Zijlstra, Nick Desaulniers,
Jonathan Corbet, Jakub Kicinski, Yafang Shao, Tony Ambardar,
Alexander Lobakin, Jan Hendrik Farr, Alexander Potapenko,
linux-kernel, linux-hardening, linux-doc, llvm
To support shifting away from sized allocation towards typed
allocations, suggest the kmalloc_obj family of macros when a sizeof() is
present in the argument lists.
Signed-off-by: Kees Cook <kees@kernel.org>
---
Cc: Andy Whitcroft <apw@canonical.com>
Cc: Joe Perches <joe@perches.com>
Cc: Dwaipayan Ray <dwaipayanray1@gmail.com>
Cc: Lukas Bulwahn <lukas.bulwahn@gmail.com>
---
scripts/checkpatch.pl | 39 +++++++++++++++++++++++++++++++++------
1 file changed, 33 insertions(+), 6 deletions(-)
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index d58ca9655ab7..a8cdfb502ccc 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -7258,17 +7258,42 @@ sub process {
"Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
}
-# check for (kv|k)[mz]alloc with multiplies that could be kmalloc_array/kvmalloc_array/kvcalloc/kcalloc
+# check for (kv|k)[mz]alloc that could be kmalloc_obj/kvmalloc_obj/kzalloc_obj/kvzalloc_obj
+ if ($perl_version_ok &&
+ defined $stat &&
+ $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*,/) {
+ my $oldfunc = $3;
+ my $a1 = $4;
+ my $newfunc = "kmalloc_obj";
+ $newfunc = "kvmalloc_obj" if ($oldfunc eq "kvmalloc");
+ $newfunc = "kvzalloc_obj" if ($oldfunc eq "kvzalloc");
+ $newfunc = "kzalloc_obj" if ($oldfunc eq "kzalloc");
+
+ if ($a1 =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/) {
+ my $cnt = statement_rawlines($stat);
+ my $herectx = get_stat_here($linenr, $cnt, $here);
+
+ if (WARN("ALLOC_WITH_SIZEOF",
+ "Prefer $newfunc over $oldfunc with sizeof\n" . $herectx) &&
+ $cnt == 1 &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*,/$1 = $newfunc($a1,/;
+ }
+ }
+ }
+
+
+# check for (kv|k)[mz]alloc with multiplies that could be kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs
if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
my $oldfunc = $3;
my $a1 = $4;
my $a2 = $10;
- my $newfunc = "kmalloc_array";
- $newfunc = "kvmalloc_array" if ($oldfunc eq "kvmalloc");
- $newfunc = "kvcalloc" if ($oldfunc eq "kvzalloc");
- $newfunc = "kcalloc" if ($oldfunc eq "kzalloc");
+ my $newfunc = "kmalloc_objs";
+ $newfunc = "kvmalloc_objs" if ($oldfunc eq "kvmalloc");
+ $newfunc = "kvzalloc_objs" if ($oldfunc eq "kvzalloc");
+ $newfunc = "kzalloc_objs" if ($oldfunc eq "kzalloc");
my $r1 = $a1;
my $r2 = $a2;
if ($a1 =~ /^sizeof\s*\S/) {
@@ -7284,7 +7309,9 @@ sub process {
"Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
$cnt == 1 &&
$fix) {
- $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
+ my $sized = trim($r2);
+ $sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;
+ $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . $sized . ', ' . trim($r1)/e;
}
}
}
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v6 3/5] compiler_types: Introduce __flex_counter() and family
2025-12-03 23:30 [PATCH v6 0/5] asdf Kees Cook
2025-12-03 23:30 ` [PATCH v6 1/5] slab: Introduce kmalloc_obj() and family Kees Cook
2025-12-03 23:30 ` [PATCH v6 2/5] checkpatch: Suggest kmalloc_obj family for sizeof allocations Kees Cook
@ 2025-12-03 23:30 ` Kees Cook
2025-12-04 8:54 ` Peter Zijlstra
2025-12-03 23:30 ` [PATCH v6 4/5] slab: Introduce kmalloc_flex() " Kees Cook
` (2 subsequent siblings)
5 siblings, 1 reply; 9+ messages in thread
From: Kees Cook @ 2025-12-03 23:30 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Kees Cook, Miguel Ojeda, Gustavo A. R. Silva, Nathan Chancellor,
Peter Zijlstra, Nick Desaulniers, Marco Elver, Przemek Kitszel,
linux-hardening, Linus Torvalds, Randy Dunlap, Matthew Wilcox,
John Hubbard, Joe Perches, Christoph Lameter, Vegard Nossum,
Pekka Enberg, David Rientjes, Joonsoo Kim, Andrew Morton,
Roman Gushchin, Harry Yoo, Bill Wendling, Justin Stitt,
Jann Horn, Greg Kroah-Hartman, Sasha Levin, linux-mm,
Nick Desaulniers, Jonathan Corbet, Jakub Kicinski, Yafang Shao,
Tony Ambardar, Alexander Lobakin, Jan Hendrik Farr,
Alexander Potapenko, linux-kernel, linux-doc, llvm
Introduce __flex_counter() which wraps __builtin_counted_by_ref(),
as newly introduced by GCC[1] and Clang[2]. Use of __flex_counter()
allows access to the counter member of a struct's flexible array member
when it has been annotated with __counted_by().
Introduce typeof_flex_counter(), overflows_flex_counter_type(), and
__set_flex_counter() to provide the needed _Generic() wrappers to get
sane results out of __flex_counter().
For example, with:
struct foo {
int counter;
short array[] __counted_by(counter);
} *p;
__flex_counter(p->array) will resolve to: &p->counter
typeof_flex_counter(p->array) will resolve to "int". (If p->array was not
annotated, it would resolve to "size_t".)
overflows_flex_counter_type(typeof(*p), array, COUNT) is the same as:
COUNT <= type_max(p->counter) && COUNT >= type_min(p->counter)
(If p->array was not annotated it would return true since everything
fits in size_t.)
__set_flex_counter(p->array, COUNT) is the same as:
p->counter = COUNT;
(It is a no-op if p->array is not annotated with __counted_by().)
Signed-off-by: Kees Cook <kees@kernel.org>
---
Cc: Miguel Ojeda <ojeda@kernel.org>
Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Marco Elver <elver@google.com>
Cc: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Cc: linux-hardening@vger.kernel.org
---
include/linux/compiler_types.h | 31 +++++++++++++++++++++++++
include/linux/overflow.h | 42 ++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+)
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index c46855162a8a..a31fe3dbf576 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -507,6 +507,37 @@ struct ftrace_likely_data {
#define __annotated(var, attr) __builtin_has_attribute(var, attr)
#endif
+/*
+ * Optional: only supported since gcc >= 15, clang >= 19
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fcounted_005fby_005fref
+ * clang: https://clang.llvm.org/docs/LanguageExtensions.html#builtin-counted-by-ref
+ */
+#if __has_builtin(__builtin_counted_by_ref)
+/**
+ * __flex_counter() - Get pointer to counter member for the given
+ * flexible array, if it was annotated with __counted_by()
+ * @FAM: Pointer to flexible array member of an addressable struct instance
+ *
+ * For example, with:
+ *
+ * struct foo {
+ * int counter;
+ * short array[] __counted_by(counter);
+ * } *p;
+ *
+ * __flex_counter(p->array) will resolve to &p->counter.
+ *
+ * Note that Clang may not allow this to be assigned to a separate
+ * variable; it must be used directly.
+ *
+ * If p->array is unannotated, this returns (void *)NULL.
+ */
+#define __flex_counter(FAM) __builtin_counted_by_ref(FAM)
+#else
+#define __flex_counter(FAM) ((void *)NULL)
+#endif
+
/*
* Some versions of gcc do not mark 'asm goto' volatile:
*
diff --git a/include/linux/overflow.h b/include/linux/overflow.h
index 725f95f7e416..f362e155a7ec 100644
--- a/include/linux/overflow.h
+++ b/include/linux/overflow.h
@@ -540,4 +540,46 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
(__member_size((name)->array) / sizeof(*(name)->array) + \
__must_be_array((name)->array))
+/**
+ * typeof_flex_counter() - Return the type of the counter variable of a given
+ * flexible array member annotated by __counted_by().
+ * @FAM: Instance of flexible array member within a given struct.
+ *
+ * Returns: "size_t" if no annotation exists.
+ */
+#define typeof_flex_counter(FAM) \
+ typeof(_Generic(__flex_counter(FAM), \
+ void *: (size_t)0, \
+ default: *__flex_counter(FAM)))
+
+/**
+ * overflows_flex_counter_type() - Check if the counter associated with the
+ * given flexible array member can represent
+ * a value.
+ * @TYPE: Type of the struct that contains the @FAM.
+ * @FAM: Member name of the FAM within @TYPE.
+ * @COUNT: Value to check against the __counted_by annotated @FAM's counter.
+ *
+ * Returns: true if @COUNT can be represented in the @FAM's counter. When
+ * @FAM is not annotated with __counted_by(), always returns true.
+ */
+#define overflows_flex_counter_type(TYPE, FAM, COUNT) \
+ (!overflows_type(COUNT, typeof_flex_counter(((TYPE *)NULL)->FAM)))
+
+/**
+ * __set_flex_counter() - Set the counter associated with the given flexible
+ * array member that has been annoated by __counted_by().
+ * @FAM: Instance of flexible array member within a given struct.
+ * @COUNT: Value to store to the __counted_by annotated @FAM_PTR's counter.
+ *
+ * This is a no-op if no annotation exists. Count needs to be checked with
+ * overflows_flex_counter_type() before using this function.
+ */
+#define __set_flex_counter(FAM, COUNT) \
+({ \
+ *_Generic(__flex_counter(FAM), \
+ void *: &(size_t){ 0 }, \
+ default: __flex_counter(FAM)) = (COUNT); \
+})
+
#endif /* __LINUX_OVERFLOW_H */
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v6 4/5] slab: Introduce kmalloc_flex() and family
2025-12-03 23:30 [PATCH v6 0/5] asdf Kees Cook
` (2 preceding siblings ...)
2025-12-03 23:30 ` [PATCH v6 3/5] compiler_types: Introduce __flex_counter() and family Kees Cook
@ 2025-12-03 23:30 ` Kees Cook
2025-12-03 23:30 ` [PATCH v6 5/5] coccinelle: Add kmalloc_objs conversion script Kees Cook
2025-12-04 6:07 ` [PATCH v6 0/5] asdf Kees Cook
5 siblings, 0 replies; 9+ messages in thread
From: Kees Cook @ 2025-12-03 23:30 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Kees Cook, Jonathan Corbet, Andrew Morton, Christoph Lameter,
David Rientjes, Roman Gushchin, Harry Yoo, Gustavo A. R. Silva,
workflows, linux-doc, linux-mm, linux-hardening, Linus Torvalds,
Randy Dunlap, Miguel Ojeda, Przemek Kitszel, Matthew Wilcox,
John Hubbard, Joe Perches, Christoph Lameter, Marco Elver,
Vegard Nossum, Pekka Enberg, Joonsoo Kim, Bill Wendling,
Justin Stitt, Jann Horn, Greg Kroah-Hartman, Sasha Levin,
Nathan Chancellor, Peter Zijlstra, Nick Desaulniers,
Jakub Kicinski, Yafang Shao, Tony Ambardar, Alexander Lobakin,
Jan Hendrik Farr, Alexander Potapenko, linux-kernel, llvm
As done for kmalloc_obj*(), introduce a type-aware allocator for flexible
arrays, which may also have "counted_by" annotations:
ptr = kmalloc(struct_size(ptr, flex_member, count), gfp);
becomes:
ptr = kmalloc_flex(*ptr, flex_member, count, gfp);
The internal use of __flex_counter() allows for automatically setting
the counter member of a struct's flexible array member when it has
been annotated with __counted_by(), avoiding any missed early size
initializations while __counted_by() annotations are added to the
kernel. Additionally, this also checks for "too large" allocations based
on the type size of the counter variable. For example:
if (count > type_max(ptr->flex_counter))
fail...;
size = struct_size(ptr, flex_member, count);
ptr = kmalloc(size, gfp);
ptr->flex_counter = count;
becomes (n.b. unchanged from earlier example):
ptr = kmalloc_flex(*ptr, flex_member, count, gfp);
ptr->flex_count = count;
Note that manual initialization of the flexible array counter is still
required (at some point) after allocation as not all compiler versions
support the __counted_by annotation yet. But doing it internally makes
sure they cannot be missed when __counted_by _is_ available, meaning
that the bounds checker will not trip due to the lack of "early enough"
initializations that used to work before enabling the stricter bounds
checking. For example:
ptr = kmalloc_flex(*ptr, flex_member, count, gfp);
fill(ptr->flex, count);
ptr->flex_count = count;
This works correctly before adding a __counted_by annotation (since
nothing is checking ptr->flex accesses against ptr->flex_count). After
adding the annotation, the bounds sanitizer would trip during fill()
because ptr->flex_count wasn't set yet. But with kmalloc_flex() setting
ptr->flex_count internally at allocation time, the existing code works
without needing to move the ptr->flex_count assignment before the call
to fill(). (This has been a stumbling block for __counted_by adoption.)
Signed-off-by: Kees Cook <kees@kernel.org>
---
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Christoph Lameter <cl@gentwo.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Harry Yoo <harry.yoo@oracle.com>
Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: <workflows@vger.kernel.org>
Cc: <linux-doc@vger.kernel.org>
Cc: <linux-mm@kvack.org>
Cc: <linux-hardening@vger.kernel.org>
---
Documentation/process/deprecated.rst | 7 ++++
include/linux/slab.h | 48 ++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/Documentation/process/deprecated.rst b/Documentation/process/deprecated.rst
index 91c628fa2d59..fed56864d036 100644
--- a/Documentation/process/deprecated.rst
+++ b/Documentation/process/deprecated.rst
@@ -387,6 +387,7 @@ allocations. For example, these open coded assignments::
ptr = kzalloc(sizeof(*ptr), gfp);
ptr = kmalloc_array(count, sizeof(*ptr), gfp);
ptr = kcalloc(count, sizeof(*ptr), gfp);
+ ptr = kmalloc(struct_size(ptr, flex_member, count), gfp);
ptr = kmalloc(sizeof(struct foo, gfp);
become, respectively::
@@ -395,4 +396,10 @@ become, respectively::
ptr = kzalloc_obj(*ptr, gfp);
ptr = kmalloc_objs(*ptr, count, gfp);
ptr = kzalloc_objs(*ptr, count, gfp);
+ ptr = kmalloc_flex(*ptr, flex_member, count, gfp);
__auto_type ptr = kmalloc_obj(struct foo, gfp);
+
+If `ptr->flex_member` is annotated with __counted_by(), the allocation
+will automatically fail if `count` is larger than the maximum
+representable value that can be stored in the counter member associated
+with `flex_member`.
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 726457daedbd..2656ea610b68 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -982,6 +982,33 @@ void *kmalloc_nolock_noprof(size_t size, gfp_t gfp_flags, int node);
(TYPE *)KMALLOC(__obj_size, GFP); \
})
+/**
+ * __alloc_flex - Allocate an object that has a trailing flexible array
+ * @KMALLOC: kmalloc wrapper function to use for allocation.
+ * @GFP: GFP flags for the allocation.
+ * @TYPE: type of structure to allocate space for.
+ * @FAM: The name of the flexible array member of @TYPE structure.
+ * @COUNT: how many @FAM elements to allocate space for.
+ *
+ * Returns: Newly allocated pointer to @TYPE with @COUNT-many trailing
+ * @FAM elements, or NULL on failure or if @COUNT cannot be represented
+ * by the member of @TYPE that counts the @FAM elements (annotated via
+ * __counted_by()).
+ */
+#define __alloc_flex(KMALLOC, GFP, TYPE, FAM, COUNT) \
+({ \
+ const size_t __count = (COUNT); \
+ const size_t __obj_size = struct_size_t(TYPE, FAM, __count); \
+ TYPE *__obj_ptr; \
+ if (WARN_ON_ONCE(overflows_flex_counter_type(TYPE, FAM, __count))) \
+ __obj_ptr = NULL; \
+ else \
+ __obj_ptr = KMALLOC(__obj_size, GFP); \
+ if (__obj_ptr) \
+ __set_flex_counter(__obj_ptr->FAM, __count); \
+ __obj_ptr; \
+})
+
/**
* kmalloc_obj - Allocate a single instance of the given type
* @VAR_OR_TYPE: Variable or type to allocate.
@@ -1005,23 +1032,44 @@ void *kmalloc_nolock_noprof(size_t size, gfp_t gfp_flags, int node);
#define kmalloc_objs(VAR_OR_TYPE, COUNT, GFP) \
__alloc_objs(kmalloc, GFP, typeof(VAR_OR_TYPE), COUNT)
+/**
+ * kmalloc_flex - Allocate a single instance of the given flexible structure
+ * @VAR_OR_TYPE: Variable or type to allocate (with its flex array).
+ * @FAM: The name of the flexible array member of the structure.
+ * @COUNT: How many flexible array member elements are desired.
+ * @GFP: GFP flags for the allocation.
+ *
+ * Returns: newly allocated pointer to @VAR_OR_TYPE on success, NULL on
+ * failure. If @FAM has been annotated with __counted_by(), the allocation
+ * will immediately fail if @COUNT is larger than what the type of the
+ * struct's counter variable can represent.
+ */
+#define kmalloc_flex(VAR_OR_TYPE, FAM, COUNT, GFP) \
+ __alloc_flex(kmalloc, GFP, typeof(VAR_OR_TYPE), FAM, COUNT)
+
/* All kzalloc aliases for kmalloc_(obj|objs|flex). */
#define kzalloc_obj(P, GFP) \
__alloc_objs(kzalloc, GFP, typeof(P), 1)
#define kzalloc_objs(P, COUNT, GFP) \
__alloc_objs(kzalloc, GFP, typeof(P), COUNT)
+#define kzalloc_flex(P, FAM, COUNT, GFP) \
+ __alloc_flex(kzalloc, GFP, typeof(P), FAM, COUNT)
/* All kvmalloc aliases for kmalloc_(obj|objs|flex). */
#define kvmalloc_obj(P, GFP) \
__alloc_objs(kvmalloc, GFP, typeof(P), 1)
#define kvmalloc_objs(P, COUNT, GFP) \
__alloc_objs(kvmalloc, GFP, typeof(P), COUNT)
+#define kvmalloc_flex(P, FAM, COUNT, GFP) \
+ __alloc_flex(kvmalloc, GFP, typeof(P), FAM, COUNT)
/* All kvzalloc aliases for kmalloc_(obj|objs|flex). */
#define kvzalloc_obj(P, GFP) \
__alloc_objs(kvzalloc, GFP, typeof(P), 1)
#define kvzalloc_objs(P, COUNT, GFP) \
__alloc_objs(kvzalloc, GFP, typeof(P), COUNT)
+#define kvzalloc_flex(P, FAM, COUNT, GFP) \
+ __alloc_flex(kvzalloc, GFP, typeof(P), FAM, COUNT)
#define kmem_buckets_alloc(_b, _size, _flags) \
alloc_hooks(__kmalloc_node_noprof(PASS_BUCKET_PARAMS(_size, _b), _flags, NUMA_NO_NODE))
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v6 5/5] coccinelle: Add kmalloc_objs conversion script
2025-12-03 23:30 [PATCH v6 0/5] asdf Kees Cook
` (3 preceding siblings ...)
2025-12-03 23:30 ` [PATCH v6 4/5] slab: Introduce kmalloc_flex() " Kees Cook
@ 2025-12-03 23:30 ` Kees Cook
2025-12-04 6:07 ` [PATCH v6 0/5] asdf Kees Cook
5 siblings, 0 replies; 9+ messages in thread
From: Kees Cook @ 2025-12-03 23:30 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Kees Cook, Julia Lawall, Nicolas Palix, cocci, Linus Torvalds,
Randy Dunlap, Miguel Ojeda, Przemek Kitszel, Gustavo A. R. Silva,
Matthew Wilcox, John Hubbard, Joe Perches, Christoph Lameter,
Marco Elver, Vegard Nossum, Pekka Enberg, David Rientjes,
Joonsoo Kim, Andrew Morton, Roman Gushchin, Harry Yoo,
Bill Wendling, Justin Stitt, Jann Horn, Greg Kroah-Hartman,
Sasha Levin, linux-mm, Nathan Chancellor, Peter Zijlstra,
Nick Desaulniers, Jonathan Corbet, Jakub Kicinski, Yafang Shao,
Tony Ambardar, Alexander Lobakin, Jan Hendrik Farr,
Alexander Potapenko, linux-kernel, linux-hardening, linux-doc,
llvm
Finds and converts sized kmalloc-family of allocations into the
typed kmalloc_obj-family of allocations.
Signed-off-by: Kees Cook <kees@kernel.org>
---
Cc: Julia Lawall <Julia.Lawall@inria.fr>
Cc: Nicolas Palix <nicolas.palix@imag.fr>
Cc: cocci@inria.fr
---
scripts/coccinelle/api/kmalloc_objs.cocci | 109 ++++++++++++++++++++++
1 file changed, 109 insertions(+)
create mode 100644 scripts/coccinelle/api/kmalloc_objs.cocci
diff --git a/scripts/coccinelle/api/kmalloc_objs.cocci b/scripts/coccinelle/api/kmalloc_objs.cocci
new file mode 100644
index 000000000000..916cc3a661b9
--- /dev/null
+++ b/scripts/coccinelle/api/kmalloc_objs.cocci
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/// Use kmalloc_obj family of macros for allocations
+///
+// Confidence: High
+// Options: --include-headers-for-types --all-includes --include-headers --keep-comments
+
+virtual patch
+
+@initialize:python@
+@@
+import sys
+
+def alloc_array(name):
+ func = "FAILED_RENAME"
+ if name == "kmalloc_array":
+ func = "kmalloc_objs"
+ elif name == "kvmalloc_array":
+ func = "kvmalloc_objs"
+ elif name == "kcalloc":
+ func = "kzalloc_objs"
+ elif name == "kvcalloc":
+ func = "kvzalloc_objs"
+ else:
+ print(f"Unknown transform for {name}", file=sys.stderr)
+ return func
+
+// This excludes anything that is assigning to or from integral types or
+// string literals. Everything else gets the sizeof() extracted for the
+// kmalloc_obj() type/var argument. sizeof(void *) is also excluded because
+// it will need case-by-case double-checking to make sure the right type is
+// being assigned.
+@direct depends on patch && !(file in "tools") && !(file in "samples")@
+typedef u8, u16, u32, u64;
+typedef __u8, __u16, __u32, __u64;
+typedef uint8_t, uint16_t, uint32_t, uint64_t;
+typedef __le16, __le32, __le64;
+typedef __be16, __be32, __be64;
+type INTEGRAL = {u8,__u8,uint8_t,char,unsigned char,
+ u16,__u16,uint16_t,unsigned short,
+ u32,__u32,uint32_t,unsigned int,
+ u64,__u64,uint64_t,unsigned long,
+ __le16,__le32,__le64,__be16,__be32,__be64};
+char [] STRING;
+INTEGRAL *BYTES;
+type TYPE;
+expression VAR;
+expression GFP;
+expression COUNT;
+expression FLEX;
+expression E;
+identifier ALLOC =~ "^kv?[mz]alloc$";
+fresh identifier ALLOC_OBJ = ALLOC ## "_obj";
+fresh identifier ALLOC_FLEX = ALLOC ## "_flex";
+identifier ALLOC_ARRAY = {kmalloc_array,kvmalloc_array,kcalloc,kvcalloc};
+fresh identifier ALLOC_OBJS = script:python(ALLOC_ARRAY) { alloc_array(ALLOC_ARRAY) };
+@@
+
+(
+- VAR = ALLOC((sizeof(*VAR)), GFP)
++ VAR = ALLOC_OBJ(*VAR, GFP)
+|
+ ALLOC((\(sizeof(STRING)\|sizeof(INTEGRAL)\|sizeof(INTEGRAL *)\)), GFP)
+|
+ BYTES = ALLOC((sizeof(E)), GFP)
+|
+ BYTES = ALLOC((sizeof(TYPE)), GFP)
+|
+ ALLOC((sizeof(void *)), GFP)
+|
+- ALLOC((sizeof(E)), GFP)
++ ALLOC_OBJ(E, GFP)
+|
+- ALLOC((sizeof(TYPE)), GFP)
++ ALLOC_OBJ(TYPE, GFP)
+|
+ ALLOC_ARRAY(COUNT, (\(sizeof(STRING)\|sizeof(INTEGRAL)\|sizeof(INTEGRAL *)\)), GFP)
+|
+ BYTES = ALLOC_ARRAY(COUNT, (sizeof(E)), GFP)
+|
+ BYTES = ALLOC_ARRAY(COUNT, (sizeof(TYPE)), GFP)
+|
+ ALLOC_ARRAY((\(sizeof(STRING)\|sizeof(INTEGRAL)\|sizeof(INTEGRAL *)\)), COUNT, GFP)
+|
+ BYTES = ALLOC_ARRAY((sizeof(E)), COUNT, GFP)
+|
+ BYTES = ALLOC_ARRAY((sizeof(TYPE)), COUNT, GFP)
+|
+ ALLOC_ARRAY(COUNT, (sizeof(void *)), GFP)
+|
+ ALLOC_ARRAY((sizeof(void *)), COUNT, GFP)
+|
+- ALLOC_ARRAY(COUNT, (sizeof(E)), GFP)
++ ALLOC_OBJS(E, COUNT, GFP)
+|
+- ALLOC_ARRAY(COUNT, (sizeof(TYPE)), GFP)
++ ALLOC_OBJS(TYPE, COUNT, GFP)
+|
+- ALLOC_ARRAY((sizeof(E)), COUNT, GFP)
++ ALLOC_OBJS(E, COUNT, GFP)
+|
+- ALLOC_ARRAY((sizeof(TYPE)), COUNT, GFP)
++ ALLOC_OBJS(TYPE, COUNT, GFP)
+|
+- ALLOC(struct_size(VAR, FLEX, COUNT), GFP)
++ ALLOC_FLEX(*VAR, FLEX, COUNT, GFP)
+|
+- ALLOC(struct_size_t(TYPE, FLEX, COUNT), GFP)
++ ALLOC_FLEX(TYPE, FLEX, COUNT, GFP)
+)
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v6 0/5] asdf
2025-12-03 23:30 [PATCH v6 0/5] asdf Kees Cook
` (4 preceding siblings ...)
2025-12-03 23:30 ` [PATCH v6 5/5] coccinelle: Add kmalloc_objs conversion script Kees Cook
@ 2025-12-04 6:07 ` Kees Cook
5 siblings, 0 replies; 9+ messages in thread
From: Kees Cook @ 2025-12-04 6:07 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Linus Torvalds, Randy Dunlap, Miguel Ojeda, Przemek Kitszel,
Gustavo A. R. Silva, Matthew Wilcox, John Hubbard, Joe Perches,
Christoph Lameter, Marco Elver, Vegard Nossum, Pekka Enberg,
David Rientjes, Joonsoo Kim, Andrew Morton, Roman Gushchin,
Harry Yoo, Bill Wendling, Justin Stitt, Jann Horn,
Greg Kroah-Hartman, Sasha Levin, linux-mm, Nathan Chancellor,
Peter Zijlstra, Nick Desaulniers, Jonathan Corbet,
Jakub Kicinski, Yafang Shao, Tony Ambardar, Alexander Lobakin,
Jan Hendrik Farr, Alexander Potapenko, linux-kernel,
linux-hardening, linux-doc, llvm
> Subject: Re: [PATCH v6 0/5] asdf
*sigh* Should have been:
[PATCH v6 0/5] slab: Introduce kmalloc_obj() and family
--
Kees Cook
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v6 3/5] compiler_types: Introduce __flex_counter() and family
2025-12-03 23:30 ` [PATCH v6 3/5] compiler_types: Introduce __flex_counter() and family Kees Cook
@ 2025-12-04 8:54 ` Peter Zijlstra
2025-12-04 20:25 ` Kees Cook
0 siblings, 1 reply; 9+ messages in thread
From: Peter Zijlstra @ 2025-12-04 8:54 UTC (permalink / raw)
To: Kees Cook
Cc: Vlastimil Babka, Miguel Ojeda, Gustavo A. R. Silva,
Nathan Chancellor, Nick Desaulniers, Marco Elver,
Przemek Kitszel, linux-hardening, Linus Torvalds, Randy Dunlap,
Matthew Wilcox, John Hubbard, Joe Perches, Christoph Lameter,
Vegard Nossum, Pekka Enberg, David Rientjes, Joonsoo Kim,
Andrew Morton, Roman Gushchin, Harry Yoo, Bill Wendling,
Justin Stitt, Jann Horn, Greg Kroah-Hartman, Sasha Levin,
linux-mm, Nick Desaulniers, Jonathan Corbet, Jakub Kicinski,
Yafang Shao, Tony Ambardar, Alexander Lobakin, Jan Hendrik Farr,
Alexander Potapenko, linux-kernel, linux-doc, llvm
On Wed, Dec 03, 2025 at 03:30:33PM -0800, Kees Cook wrote:
> Introduce __flex_counter() which wraps __builtin_counted_by_ref(),
> as newly introduced by GCC[1] and Clang[2]. Use of __flex_counter()
> allows access to the counter member of a struct's flexible array member
> when it has been annotated with __counted_by().
>
> Introduce typeof_flex_counter(), overflows_flex_counter_type(), and
> __set_flex_counter() to provide the needed _Generic() wrappers to get
> sane results out of __flex_counter().
>
> For example, with:
>
> struct foo {
> int counter;
> short array[] __counted_by(counter);
> } *p;
>
> __flex_counter(p->array) will resolve to: &p->counter
>
> typeof_flex_counter(p->array) will resolve to "int". (If p->array was not
> annotated, it would resolve to "size_t".)
Uhh, how will this interact with the proposed extension of
__counted_by() to normal pointer types?
Because the moment we have __counted_by() on pointers (remember, you
promised to rename __counted_by_ptr() to __counted_by() once GCC-16
releases) using __flex_counter() on a ptr thing makes absolutely no
sense.
So perhaps just name this thing __counter_of() or something?
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v6 3/5] compiler_types: Introduce __flex_counter() and family
2025-12-04 8:54 ` Peter Zijlstra
@ 2025-12-04 20:25 ` Kees Cook
0 siblings, 0 replies; 9+ messages in thread
From: Kees Cook @ 2025-12-04 20:25 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Vlastimil Babka, Miguel Ojeda, Gustavo A. R. Silva,
Nathan Chancellor, Nick Desaulniers, Marco Elver,
Przemek Kitszel, linux-hardening, Linus Torvalds, Randy Dunlap,
Matthew Wilcox, John Hubbard, Joe Perches, Christoph Lameter,
Vegard Nossum, Pekka Enberg, David Rientjes, Joonsoo Kim,
Andrew Morton, Roman Gushchin, Harry Yoo, Bill Wendling,
Justin Stitt, Jann Horn, Greg Kroah-Hartman, Sasha Levin,
linux-mm, Nick Desaulniers, Jonathan Corbet, Jakub Kicinski,
Yafang Shao, Tony Ambardar, Alexander Lobakin, Jan Hendrik Farr,
Alexander Potapenko, linux-kernel, linux-doc, llvm
On Thu, Dec 04, 2025 at 09:54:35AM +0100, Peter Zijlstra wrote:
> On Wed, Dec 03, 2025 at 03:30:33PM -0800, Kees Cook wrote:
> > Introduce __flex_counter() which wraps __builtin_counted_by_ref(),
> > as newly introduced by GCC[1] and Clang[2]. Use of __flex_counter()
> > allows access to the counter member of a struct's flexible array member
> > when it has been annotated with __counted_by().
> >
> > Introduce typeof_flex_counter(), overflows_flex_counter_type(), and
> > __set_flex_counter() to provide the needed _Generic() wrappers to get
> > sane results out of __flex_counter().
> >
> > For example, with:
> >
> > struct foo {
> > int counter;
> > short array[] __counted_by(counter);
> > } *p;
> >
> > __flex_counter(p->array) will resolve to: &p->counter
> >
> > typeof_flex_counter(p->array) will resolve to "int". (If p->array was not
> > annotated, it would resolve to "size_t".)
>
> Uhh, how will this interact with the proposed extension of
> __counted_by() to normal pointer types?
Good point -- at present __builtin_counted_by_ref() only works on flex
arrays. I will ask the compiler devs their thoughts on expanding it to
the pointer references too...
--
Kees Cook
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-12-04 20:25 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-03 23:30 [PATCH v6 0/5] asdf Kees Cook
2025-12-03 23:30 ` [PATCH v6 1/5] slab: Introduce kmalloc_obj() and family Kees Cook
2025-12-03 23:30 ` [PATCH v6 2/5] checkpatch: Suggest kmalloc_obj family for sizeof allocations Kees Cook
2025-12-03 23:30 ` [PATCH v6 3/5] compiler_types: Introduce __flex_counter() and family Kees Cook
2025-12-04 8:54 ` Peter Zijlstra
2025-12-04 20:25 ` Kees Cook
2025-12-03 23:30 ` [PATCH v6 4/5] slab: Introduce kmalloc_flex() " Kees Cook
2025-12-03 23:30 ` [PATCH v6 5/5] coccinelle: Add kmalloc_objs conversion script Kees Cook
2025-12-04 6:07 ` [PATCH v6 0/5] asdf Kees Cook
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox