Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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.

Link: https://lore.kernel.org/all/CAHk-=wiCOTW5UftUrAnvJkr6769D29tF7Of79gUjdQHS_TkF5A@mail.gmail.com/ [1]
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Link: https://patch.msgid.link/20251203233036.3212363-1-kees@kernel.org
Signed-off-by: Kees Cook <kees@kernel.org>

Kees Cook 2932ba8d 9448598b

+82
+24
Documentation/process/deprecated.rst
··· 372 372 DECLARE_FLEX_ARRAY(struct type2, two); 373 373 }; 374 374 }; 375 + 376 + Open-coded kmalloc assignments for struct objects 377 + ------------------------------------------------- 378 + Performing open-coded kmalloc()-family allocation assignments prevents 379 + the kernel (and compiler) from being able to examine the type of the 380 + variable being assigned, which limits any related introspection that 381 + may help with alignment, wrap-around, or additional hardening. The 382 + kmalloc_obj()-family of macros provide this introspection, which can be 383 + used for the common code patterns for single, array, and flexible object 384 + allocations. For example, these open coded assignments:: 385 + 386 + ptr = kmalloc(sizeof(*ptr), gfp); 387 + ptr = kzalloc(sizeof(*ptr), gfp); 388 + ptr = kmalloc_array(count, sizeof(*ptr), gfp); 389 + ptr = kcalloc(count, sizeof(*ptr), gfp); 390 + ptr = kmalloc(sizeof(struct foo, gfp); 391 + 392 + become, respectively:: 393 + 394 + ptr = kmalloc_obj(*ptr, gfp); 395 + ptr = kzalloc_obj(*ptr, gfp); 396 + ptr = kmalloc_objs(*ptr, count, gfp); 397 + ptr = kzalloc_objs(*ptr, count, gfp); 398 + __auto_type ptr = kmalloc_obj(struct foo, gfp);
+58
include/linux/slab.h
··· 12 12 #ifndef _LINUX_SLAB_H 13 13 #define _LINUX_SLAB_H 14 14 15 + #include <linux/bug.h> 15 16 #include <linux/cache.h> 16 17 #include <linux/gfp.h> 17 18 #include <linux/overflow.h> ··· 965 964 966 965 void *kmalloc_nolock_noprof(size_t size, gfp_t gfp_flags, int node); 967 966 #define kmalloc_nolock(...) alloc_hooks(kmalloc_nolock_noprof(__VA_ARGS__)) 967 + 968 + /** 969 + * __alloc_objs - Allocate objects of a given type using 970 + * @KMALLOC: which size-based kmalloc wrapper to allocate with. 971 + * @GFP: GFP flags for the allocation. 972 + * @TYPE: type to allocate space for. 973 + * @COUNT: how many @TYPE objects to allocate. 974 + * 975 + * Returns: Newly allocated pointer to (first) @TYPE of @COUNT-many 976 + * allocated @TYPE objects, or NULL on failure. 977 + */ 978 + #define __alloc_objs(KMALLOC, GFP, TYPE, COUNT) \ 979 + ({ \ 980 + const size_t __obj_size = size_mul(sizeof(TYPE), COUNT); \ 981 + (TYPE *)KMALLOC(__obj_size, GFP); \ 982 + }) 983 + 984 + /** 985 + * kmalloc_obj - Allocate a single instance of the given type 986 + * @VAR_OR_TYPE: Variable or type to allocate. 987 + * @GFP: GFP flags for the allocation. 988 + * 989 + * Returns: newly allocated pointer to a @VAR_OR_TYPE on success, or NULL 990 + * on failure. 991 + */ 992 + #define kmalloc_obj(VAR_OR_TYPE, GFP) \ 993 + __alloc_objs(kmalloc, GFP, typeof(VAR_OR_TYPE), 1) 994 + 995 + /** 996 + * kmalloc_objs - Allocate an array of the given type 997 + * @VAR_OR_TYPE: Variable or type to allocate an array of. 998 + * @COUNT: How many elements in the array. 999 + * @GFP: GFP flags for the allocation. 1000 + * 1001 + * Returns: newly allocated pointer to array of @VAR_OR_TYPE on success, 1002 + * or NULL on failure. 1003 + */ 1004 + #define kmalloc_objs(VAR_OR_TYPE, COUNT, GFP) \ 1005 + __alloc_objs(kmalloc, GFP, typeof(VAR_OR_TYPE), COUNT) 1006 + 1007 + /* All kzalloc aliases for kmalloc_(obj|objs|flex). */ 1008 + #define kzalloc_obj(P, GFP) \ 1009 + __alloc_objs(kzalloc, GFP, typeof(P), 1) 1010 + #define kzalloc_objs(P, COUNT, GFP) \ 1011 + __alloc_objs(kzalloc, GFP, typeof(P), COUNT) 1012 + 1013 + /* All kvmalloc aliases for kmalloc_(obj|objs|flex). */ 1014 + #define kvmalloc_obj(P, GFP) \ 1015 + __alloc_objs(kvmalloc, GFP, typeof(P), 1) 1016 + #define kvmalloc_objs(P, COUNT, GFP) \ 1017 + __alloc_objs(kvmalloc, GFP, typeof(P), COUNT) 1018 + 1019 + /* All kvzalloc aliases for kmalloc_(obj|objs|flex). */ 1020 + #define kvzalloc_obj(P, GFP) \ 1021 + __alloc_objs(kvzalloc, GFP, typeof(P), 1) 1022 + #define kvzalloc_objs(P, COUNT, GFP) \ 1023 + __alloc_objs(kvzalloc, GFP, typeof(P), COUNT) 968 1024 969 1025 #define kmem_buckets_alloc(_b, _size, _flags) \ 970 1026 alloc_hooks(__kmalloc_node_noprof(PASS_BUCKET_PARAMS(_size, _b), _flags, NUMA_NO_NODE))