History

Merge tag 'kmalloc_obj-v7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull kmalloc_obj updates from Kees Cook: "Introduce the kmalloc_obj* family of APIs for switching to type-based kmalloc allocations, away from purely size-based allocations. Discussed on lkml, with you, and at Linux Plumbers. It's been in -next for the entire dev cycle. Before the merge window closes, I'd like to send the treewide change (generated from the Coccinelle script included here), which mechanically converts almost 20k callsites from kmalloc* to kmalloc_obj*: 8007 files changed, 19980 insertions(+), 20838 deletions(-) This change needed fixes for mismatched types (since now the return type from allocations is a pointer to the requested type, not "void *"), and I've been fixing these over the last 4 releases. These fixes have mostly been trivial mismatches with const qualifiers or accidentally identical sizes (e.g. same object size: "struct kvec" vs "struct iovec", or differing pointers to pointers), but I did catch one case of too-small allocation. Summary: - Introduce kmalloc_obj*() family of type-based allocator APIs - checkpatch: Suggest kmalloc_obj family for sizeof allocations - coccinelle: Add kmalloc_objs conversion script" * tag 'kmalloc_obj-v7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: coccinelle: Add kmalloc_objs conversion script slab: Introduce kmalloc_flex() and family compiler_types: Introduce __flex_counter() and family checkpatch: Suggest kmalloc_obj family for sizeof allocations slab: Introduce kmalloc_obj() and family

Linus Torvalds committed 9 months ago

Commit 958f7fb2 parents 85f24b0 bdc50716 files · +367 −6Browse files

Showing the changes to scripts (2 of 6 files). Show all

Unified · Split

2 files
  1. scripts/checkpatch.pl +33 −6
  2. scripts/coccinelle/api/kmalloc_objs.cocci +124 −0
