asdf
Subsystems (7)
Kees Cook
maintainerv6 cover asdf
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
7682This 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-afterThanks!
-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/[email protected]/
v4: https://lore.kernel.org/lkml/[email protected]/
v3: https://lore.kernel.org/lkml/[email protected]/
v2: https://lore.kernel.org/lkml/[email protected]/
v1: https://lore.kernel.org/lkml/[email protected]/
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
Signature · 1 line
2.34.1
Kees Cook
maintainerPATCH v6 1/5 slab: Introduce kmalloc_obj() and family
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.
---
Cc: Vlastimil Babka <[email protected]>
Cc: Christoph Lameter <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: David Rientjes <[email protected]>
Cc: Joonsoo Kim <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Roman Gushchin <[email protected]>
Cc: Hyeonggon Yoo <[email protected]>
Cc: Gustavo A. R. Silva <[email protected]>
Cc: Bill Wendling <[email protected]>
Cc: Justin Stitt <[email protected]>
Cc: Jann Horn <[email protected]>
Cc: Przemek Kitszel <[email protected]>
Cc: Marco Elver <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Sasha Levin <[email protected]>
Cc: [email protected]
--- Documentation/process/deprecated.rst | 24 ++++++++++++ include/linux/slab.h | 58 ++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+)
Documentation/process/deprecated.rst +24 -0
@@ -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);
include/linux/slab.h +58 -0
70 lines not on this page · raw message
Signature · 1 line
2.34.1
Re: [PATCH v6 1/5] slab: Introduce kmalloc_obj() and family
Quoted 35 lines · Kees Cook
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.
Quoted 2 lines
How do you plan to handle this series? Given minimal slab changes (just wrappers) but there being also changes elsewhere, want to use your hardening tree? I wouldn't mind.
Quoted 17 lines
include/linux/slab.h +4
-0@@ -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 fvoid *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.
include/linux/slab.h static __always_inline __alloc_size(1) void *kmalloc_noprof(size_t size, gfp_t f · line 981
Quoted 10 lines
include/linux/slab.h +10
-0+* @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); \
I assume with the hardcoded 1 for COUNT, this size_mul() will be eliminated by the compiler and not add unnecessary runtime overhead? Otherwise we should have two core #define variants.
I also noted that the existing kmalloc_array() and kvmalloc_array() do check_mul_overflow() and return NULL silently on overflow. This AFAIU will make SIZE_MAX passed to the underlying kmalloc/kvmalloc and thus will cause a warning. That's IMHO a good thing.
Quoted 47 lines
include/linux/slab.h +44
-0+ (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))
Kees Cook
maintainerRe: [PATCH v6 1/5] slab: Introduce kmalloc_obj() and family
Quoted 36 lines · Vlastimil Babka
Quoted 35 lines · Kees Cook
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.
Quoted 8 lines
Quoted 2 lines
Acked-by Vlastimil Babka <[email protected]>How do you plan to handle this series? Given minimal slab changes (just wrappers) but there being also changes elsewhere, want to use your hardening tree? I wouldn't mind.
Ah! Sure, yeah, I can take it. Thanks for the Ack. I'll get it into -next and refresh the treewide changes.
-Kees
Signature · 1 line
Kees Cook
Kees Cook
maintainerRe: [PATCH v6 1/5] slab: Introduce kmalloc_obj() and family
In reply to Vlastimil BabkaQuoted 11 lines · Vlastimil Babka
Quoted 10 lines · Kees Cook
[...]
+/**
+ *__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.
Quoted 8 lines
include/linux/slab.h static __always_inline __alloc_size(1) void *kmalloc_noprof(size_t size, gfp_t f · line 981
Quoted 4 lines
+ */
include/linux/slab.h +3
-0+#define __alloc_objs (KMALLOC ,GFP ,TYPE ,COUNT ) \ +({ \ + const size_t __obj_size = size_mul(sizeof(TYPE), COUNT); \I assume with the hardcoded 1 for COUNT, this
size_mul()will be eliminated by the compiler and not add unnecessary runtime overhead? Otherwise we should have two core #define variants.
You're correct: the compiler completely collapses it with 0 runtime overhead; a variant is not needed.
Quoted 4 lines
I also noted that the existing
kmalloc_array()andkvmalloc_array()docheck_mul_overflow()and return NULL silently on overflow. This AFAIU will makeSIZE_MAXpassed to the underlying kmalloc/kvmalloc and thus will cause a warning. That's IMHO a good thing.
Right -- I prefer seeing the SIZE_MAX yelling from the allocator. Should we change how k*malloc_array() behaves?
-Kees
Signature · 1 line
Kees Cook
Re: [PATCH v6 1/5] slab: Introduce kmalloc_obj() and family
Quoted 24 lines · Kees Cook
Quoted 11 lines · Vlastimil Babka
Quoted 10 lines · Kees Cook
[...]
+/**
+ *__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.Quoted 8 lines
include/linux/slab.h static __always_inline __alloc_size(1) void *kmalloc_noprof(size_t size, gfp_t f · line 981
Quoted 4 lines
+ */
include/linux/slab.h +3
-0+#define __alloc_objs (KMALLOC ,GFP ,TYPE ,COUNT ) \ +({ \ + const size_t __obj_size = size_mul(sizeof(TYPE), COUNT); \I assume with the hardcoded 1 for COUNT, this
size_mul()will be eliminated by the compiler and not add unnecessary runtime overhead? Otherwise we should have two core #define variants.You're correct: the compiler completely collapses it with 0 runtime overhead; a variant is not needed.
Quoted 7 lines
Quoted 4 lines
I also noted that the existing
kmalloc_array()andkvmalloc_array()docheck_mul_overflow()and return NULL silently on overflow. This AFAIU will makeSIZE_MAXpassed to the underlying kmalloc/kvmalloc and thus will cause a warning. That's IMHO a good thing.Right -- I prefer seeing the
SIZE_MAXyelling from the allocator. Should we change how k*malloc_array() behaves?
Yeah it should best behave the same I think.
Quoted 2 lines
-Kees
Re: [PATCH v6 1/5] slab: Introduce kmalloc_obj() and family
In reply to Kees CookQuoted 24 lines · Kees Cook
Quoted 11 lines · Vlastimil Babka
Quoted 10 lines · Kees Cook
[...]
+/**
+ *__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.Quoted 8 lines
include/linux/slab.h static __always_inline __alloc_size(1) void *kmalloc_noprof(size_t size, gfp_t f · line 981
Quoted 4 lines
+ */
include/linux/slab.h +3
-0+#define __alloc_objs (KMALLOC ,GFP ,TYPE ,COUNT ) \ +({ \ + const size_t __obj_size = size_mul(sizeof(TYPE), COUNT); \I assume with the hardcoded 1 for COUNT, this
size_mul()will be eliminated by the compiler and not add unnecessary runtime overhead? Otherwise we should have two core #define variants.You're correct: the compiler completely collapses it with 0 runtime overhead; a variant is not needed.
Quoted 7 lines
Quoted 4 lines
I also noted that the existing
kmalloc_array()andkvmalloc_array()docheck_mul_overflow()and return NULL silently on overflow. This AFAIU will makeSIZE_MAXpassed to the underlying kmalloc/kvmalloc and thus will cause a warning. That's IMHO a good thing.Right -- I prefer seeing the
SIZE_MAXyelling from the allocator. Should we change how k*malloc_array() behaves?
Huh, yeah, it's weird to not get a stack trace if kmalloc() fails. On the other hand, if we're allocating SIZE_MAX, that is probably a user controlled size. Since we don't want people spamming dmesg, it should probably be WARN_ONCE().
regards,
dan carpenter
Re: [PATCH v6 1/5] slab: Introduce kmalloc_obj() and family
In reply to Kees CookQuoted 9 lines · Kees Cook
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);
Quoted 3 lines
These become, respectively:
ptr = kmalloc_obj(*ptr, gfp);
We are already getting patches that covert these to:
ptr = kmalloc_obj(ptr, gfp);
(without the *). This feels like the obvious bug people will introduce with this API. I sort of think that "ptr = kmalloc_obj(ptr, gfp);" is more natural, so maybe we could make it work that way instead?
regards,
dan carpenter
Re: [PATCH v6 1/5] slab: Introduce kmalloc_obj() and family
Quoted 14 lines · Dan Carpenter
Quoted 9 lines · Kees Cook
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);Quoted 3 lines
These become, respectively:
ptr = kmalloc_obj(*ptr, gfp);
Quoted 7 lines
We are already getting patches that covert these to:
ptr = kmalloc_obj(ptr, gfp);(without the *). This feels like the obvious bug people will introduce with this API. I sort of think that "ptr =
kmalloc_obj(ptr, gfp);" is more natural, so maybe we could make it work that way instead?
Never mind. It causes a compile error when people leave out the asterisk. Thanks for that.
regards,
dan carpenter
Kees Cook
maintainerPATCH v6 2/5 checkpatch: Suggest kmalloc_obj family for sizeof allocations
In reply to Kees CookTo 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.
---
Cc: Andy Whitcroft <[email protected]>
Cc: Joe Perches <[email protected]>
Cc: Dwaipayan Ray <[email protected]>
Cc: Lukas Bulwahn <[email protected]>
--- scripts/checkpatch.pl | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-)
scripts/checkpatch.pl +33 -6
@@ -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; } } }
Signature · 1 line
2.34.1
Kees Cook
maintainerPATCH v6 3/5 compiler_types: Introduce __flex_counter() and family
In reply to Kees CookIntroduce __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().)
---
Cc: Miguel Ojeda <[email protected]>
Cc: "Gustavo A. R. Silva" <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Nick Desaulniers <[email protected]>
Cc: Marco Elver <[email protected]>
Cc: Przemek Kitszel <[email protected]>
Cc: [email protected]
--- include/linux/compiler_types.h | 31 +++++++++++++++++++++++++ include/linux/overflow.h | 42 ++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+)
include/linux/compiler_types.h +31 -0
@@ -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: *
include/linux/overflow.h +42 -0
46 lines not on this page · raw message
Signature · 1 line
2.34.1
Re: [PATCH v6 3/5] compiler_types: Introduce __flex_counter() and family
Quoted 16 lines · Kees Cook
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;
Quoted 4 lines
__flex_counter(p->array)will resolve to:&p->counter
typeof_flex_counter(p->array)will resolve to "int". (Ifp->arraywas 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?
Kees Cook
maintainerRe: [PATCH v6 3/5] compiler_types: Introduce __flex_counter() and family
Quoted 17 lines · Peter Zijlstra
Quoted 16 lines · Kees Cook
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;
Quoted 7 lines
Quoted 4 lines
__flex_counter(p->array)will resolve to:&p->counter
typeof_flex_counter(p->array)will resolve to "int". (Ifp->arraywas 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...
Signature · 1 line
Kees Cook
Kees Cook
maintainerPATCH v6 4/5 slab: Introduce kmalloc_flex() and family
In reply to Kees CookAs 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.)
---
Cc: Jonathan Corbet <[email protected]>
Cc: Vlastimil Babka <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Christoph Lameter <[email protected]>
Cc: David Rientjes <[email protected]>
Cc: Roman Gushchin <[email protected]>
Cc: Harry Yoo <[email protected]>
Cc: "Gustavo A. R. Silva" <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
--- Documentation/process/deprecated.rst | 7 ++++ include/linux/slab.h | 48 ++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+)
Documentation/process/deprecated.rst +7 -0
@@ -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`.
include/linux/slab.h +48 -0
77 lines not on this page · raw message
Signature · 1 line
2.34.1
Re: [PATCH v6 4/5] slab: Introduce kmalloc_flex() and family
Quoted 22 lines · Kees Cook
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;
Quoted 4 lines
becomes (n.b. unchanged from earlier example):
ptr = kmalloc_flex(*ptr, flex_member, count, gfp); ptr->flex_count = count;
^ flex_counter ?
But if it was "too large", ptr is NULL so this will oops?
Quoted 145 lines
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_byannotation 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_byannotation (since nothing is checkingptr->flexaccesses againstptr->flex_count). After adding the annotation, the bounds sanitizer would trip duringfill()becauseptr->flex_countwasn't set yet. But withkmalloc_flex()settingptr->flex_countinternally at allocation time, the existing code works without needing to move theptr->flex_countassignment before the call tofill(). (This has been a stumbling block for__counted_byadoption.)Signed-off-by Kees Cook <[email protected]>---
Cc: Jonathan Corbet <[email protected]>
Cc: Vlastimil Babka <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Christoph Lameter <[email protected]>
Cc: David Rientjes <[email protected]>
Cc: Roman Gushchin <[email protected]>
Cc: Harry Yoo <[email protected]>
Cc: "Gustavo A. R. Silva" <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>--- Documentation/process/deprecated.rst | 7 ++++ include/linux/slab.h | 48 ++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+)Documentation/process/deprecated.rst +7
-0@@ -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`.include/linux/slab.h +48
-0@@ -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))
Kees Cook
maintainerRe: [PATCH v6 4/5] slab: Introduce kmalloc_flex() and family
Quoted 23 lines · Vlastimil Babka
Quoted 22 lines · Kees Cook
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;
Quoted 8 lines
Quoted 4 lines
becomes (n.b. unchanged from earlier example):
ptr = kmalloc_flex(*ptr, flex_member, count, gfp); ptr->flex_count = count;^
flex_counter?But if it was "too large", ptr is NULL so this will oops?
Oops, yes, typo in the example. I will fix that. As for NULL, I dropped the NULL checking on both sides of the example just to focus on the differences.
Signature · 1 line
Kees Cook
Kees Cook
maintainerRe: [PATCH v6 4/5] slab: Introduce kmalloc_flex() and family
In reply to Vlastimil BabkaQuoted 23 lines · Vlastimil Babka
Quoted 22 lines · Kees Cook
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;
Quoted 8 lines
Quoted 4 lines
becomes (n.b. unchanged from earlier example):
ptr = kmalloc_flex(*ptr, flex_member, count, gfp); ptr->flex_count = count;^
flex_counter?But if it was "too large", ptr is NULL so this will oops?
I've changed this to:
...
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);
if (!ptr)
fail...;
ptr->flex_counter = count;becomes (n.b. unchanged from earlier example):
ptr = kmalloc_flex(*ptr, flex_member, count, gfp);
if (!ptr)
fail...;
ptr->flex_counter = count;May I add your Acked-by for this 4/5 patch?
Signature · 1 line
Kees Cook
Re: [PATCH v6 4/5] slab: Introduce kmalloc_flex() and family
In reply to Kees CookQuoted 47 lines · Kees Cook
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_byannotation 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_byannotation (since nothing is checkingptr->flexaccesses againstptr->flex_count). After adding the annotation, the bounds sanitizer would trip duringfill()becauseptr->flex_countwasn't set yet. But withkmalloc_flex()settingptr->flex_countinternally at allocation time, the existing code works without needing to move theptr->flex_countassignment before the call tofill(). (This has been a stumbling block for__counted_byadoption.)
Quoted 1 line
Signed-off-by Kees Cook <[email protected]>
Quoted 124 lines
---
Cc: Jonathan Corbet <[email protected]>
Cc: Vlastimil Babka <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Christoph Lameter <[email protected]>
Cc: David Rientjes <[email protected]>
Cc: Roman Gushchin <[email protected]>
Cc: Harry Yoo <[email protected]>
Cc: "Gustavo A. R. Silva" <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>--- Documentation/process/deprecated.rst | 7 ++++ include/linux/slab.h | 48 ++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+)Documentation/process/deprecated.rst +7
-0@@ -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`.include/linux/slab.h +48
-0@@ -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))
Re: [PATCH v6 4/5] slab: Introduce kmalloc_flex() and family
In reply to Kees CookQuoted 107 lines · Kees Cook
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_byannotation 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_byannotation (since nothing is checkingptr->flexaccesses againstptr->flex_count). After adding the annotation, the bounds sanitizer would trip duringfill()becauseptr->flex_countwasn't set yet. But withkmalloc_flex()settingptr->flex_countinternally at allocation time, the existing code works without needing to move theptr->flex_countassignment before the call tofill(). (This has been a stumbling block for__counted_byadoption.)Signed-off-by Kees Cook <[email protected]>---
Cc: Jonathan Corbet <[email protected]>
Cc: Vlastimil Babka <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Christoph Lameter <[email protected]>
Cc: David Rientjes <[email protected]>
Cc: Roman Gushchin <[email protected]>
Cc: Harry Yoo <[email protected]>
Cc: "Gustavo A. R. Silva" <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>--- Documentation/process/deprecated.rst | 7 ++++ include/linux/slab.h | 48 ++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+)Documentation/process/deprecated.rst +7
-0@@ -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`.include/linux/slab.h +10
-0@@ -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
include/linux/slab.h void *kmalloc_nolock_noprof(size_t size, gfp_t gfp_flags, int node); · line 1004
Quoted 10 lines
include/linux/slab.h +10
-0+* 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; \
I wonder if this is correct? Because overflows_flex_counter_type() is:
#define overflows_flex_counter_type(TYPE, FAM, COUNT) \ (!overflows_type(COUNT, typeof_flex_counter(((TYPE *)NULL)->FAM)))
I.e. returns true if overflows_type() returns false, and whose comment states:
* Returns: true if @COUNT can be represented in the @FAM's counter. When
* @FAM is not annotated with __counted_by(), always returns true.
So we warn on when the @COUNT _can_ be represented in @FAM's counter?
I'm seeing the warning for the following:
struct multi_remaps {
unsigned int nr, cap;
long offsets[] __counted_by(cap);
};...
unsigned int cap;
...
multi = kmalloc_flex(*multi, offsets, cap, gfp);
Surely that ! should not be there?
Annnd now I typed that I realise that Linus fixed this up in mainline and I was working with a stale version of this file :))
Anyway, I see that the comment isn't fixed up, so I think that's something we should patch, like:
* Returns: true if @COUNT can be represented in the @FAM's counter. When
* @FAM is not annotated with __counted_by(), always returns true.
->
* Returns: true if @COUNT cannot be represented in the @FAM's counter. When
* @FAM is not annotated with __counted_by(), always returns false.
Cheers, Lorenzo
Re: [PATCH v6 4/5] slab: Introduce kmalloc_flex() and family
Quoted 1 line · On Tue, 24 Feb 2026 10:26:36 +0000 Lorenzo Stoakes…
On Wed, Dec 03, 2025 at 03:30:34PM -0800, Kees Cook wrote:
...
Quoted 20 lines
Quoted 20 lines
include/linux/slab.h +20
-0+/** +* __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; \
...
Quoted 2 lines
Annnd now I typed that I realise that Linus fixed this up in mainline and I was working with a stale version of this file :))
I think someone else mentioned it, but having a WARN_ON_ONCE() is there is really a bad idea.
The code bloat must be stunning.
I won't ask why the #define parameters are all UPPER CASE.
David
Kees Cook
maintainerRe: [PATCH v6 4/5] slab: Introduce kmalloc_flex() and family
In reply to Lorenzo StoakesQuoted 6 lines · Lorenzo Stoakes
Annnd now I typed that I realise that Linus fixed this up in mainline and I was working with a stale version of this file :))
Anyway, I see that the comment isn't fixed up, so I think that's something we should patch, like:
Quoted 7 lines
* Returns: true if @COUNT can be represented in the @FAM's counter. When
* @FAM is not annotated with__counted_by(), always returns true.->
* Returns: true if @COUNT cannot be represented in the @FAM's counter. When
* @FAM is not annotated with__counted_by(), always returns false.
Yeah, I'm working on fixing this up correctly. I think Linux is right that we need to put the overflow checking entirely within the counter setting. That way the checks will only happen for the cases where counted_by is actually in use.
I am, however, still pondering that the size check (as I _intended_ it, not as it actually manifested), would catch negative sizes (i.e. negative can't be represented in a size_t -- the default type when the counter type is unknown) and refuse to allocate, though honestly the allocator would probably also refuse to allocate them since they would be very very large when cast back to size_t for the allocation itself.
Signature · 1 line
Kees Cook
Kees Cook
maintainerPATCH v6 5/5 coccinelle: Add kmalloc_objs conversion script
In reply to Kees CookFinds and converts sized kmalloc-family of allocations into the typed kmalloc_obj-family of allocations.
---
Cc: Julia Lawall <[email protected]>
Cc: Nicolas Palix <[email protected]>
Cc: [email protected]
--- scripts/coccinelle/api/kmalloc_objs.cocci | 109 ++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 scripts/coccinelle/api/kmalloc_objs.cocci
scripts/coccinelle/api/kmalloc_objs.cocci new file +109 -0
@@ -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) +)
Signature · 1 line
2.34.1
Re: [PATCH v6 5/5] coccinelle: Add kmalloc_objs conversion script
Quoted 2 lines
Finds and converts sized kmalloc-family of allocations into the typed kmalloc_obj-family of allocations.
Can previous patch review concerns get more development attention anyhow?
https://lore.kernel.org/cocci/[email protected]/
https://sympa.inria.fr/sympa/arc/cocci/2025-11/msg00066.html
Regards,
Markus
Kees Cook
maintainerRe: [PATCH v6 5/5] coccinelle: Add kmalloc_objs conversion script
Quoted 6 lines · Markus Elfring
Quoted 2 lines
Finds and converts sized kmalloc-family of allocations into the typed kmalloc_obj-family of allocations.
Can previous patch review concerns get more development attention anyhow?
https://lore.kernel.org/cocci/[email protected]/
https://sympa.inria.fr/sympa/arc/cocci/2025-11/msg00066.html
I've replied there now. tl;dr: I already dropped the empty Comments line for this v5, and didn't want to make other changes to the .cocci without a better rationale. I'm open to suggestions, though!
-Kees
Signature · 1 line
Kees Cook
Julia Lawall
maintainerRe: [cocci] [PATCH v6 5/5] coccinelle: Add kmalloc_objs conversion script
In reply to Kees CookQuoted 2 lines · Kees Cook
Finds and converts sized kmalloc-family of allocations into the typed kmalloc_obj-family of allocations.
The combination of the use of a regular expression to find the function names and the big disjunction makes this unnecessarily slow. I will try to propose something shortly.
julia
Quoted 130 lines
Signed-off-by Kees Cook <[email protected]>---
Cc: Julia Lawall <[email protected]>
Cc: Nicolas Palix <[email protected]>
Cc: [email protected]--- scripts/coccinelle/api/kmalloc_objs.cocci | 109 ++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 scripts/coccinelle/api/kmalloc_objs.cocciscripts/coccinelle/api/kmalloc_objs.cocci new file +109
-1@@ -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
Re: [PATCH v6 5/5] coccinelle: Add kmalloc_objs conversion script
In reply to Kees CookQuoted 4 lines · Kees Cook
Finds and converts sized kmalloc-family of allocations into the typed kmalloc_obj-family of allocations.
Signed-off-by Kees Cook <[email protected]>
Quoted 8 lines
---
Cc: Julia Lawall <[email protected]>
Cc: Nicolas Palix <[email protected]>
Cc: [email protected]--- scripts/coccinelle/api/kmalloc_objs.cocci | 109 ++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 scripts/coccinelle/api/kmalloc_objs.cocci
Is there a way to reproduce commit 69050f8d6d075dc using this semantic patch as claimed? I spend a while installing the latest version of spatch (which was quite hard to do due to all the unusual dependencies), but it complains that no rules apply:
$ /usr/local/bin/spatch --sp-file scripts/coccinelle/api/kmalloc_objs.cocci --dir . --in-place init_defs_builtins: /usr/local/lib/coccinelle/standard.h SPECIAL NAMES: adding u8 as a type SPECIAL NAMES: adding u16 as a type SPECIAL NAMES: adding u32 as a type SPECIAL NAMES: adding u64 as a type SPECIAL NAMES: adding __u8 as a type SPECIAL NAMES: adding __u16 as a type SPECIAL NAMES: adding __u32 as a type SPECIAL NAMES: adding __u64 as a type SPECIAL NAMES: adding uint8_t as a type SPECIAL NAMES: adding uint16_t as a type SPECIAL NAMES: adding uint32_t as a type SPECIAL NAMES: adding uint64_t as a type SPECIAL NAMES: adding uchar as a type SPECIAL NAMES: adding ushort as a type SPECIAL NAMES: adding uint as a type SPECIAL NAMES: adding ulong as a type SPECIAL NAMES: adding __le16 as a type SPECIAL NAMES: adding __le32 as a type SPECIAL NAMES: adding __le64 as a type SPECIAL NAMES: adding __be16 as a type SPECIAL NAMES: adding __be32 as a type SPECIAL NAMES: adding __be64 as a type SPECIAL NAMES: adding wchar_t as a type No rules apply. Perhaps your semantic patch doesn't contain any +/-/* code, or you have a failed dependency. If the problem is not clear, try --debug-parse-cocci or check whether any virtual rules (e.g., patch) should be defined.
Kees Cook
maintainerRe: [PATCH v6 5/5] coccinelle: Add kmalloc_objs conversion script
Quoted 37 lines · Eric Biggers
Quoted 4 lines · Kees Cook
Finds and converts sized kmalloc-family of allocations into the typed kmalloc_obj-family of allocations.
Signed-off-by Kees Cook <[email protected]>Quoted 8 lines
---
Cc: Julia Lawall <[email protected]>
Cc: Nicolas Palix <[email protected]>
Cc: [email protected]--- scripts/coccinelle/api/kmalloc_objs.cocci | 109 ++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 scripts/coccinelle/api/kmalloc_objs.cocciIs there a way to reproduce commit
69050f8d6d075dcusing this semantic patch as claimed? I spend a while installing the latest version of spatch (which was quite hard to do due to all the unusual dependencies), but it complains that no rules apply:$ /usr/local/bin/spatch --sp-file scripts/coccinelle/api/kmalloc_objs.cocci --dir . --in-place init_defs_builtins: /usr/local/lib/coccinelle/standard.h SPECIAL NAMES: adding u8 as a type SPECIAL NAMES: adding u16 as a type SPECIAL NAMES: adding u32 as a type SPECIAL NAMES: adding u64 as a type SPECIAL NAMES: adding __u8 as a type SPECIAL NAMES: adding __u16 as a type SPECIAL NAMES: adding __u32 as a type SPECIAL NAMES: adding __u64 as a type SPECIAL NAMES: adding uint8_t as a type SPECIAL NAMES: adding uint16_t as a type SPECIAL NAMES: adding uint32_t as a type SPECIAL NAMES: adding uint64_t as a type SPECIAL NAMES: adding uchar as a type SPECIAL NAMES: adding ushort as a type SPECIAL NAMES: adding uint as a type SPECIAL NAMES: adding ulong as a type
Quoted 8 lines
SPECIAL NAMES: adding __le16 as a type SPECIAL NAMES: adding __le32 as a type SPECIAL NAMES: adding __le64 as a type SPECIAL NAMES: adding __be16 as a type SPECIAL NAMES: adding __be32 as a type SPECIAL NAMES: adding __be64 as a type SPECIAL NAMES: adding wchar_t as a type No rules apply. Perhaps your semantic patch doesn't contain any +/-/* code, or you have a failed dependency. If the problem is not clear, try --debug-parse-cocci or check whether any virtual rules (e.g., patch) should be defined.
I'm running:
$ spatch --version spatch version 1.1.1-00467-g578998d7826c compiled with OCaml version 4.13.1
Running Coccinelle scripts is normally done with the coccicheck target:
$ make coccicheck V=1 MODE=patch COCCI=scripts/coccinelle/api/kmalloc_objs.cocci
-Kees
Signature · 1 line
Kees Cook
Julia Lawall
maintainerRe: [PATCH v6 5/5] coccinelle: Add kmalloc_objs conversion script
In reply to Eric BiggersQuoted 14 lines · Eric Biggers
Quoted 4 lines · Kees Cook
Finds and converts sized kmalloc-family of allocations into the typed kmalloc_obj-family of allocations.
Signed-off-by Kees Cook <[email protected]>Quoted 8 lines
---
Cc: Julia Lawall <[email protected]>
Cc: Nicolas Palix <[email protected]>
Cc: [email protected]--- scripts/coccinelle/api/kmalloc_objs.cocci | 109 ++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 scripts/coccinelle/api/kmalloc_objs.cocci
Quoted 4 lines
Is there a way to reproduce commit
69050f8d6d075dcusing this semantic patch as claimed? I spend a while installing the latest version of spatch (which was quite hard to do due to all the unusual dependencies), but it complains that no rules apply:
I guess you would have to write on the command line -D patch?
julia
Quoted 28 lines
$ /usr/local/bin/spatch --sp-file scripts/coccinelle/api/kmalloc_objs.cocci --dir . --in-place init_defs_builtins: /usr/local/lib/coccinelle/standard.h SPECIAL NAMES: adding u8 as a type SPECIAL NAMES: adding u16 as a type SPECIAL NAMES: adding u32 as a type SPECIAL NAMES: adding u64 as a type SPECIAL NAMES: adding __u8 as a type SPECIAL NAMES: adding __u16 as a type SPECIAL NAMES: adding __u32 as a type SPECIAL NAMES: adding __u64 as a type SPECIAL NAMES: adding uint8_t as a type SPECIAL NAMES: adding uint16_t as a type SPECIAL NAMES: adding uint32_t as a type SPECIAL NAMES: adding uint64_t as a type SPECIAL NAMES: adding uchar as a type SPECIAL NAMES: adding ushort as a type SPECIAL NAMES: adding uint as a type SPECIAL NAMES: adding ulong as a type SPECIAL NAMES: adding __le16 as a type SPECIAL NAMES: adding __le32 as a type SPECIAL NAMES: adding __le64 as a type SPECIAL NAMES: adding __be16 as a type SPECIAL NAMES: adding __be32 as a type SPECIAL NAMES: adding __be64 as a type SPECIAL NAMES: adding wchar_t as a type No rules apply. Perhaps your semantic patch doesn't contain any +/-/* code, or you have a failed dependency. If the problem is not clear, try --debug-parse-cocci or check whether any virtual rules (e.g., patch) should be defined.
Kees Cook
maintainerQuoted 1 line
Subject: Re: [PATCH v6 0/5] asdf
*sigh* Should have been:
[PATCH v6 0/5] slab: Introduce kmalloc_obj() and family
Signature · 1 line
Kees Cook