* [cocci] [PATCH v5 4/4] coccinelle: Add kmalloc_objs conversion script
[not found] <20251122014258.do.018-kees@kernel.org>
@ 2025-11-22 1:43 ` Kees Cook
2025-11-24 12:50 ` Markus Elfring
0 siblings, 1 reply; 3+ messages in thread
From: Kees Cook @ 2025-11-22 1:43 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Kees Cook, Julia Lawall, Nicolas Palix, cocci, Randy Dunlap,
Miguel Ojeda, Przemek Kitszel, Gustavo A. R. Silva,
Linus Torvalds, Matthew Wilcox, 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 | 168 ++++++++++++++++++++++
1 file changed, 168 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..39f82f014b17
--- /dev/null
+++ b/scripts/coccinelle/api/kmalloc_objs.cocci
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/// Use kmalloc_obj family of macros for allocations
+///
+// Confidence: High
+// Comments:
+// 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
+
+@assign_sizeof depends on patch && !(file in "tools") && !(file in "samples")@
+type TYPE;
+TYPE *P;
+TYPE INST;
+expression VAR;
+expression GFP;
+expression SIZE;
+identifier ALLOC =~ "^kv?[mz]alloc$";
+fresh identifier ALLOC_OBJ_SZ = ALLOC ## "_obj_sz";
+@@
+
+(
+- SIZE = sizeof(*VAR);
+ ... when != SIZE
+ VAR =
+- ALLOC(SIZE, GFP);
++ ALLOC_OBJ_SZ(*VAR, GFP, &SIZE);
+|
+- SIZE = (sizeof(TYPE));
+ ... when != SIZE
+ P =
+- ALLOC(SIZE, GFP);
++ ALLOC_OBJ_SZ(*P, GFP, &SIZE);
+|
+- SIZE = (sizeof(INST));
+ ... when != SIZE
+ P =
+- ALLOC(SIZE, GFP);
++ ALLOC_OBJ_SZ(*P, GFP, &SIZE);
+)
+
+@assign_struct_size depends on patch && !(file in "tools") && !(file in "samples")@
+type TYPE;
+TYPE *P;
+expression VAR;
+expression GFP;
+expression SIZE;
+expression FLEX;
+expression COUNT;
+identifier ALLOC =~ "^kv?[mz]alloc$";
+fresh identifier ALLOC_FLEX_SZ = ALLOC ## "_flex_sz";
+@@
+
+(
+- SIZE = struct_size(VAR, FLEX, COUNT);
+ ... when != SIZE
+ VAR =
+- ALLOC(SIZE, GFP);
++ ALLOC_FLEX_SZ(*VAR, FLEX, COUNT, GFP, &SIZE);
+|
+- SIZE = struct_size_t(TYPE, FLEX, COUNT);
+ ... when != SIZE
+ P =
+- ALLOC(SIZE, GFP);
++ ALLOC_FLEX_SZ(*P, FLEX, COUNT, GFP, &SIZE);
+)
+
+// 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 related [flat|nested] 3+ messages in thread