scripts/checkpatch.pl+33−6
@@ -7260,17 +7260,42 @@ sub process { · 7259 unmodified lines
7260 "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);7260 "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
7261 }7261 }
7262 7262
7263# check for (kv|k)[mz]alloc with multiplies that could be kmalloc_array/kvmalloc_array/kvcalloc/kcalloc7263# check for (kv|k)[mz]alloc that could be kmalloc_obj/kvmalloc_obj/kzalloc_obj/kvzalloc_obj
7264 if ($perl_version_ok &&
7265 defined $stat &&
7266 $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*,/) {
7267 my $oldfunc = $3;
7268 my $a1 = $4;
7269 my $newfunc = "kmalloc_obj";
7270 $newfunc = "kvmalloc_obj" if ($oldfunc eq "kvmalloc");
7271 $newfunc = "kvzalloc_obj" if ($oldfunc eq "kvzalloc");
7272 $newfunc = "kzalloc_obj" if ($oldfunc eq "kzalloc");
7273
7274 if ($a1 =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/) {
7275 my $cnt = statement_rawlines($stat);
7276 my $herectx = get_stat_here($linenr, $cnt, $here);
7277
7278 if (WARN("ALLOC_WITH_SIZEOF",
7279 "Prefer $newfunc over $oldfunc with sizeof\n" . $herectx) &&
7280 $cnt == 1 &&
7281 $fix) {
7282 $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*,/$1 = $newfunc($a1,/;
7283 }
7284 }
7285 }
7286
7287
7288# check for (kv|k)[mz]alloc with multiplies that could be kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs
7264 if ($perl_version_ok &&7289 if ($perl_version_ok &&
7265 defined $stat &&7290 defined $stat &&
7266 $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {7291 $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
7267 my $oldfunc = $3;7292 my $oldfunc = $3;
7268 my $a1 = $4;7293 my $a1 = $4;
7269 my $a2 = $10;7294 my $a2 = $10;
7270 my $newfunc = "kmalloc_array";7295 my $newfunc = "kmalloc_objs";
7271 $newfunc = "kvmalloc_array" if ($oldfunc eq "kvmalloc");7296 $newfunc = "kvmalloc_objs" if ($oldfunc eq "kvmalloc");
7272 $newfunc = "kvcalloc" if ($oldfunc eq "kvzalloc");7297 $newfunc = "kvzalloc_objs" if ($oldfunc eq "kvzalloc");
7273 $newfunc = "kcalloc" if ($oldfunc eq "kzalloc");7298 $newfunc = "kzalloc_objs" if ($oldfunc eq "kzalloc");
7274 my $r1 = $a1;7299 my $r1 = $a1;
7275 my $r2 = $a2;7300 my $r2 = $a2;
7276 if ($a1 =~ /^sizeof\s*\S/) {7301 if ($a1 =~ /^sizeof\s*\S/) {
@@ -7286,7 +7311,9 @@ sub process { · 9 unmodified lines
7286 "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&7311 "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
7287 $cnt == 1 &&7312 $cnt == 1 &&
7288 $fix) {7313 $fix) {
7289 $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;7314 my $sized = trim($r2);
7315 $sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;
7316 $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;
7290 }7317 }
7291 }7318 }
7292 }7319 }
scripts/coccinelle/api/kmalloc_objs.cocci+124−0
@@ -0,0 +1,124 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/// Use kmalloc_obj family of macros for allocations
3///
4// Confidence: High
5// Options: --include-headers-for-types --all-includes --include-headers --keep-comments
6
7virtual patch
8
9@initialize:python@
10@@
11import sys
12
13def alloc_array(name):
14 func = "FAILED_RENAME"
15 if name == "kmalloc_array":
16 func = "kmalloc_objs"
17 elif name == "kvmalloc_array":
18 func = "kvmalloc_objs"
19 elif name == "kcalloc":
20 func = "kzalloc_objs"
21 elif name == "kvcalloc":
22 func = "kvzalloc_objs"
23 else:
24 print(f"Unknown transform for {name}", file=sys.stderr)
25 return func
26
27// This excludes anything that is assigning to or from integral types or
28// string literals. Everything else gets the sizeof() extracted for the
29// kmalloc_obj() type/var argument. sizeof(void *) is also excluded because
30// it will need case-by-case double-checking to make sure the right type is
31// being assigned.
32@direct depends on patch && !(file in "tools") && !(file in "samples")@
33typedef u8, u16, u32, u64;
34typedef __u8, __u16, __u32, __u64;
35typedef uint8_t, uint16_t, uint32_t, uint64_t;
36typedef uchar, ushort, uint, ulong;
37typedef __le16, __le32, __le64;
38typedef __be16, __be32, __be64;
39typedef wchar_t;
40type INTEGRAL = {u8,__u8,uint8_t,char,unsigned char,uchar,wchar_t,
41 u16,__u16,uint16_t,unsigned short,ushort,
42 u32,__u32,uint32_t,unsigned int,uint,
43 u64,__u64,uint64_t,unsigned long,ulong,
44 __le16,__le32,__le64,__be16,__be32,__be64};
45char [] STRING;
46INTEGRAL *BYTES;
47INTEGRAL **BYTES_PTRS;
48type TYPE;
49expression VAR;
50expression GFP;
51expression COUNT;
52expression FLEX;
53expression E;
54identifier ALLOC =~ "^kv?[mz]alloc$";
55fresh identifier ALLOC_OBJ = ALLOC ## "_obj";
56fresh identifier ALLOC_FLEX = ALLOC ## "_flex";
57identifier ALLOC_ARRAY = {kmalloc_array,kvmalloc_array,kcalloc,kvcalloc};
58fresh identifier ALLOC_OBJS = script:python(ALLOC_ARRAY) { alloc_array(ALLOC_ARRAY) };
59@@
60
61(
62- VAR = ALLOC((sizeof(*VAR)), GFP)
63+ VAR = ALLOC_OBJ(*VAR, GFP)
64|
65 ALLOC((\(sizeof(STRING)\|sizeof(INTEGRAL)\|sizeof(INTEGRAL *)\)), GFP)
66|
67 BYTES = ALLOC((sizeof(E)), GFP)
68|
69 BYTES = ALLOC((sizeof(TYPE)), GFP)
70|
71 BYTES_PTRS = ALLOC((sizeof(E)), GFP)
72|
73 BYTES_PTRS = ALLOC((sizeof(TYPE)), GFP)
74|
75 ALLOC((sizeof(void *)), GFP)
76|
77- ALLOC((sizeof(E)), GFP)
78+ ALLOC_OBJ(E, GFP)
79|
80- ALLOC((sizeof(TYPE)), GFP)
81+ ALLOC_OBJ(TYPE, GFP)
82|
83 ALLOC_ARRAY(COUNT, (\(sizeof(STRING)\|sizeof(INTEGRAL)\|sizeof(INTEGRAL *)\)), GFP)
84|
85 BYTES = ALLOC_ARRAY(COUNT, (sizeof(E)), GFP)
86|
87 BYTES = ALLOC_ARRAY(COUNT, (sizeof(TYPE)), GFP)
88|
89 BYTES_PTRS = ALLOC_ARRAY(COUNT, (sizeof(E)), GFP)
90|
91 BYTES_PTRS = ALLOC_ARRAY(COUNT, (sizeof(TYPE)), GFP)
92|
93 ALLOC_ARRAY((\(sizeof(STRING)\|sizeof(INTEGRAL)\|sizeof(INTEGRAL *)\)), COUNT, GFP)
94|
95 BYTES = ALLOC_ARRAY((sizeof(E)), COUNT, GFP)
96|
97 BYTES = ALLOC_ARRAY((sizeof(TYPE)), COUNT, GFP)
98|
99 BYTES_PTRS = ALLOC_ARRAY((sizeof(E)), COUNT, GFP)
100|
101 BYTES_PTRS = ALLOC_ARRAY((sizeof(TYPE)), COUNT, GFP)
102|
103 ALLOC_ARRAY(COUNT, (sizeof(void *)), GFP)
104|
105 ALLOC_ARRAY((sizeof(void *)), COUNT, GFP)
106|
107- ALLOC_ARRAY(COUNT, (sizeof(E)), GFP)
108+ ALLOC_OBJS(E, COUNT, GFP)
109|
110- ALLOC_ARRAY(COUNT, (sizeof(TYPE)), GFP)
111+ ALLOC_OBJS(TYPE, COUNT, GFP)
112|
113- ALLOC_ARRAY((sizeof(E)), COUNT, GFP)
114+ ALLOC_OBJS(E, COUNT, GFP)
115|
116- ALLOC_ARRAY((sizeof(TYPE)), COUNT, GFP)
117+ ALLOC_OBJS(TYPE, COUNT, GFP)
118|
119- ALLOC(struct_size(VAR, FLEX, COUNT), GFP)
120+ ALLOC_FLEX(*VAR, FLEX, COUNT, GFP)
121|
122- ALLOC(struct_size_t(TYPE, FLEX, COUNT), GFP)
123+ ALLOC_FLEX(TYPE, FLEX, COUNT, GFP)
124)