diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /scripts/coccinelle/api | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'scripts/coccinelle/api')
24 files changed, 3180 insertions, 0 deletions
diff --git a/scripts/coccinelle/api/alloc/alloc_cast.cocci b/scripts/coccinelle/api/alloc/alloc_cast.cocci new file mode 100644 index 000000000..f6f0ccdb6 --- /dev/null +++ b/scripts/coccinelle/api/alloc/alloc_cast.cocci | |||
@@ -0,0 +1,123 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// Remove casting the values returned by memory allocation functions | ||
3 | /// like kmalloc, kzalloc, kmem_cache_alloc, kmem_cache_zalloc etc. | ||
4 | /// | ||
5 | //# This makes an effort to find cases of casting of values returned by | ||
6 | //# kmalloc, kzalloc, kcalloc, kmem_cache_alloc, kmem_cache_zalloc, | ||
7 | //# kmem_cache_alloc_node, kmalloc_node and kzalloc_node and removes | ||
8 | //# the casting as it is not required. The result in the patch case may | ||
9 | //# need some reformatting. | ||
10 | // | ||
11 | // Confidence: High | ||
12 | // Copyright: (C) 2014 Himangi Saraogi | ||
13 | // Copyright: (C) 2017 Himanshu Jha | ||
14 | // Comments: | ||
15 | // Options: --no-includes --include-headers | ||
16 | // | ||
17 | |||
18 | virtual context | ||
19 | virtual patch | ||
20 | virtual org | ||
21 | virtual report | ||
22 | |||
23 | @initialize:python@ | ||
24 | @@ | ||
25 | import re | ||
26 | pattern = '__' | ||
27 | m = re.compile(pattern) | ||
28 | |||
29 | @r1 depends on context || patch@ | ||
30 | type T; | ||
31 | @@ | ||
32 | |||
33 | (T *) | ||
34 | \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\| | ||
35 | kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\| | ||
36 | dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\| | ||
37 | kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\| | ||
38 | pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\| | ||
39 | kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...) | ||
40 | |||
41 | //---------------------------------------------------------- | ||
42 | // For context mode | ||
43 | //---------------------------------------------------------- | ||
44 | |||
45 | @script:python depends on context@ | ||
46 | t << r1.T; | ||
47 | @@ | ||
48 | |||
49 | if m.search(t) != None: | ||
50 | cocci.include_match(False) | ||
51 | |||
52 | @depends on context && r1@ | ||
53 | type r1.T; | ||
54 | @@ | ||
55 | |||
56 | * (T *) | ||
57 | \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\| | ||
58 | kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\| | ||
59 | dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\| | ||
60 | kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\| | ||
61 | pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\| | ||
62 | kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...) | ||
63 | |||
64 | //---------------------------------------------------------- | ||
65 | // For patch mode | ||
66 | //---------------------------------------------------------- | ||
67 | |||
68 | @script:python depends on patch@ | ||
69 | t << r1.T; | ||
70 | @@ | ||
71 | |||
72 | if m.search(t) != None: | ||
73 | cocci.include_match(False) | ||
74 | |||
75 | @depends on patch && r1@ | ||
76 | type r1.T; | ||
77 | @@ | ||
78 | |||
79 | - (T *) | ||
80 | \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\| | ||
81 | kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\| | ||
82 | dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\| | ||
83 | kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\| | ||
84 | pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\| | ||
85 | kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...) | ||
86 | |||
87 | //---------------------------------------------------------- | ||
88 | // For org and report mode | ||
89 | //---------------------------------------------------------- | ||
90 | |||
91 | @r2 depends on org || report@ | ||
92 | type T; | ||
93 | position p; | ||
94 | @@ | ||
95 | |||
96 | (T@p *) | ||
97 | \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\| | ||
98 | kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\| | ||
99 | dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\| | ||
100 | kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\| | ||
101 | pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\| | ||
102 | kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...) | ||
103 | |||
104 | @script:python depends on org@ | ||
105 | p << r2.p; | ||
106 | t << r2.T; | ||
107 | @@ | ||
108 | |||
109 | if m.search(t) != None: | ||
110 | cocci.include_match(False) | ||
111 | else: | ||
112 | coccilib.org.print_safe_todo(p[0], t) | ||
113 | |||
114 | @script:python depends on report@ | ||
115 | p << r2.p; | ||
116 | t << r2.T; | ||
117 | @@ | ||
118 | |||
119 | if m.search(t) != None: | ||
120 | cocci.include_match(False) | ||
121 | else: | ||
122 | msg="WARNING: casting value returned by memory allocation function to (%s *) is useless." % (t) | ||
123 | coccilib.report.print_report(p[0], msg) | ||
diff --git a/scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci b/scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci new file mode 100644 index 000000000..9c61a23b3 --- /dev/null +++ b/scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci | |||
@@ -0,0 +1,85 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// | ||
3 | /// Use *_pool_zalloc rather than *_pool_alloc followed by memset with 0 | ||
4 | /// | ||
5 | // Copyright: (C) 2015 Intel Corp. | ||
6 | // Options: --no-includes --include-headers | ||
7 | // | ||
8 | // Keywords: dma_pool_zalloc, pci_pool_zalloc | ||
9 | // | ||
10 | |||
11 | virtual context | ||
12 | virtual patch | ||
13 | virtual org | ||
14 | virtual report | ||
15 | |||
16 | //---------------------------------------------------------- | ||
17 | // For context mode | ||
18 | //---------------------------------------------------------- | ||
19 | |||
20 | @depends on context@ | ||
21 | expression x; | ||
22 | statement S; | ||
23 | @@ | ||
24 | |||
25 | * x = \(dma_pool_alloc\|pci_pool_alloc\)(...); | ||
26 | if ((x==NULL) || ...) S | ||
27 | * memset(x,0, ...); | ||
28 | |||
29 | //---------------------------------------------------------- | ||
30 | // For patch mode | ||
31 | //---------------------------------------------------------- | ||
32 | |||
33 | @depends on patch@ | ||
34 | expression x; | ||
35 | expression a,b,c; | ||
36 | statement S; | ||
37 | @@ | ||
38 | |||
39 | - x = dma_pool_alloc(a,b,c); | ||
40 | + x = dma_pool_zalloc(a,b,c); | ||
41 | if ((x==NULL) || ...) S | ||
42 | - memset(x,0,...); | ||
43 | |||
44 | @depends on patch@ | ||
45 | expression x; | ||
46 | expression a,b,c; | ||
47 | statement S; | ||
48 | @@ | ||
49 | |||
50 | - x = pci_pool_alloc(a,b,c); | ||
51 | + x = pci_pool_zalloc(a,b,c); | ||
52 | if ((x==NULL) || ...) S | ||
53 | - memset(x,0,...); | ||
54 | |||
55 | //---------------------------------------------------------- | ||
56 | // For org and report mode | ||
57 | //---------------------------------------------------------- | ||
58 | |||
59 | @r depends on org || report@ | ||
60 | expression x; | ||
61 | expression a,b,c; | ||
62 | statement S; | ||
63 | position p; | ||
64 | @@ | ||
65 | |||
66 | x = @p\(dma_pool_alloc\|pci_pool_alloc\)(a,b,c); | ||
67 | if ((x==NULL) || ...) S | ||
68 | memset(x,0, ...); | ||
69 | |||
70 | @script:python depends on org@ | ||
71 | p << r.p; | ||
72 | x << r.x; | ||
73 | @@ | ||
74 | |||
75 | msg="%s" % (x) | ||
76 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
77 | coccilib.org.print_todo(p[0], msg_safe) | ||
78 | |||
79 | @script:python depends on report@ | ||
80 | p << r.p; | ||
81 | x << r.x; | ||
82 | @@ | ||
83 | |||
84 | msg="WARNING: *_pool_zalloc should be used for %s, instead of *_pool_alloc/memset" % (x) | ||
85 | coccilib.report.print_report(p[0], msg) | ||
diff --git a/scripts/coccinelle/api/alloc/zalloc-simple.cocci b/scripts/coccinelle/api/alloc/zalloc-simple.cocci new file mode 100644 index 000000000..b3d0c3c23 --- /dev/null +++ b/scripts/coccinelle/api/alloc/zalloc-simple.cocci | |||
@@ -0,0 +1,411 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// | ||
3 | /// Use zeroing allocator rather than allocator followed by memset with 0 | ||
4 | /// | ||
5 | /// This considers some simple cases that are common and easy to validate | ||
6 | /// Note in particular that there are no ...s in the rule, so all of the | ||
7 | /// matched code has to be contiguous | ||
8 | /// | ||
9 | // Confidence: High | ||
10 | // Copyright: (C) 2009-2010 Julia Lawall, Nicolas Palix, DIKU. | ||
11 | // Copyright: (C) 2009-2010 Gilles Muller, INRIA/LiP6. | ||
12 | // Copyright: (C) 2017 Himanshu Jha | ||
13 | // URL: http://coccinelle.lip6.fr/rules/kzalloc.html | ||
14 | // Options: --no-includes --include-headers | ||
15 | // | ||
16 | // Keywords: kmalloc, kzalloc | ||
17 | // Version min: < 2.6.12 kmalloc | ||
18 | // Version min: 2.6.14 kzalloc | ||
19 | // | ||
20 | |||
21 | virtual context | ||
22 | virtual patch | ||
23 | virtual org | ||
24 | virtual report | ||
25 | |||
26 | //---------------------------------------------------------- | ||
27 | // For context mode | ||
28 | //---------------------------------------------------------- | ||
29 | |||
30 | @depends on context@ | ||
31 | type T, T2; | ||
32 | expression x; | ||
33 | expression E1; | ||
34 | statement S; | ||
35 | @@ | ||
36 | |||
37 | * x = (T)\(kmalloc(E1, ...)\|vmalloc(E1)\|dma_alloc_coherent(...,E1,...)\| | ||
38 | kmalloc_node(E1, ...)\|kmem_cache_alloc(...)\|kmem_alloc(E1, ...)\| | ||
39 | devm_kmalloc(...,E1,...)\|kvmalloc(E1, ...)\|kvmalloc_node(E1,...)\); | ||
40 | if ((x==NULL) || ...) S | ||
41 | * memset((T2)x,0,E1); | ||
42 | |||
43 | //---------------------------------------------------------- | ||
44 | // For patch mode | ||
45 | //---------------------------------------------------------- | ||
46 | |||
47 | @depends on patch@ | ||
48 | type T, T2; | ||
49 | expression x; | ||
50 | expression E1,E2,E3,E4; | ||
51 | statement S; | ||
52 | @@ | ||
53 | |||
54 | ( | ||
55 | - x = kmalloc(E1,E2); | ||
56 | + x = kzalloc(E1,E2); | ||
57 | | | ||
58 | - x = (T *)kmalloc(E1,E2); | ||
59 | + x = kzalloc(E1,E2); | ||
60 | | | ||
61 | - x = (T)kmalloc(E1,E2); | ||
62 | + x = (T)kzalloc(E1,E2); | ||
63 | | | ||
64 | - x = vmalloc(E1); | ||
65 | + x = vzalloc(E1); | ||
66 | | | ||
67 | - x = (T *)vmalloc(E1); | ||
68 | + x = vzalloc(E1); | ||
69 | | | ||
70 | - x = (T)vmalloc(E1); | ||
71 | + x = (T)vzalloc(E1); | ||
72 | | | ||
73 | - x = kmalloc_node(E1,E2,E3); | ||
74 | + x = kzalloc_node(E1,E2,E3); | ||
75 | | | ||
76 | - x = (T *)kmalloc_node(E1,E2,E3); | ||
77 | + x = kzalloc_node(E1,E2,E3); | ||
78 | | | ||
79 | - x = (T)kmalloc_node(E1,E2,E3); | ||
80 | + x = (T)kzalloc_node(E1,E2,E3); | ||
81 | | | ||
82 | - x = kmem_cache_alloc(E3,E4); | ||
83 | + x = kmem_cache_zalloc(E3,E4); | ||
84 | | | ||
85 | - x = (T *)kmem_cache_alloc(E3,E4); | ||
86 | + x = kmem_cache_zalloc(E3,E4); | ||
87 | | | ||
88 | - x = (T)kmem_cache_alloc(E3,E4); | ||
89 | + x = (T)kmem_cache_zalloc(E3,E4); | ||
90 | | | ||
91 | - x = kmem_alloc(E1,E2); | ||
92 | + x = kmem_zalloc(E1,E2); | ||
93 | | | ||
94 | - x = (T *)kmem_alloc(E1,E2); | ||
95 | + x = kmem_zalloc(E1,E2); | ||
96 | | | ||
97 | - x = (T)kmem_alloc(E1,E2); | ||
98 | + x = (T)kmem_zalloc(E1,E2); | ||
99 | | | ||
100 | - x = devm_kmalloc(E2,E1,E3); | ||
101 | + x = devm_kzalloc(E2,E1,E3); | ||
102 | | | ||
103 | - x = (T *)devm_kmalloc(E2,E1,E3); | ||
104 | + x = devm_kzalloc(E2,E1,E3); | ||
105 | | | ||
106 | - x = (T)devm_kmalloc(E2,E1,E3); | ||
107 | + x = (T)devm_kzalloc(E2,E1,E3); | ||
108 | | | ||
109 | - x = kvmalloc(E1,E2); | ||
110 | + x = kvzalloc(E1,E2); | ||
111 | | | ||
112 | - x = (T *)kvmalloc(E1,E2); | ||
113 | + x = kvzalloc(E1,E2); | ||
114 | | | ||
115 | - x = (T)kvmalloc(E1,E2); | ||
116 | + x = (T)kvzalloc(E1,E2); | ||
117 | | | ||
118 | - x = kvmalloc_node(E1,E2,E3); | ||
119 | + x = kvzalloc_node(E1,E2,E3); | ||
120 | | | ||
121 | - x = (T *)kvmalloc_node(E1,E2,E3); | ||
122 | + x = kvzalloc_node(E1,E2,E3); | ||
123 | | | ||
124 | - x = (T)kvmalloc_node(E1,E2,E3); | ||
125 | + x = (T)kvzalloc_node(E1,E2,E3); | ||
126 | ) | ||
127 | if ((x==NULL) || ...) S | ||
128 | - memset((T2)x,0,E1); | ||
129 | |||
130 | @depends on patch@ | ||
131 | type T, T2; | ||
132 | expression x; | ||
133 | expression E1,E2,E3,E4; | ||
134 | statement S; | ||
135 | @@ | ||
136 | x = (T)dma_alloc_coherent(E1, E2, E3, E4); | ||
137 | if ((x==NULL) || ...) S | ||
138 | - memset((T2)x, 0, E2); | ||
139 | |||
140 | //---------------------------------------------------------- | ||
141 | // For org mode | ||
142 | //---------------------------------------------------------- | ||
143 | |||
144 | @r depends on org || report@ | ||
145 | type T, T2; | ||
146 | expression x; | ||
147 | expression E1,E2; | ||
148 | statement S; | ||
149 | position p; | ||
150 | @@ | ||
151 | |||
152 | x = (T)kmalloc@p(E1,E2); | ||
153 | if ((x==NULL) || ...) S | ||
154 | memset((T2)x,0,E1); | ||
155 | |||
156 | @script:python depends on org@ | ||
157 | p << r.p; | ||
158 | x << r.x; | ||
159 | @@ | ||
160 | |||
161 | msg="%s" % (x) | ||
162 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
163 | coccilib.org.print_todo(p[0], msg_safe) | ||
164 | |||
165 | @script:python depends on report@ | ||
166 | p << r.p; | ||
167 | x << r.x; | ||
168 | @@ | ||
169 | |||
170 | msg="WARNING: kzalloc should be used for %s, instead of kmalloc/memset" % (x) | ||
171 | coccilib.report.print_report(p[0], msg) | ||
172 | |||
173 | //----------------------------------------------------------------- | ||
174 | @r1 depends on org || report@ | ||
175 | type T, T2; | ||
176 | expression x; | ||
177 | expression E1; | ||
178 | statement S; | ||
179 | position p; | ||
180 | @@ | ||
181 | |||
182 | x = (T)vmalloc@p(E1); | ||
183 | if ((x==NULL) || ...) S | ||
184 | memset((T2)x,0,E1); | ||
185 | |||
186 | @script:python depends on org@ | ||
187 | p << r1.p; | ||
188 | x << r1.x; | ||
189 | @@ | ||
190 | |||
191 | msg="%s" % (x) | ||
192 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
193 | coccilib.org.print_todo(p[0], msg_safe) | ||
194 | |||
195 | @script:python depends on report@ | ||
196 | p << r1.p; | ||
197 | x << r1.x; | ||
198 | @@ | ||
199 | |||
200 | msg="WARNING: vzalloc should be used for %s, instead of vmalloc/memset" % (x) | ||
201 | coccilib.report.print_report(p[0], msg) | ||
202 | |||
203 | //----------------------------------------------------------------- | ||
204 | @r2 depends on org || report@ | ||
205 | type T, T2; | ||
206 | expression x; | ||
207 | expression E1,E2,E3,E4; | ||
208 | statement S; | ||
209 | position p; | ||
210 | @@ | ||
211 | |||
212 | x = (T)dma_alloc_coherent@p(E1,E2,E3,E4); | ||
213 | if ((x==NULL) || ...) S | ||
214 | memset((T2)x,0,E2); | ||
215 | |||
216 | @script:python depends on org@ | ||
217 | p << r2.p; | ||
218 | x << r2.x; | ||
219 | @@ | ||
220 | |||
221 | msg="%s" % (x) | ||
222 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
223 | coccilib.org.print_todo(p[0], msg_safe) | ||
224 | |||
225 | @script:python depends on report@ | ||
226 | p << r2.p; | ||
227 | x << r2.x; | ||
228 | @@ | ||
229 | |||
230 | msg="WARNING: dma_alloc_coherent used in %s already zeroes out memory, so memset is not needed" % (x) | ||
231 | coccilib.report.print_report(p[0], msg) | ||
232 | |||
233 | //----------------------------------------------------------------- | ||
234 | @r3 depends on org || report@ | ||
235 | type T, T2; | ||
236 | expression x; | ||
237 | expression E1,E2,E3; | ||
238 | statement S; | ||
239 | position p; | ||
240 | @@ | ||
241 | |||
242 | x = (T)kmalloc_node@p(E1,E2,E3); | ||
243 | if ((x==NULL) || ...) S | ||
244 | memset((T2)x,0,E1); | ||
245 | |||
246 | @script:python depends on org@ | ||
247 | p << r3.p; | ||
248 | x << r3.x; | ||
249 | @@ | ||
250 | |||
251 | msg="%s" % (x) | ||
252 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
253 | coccilib.org.print_todo(p[0], msg_safe) | ||
254 | |||
255 | @script:python depends on report@ | ||
256 | p << r3.p; | ||
257 | x << r3.x; | ||
258 | @@ | ||
259 | |||
260 | msg="WARNING: kzalloc_node should be used for %s, instead of kmalloc_node/memset" % (x) | ||
261 | coccilib.report.print_report(p[0], msg) | ||
262 | |||
263 | //----------------------------------------------------------------- | ||
264 | @r4 depends on org || report@ | ||
265 | type T, T2; | ||
266 | expression x; | ||
267 | expression E1,E2,E3; | ||
268 | statement S; | ||
269 | position p; | ||
270 | @@ | ||
271 | |||
272 | x = (T)kmem_cache_alloc@p(E2,E3); | ||
273 | if ((x==NULL) || ...) S | ||
274 | memset((T2)x,0,E1); | ||
275 | |||
276 | @script:python depends on org@ | ||
277 | p << r4.p; | ||
278 | x << r4.x; | ||
279 | @@ | ||
280 | |||
281 | msg="%s" % (x) | ||
282 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
283 | coccilib.org.print_todo(p[0], msg_safe) | ||
284 | |||
285 | @script:python depends on report@ | ||
286 | p << r4.p; | ||
287 | x << r4.x; | ||
288 | @@ | ||
289 | |||
290 | msg="WARNING: kmem_cache_zalloc should be used for %s, instead of kmem_cache_alloc/memset" % (x) | ||
291 | coccilib.report.print_report(p[0], msg) | ||
292 | |||
293 | //----------------------------------------------------------------- | ||
294 | @r5 depends on org || report@ | ||
295 | type T, T2; | ||
296 | expression x; | ||
297 | expression E1,E2; | ||
298 | statement S; | ||
299 | position p; | ||
300 | @@ | ||
301 | |||
302 | x = (T)kmem_alloc@p(E1,E2); | ||
303 | if ((x==NULL) || ...) S | ||
304 | memset((T2)x,0,E1); | ||
305 | |||
306 | @script:python depends on org@ | ||
307 | p << r5.p; | ||
308 | x << r5.x; | ||
309 | @@ | ||
310 | |||
311 | msg="%s" % (x) | ||
312 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
313 | coccilib.org.print_todo(p[0], msg_safe) | ||
314 | |||
315 | @script:python depends on report@ | ||
316 | p << r5.p; | ||
317 | x << r5.x; | ||
318 | @@ | ||
319 | |||
320 | msg="WARNING: kmem_zalloc should be used for %s, instead of kmem_alloc/memset" % (x) | ||
321 | coccilib.report.print_report(p[0], msg) | ||
322 | |||
323 | //----------------------------------------------------------------- | ||
324 | @r6 depends on org || report@ | ||
325 | type T, T2; | ||
326 | expression x; | ||
327 | expression E1,E2,E3; | ||
328 | statement S; | ||
329 | position p; | ||
330 | @@ | ||
331 | |||
332 | x = (T)devm_kmalloc@p(E2,E1,E3); | ||
333 | if ((x==NULL) || ...) S | ||
334 | memset((T2)x,0,E1); | ||
335 | |||
336 | @script:python depends on org@ | ||
337 | p << r6.p; | ||
338 | x << r6.x; | ||
339 | @@ | ||
340 | |||
341 | msg="%s" % (x) | ||
342 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
343 | coccilib.org.print_todo(p[0], msg_safe) | ||
344 | |||
345 | @script:python depends on report@ | ||
346 | p << r6.p; | ||
347 | x << r6.x; | ||
348 | @@ | ||
349 | |||
350 | msg="WARNING: devm_kzalloc should be used for %s, instead of devm_kmalloc/memset" % (x) | ||
351 | coccilib.report.print_report(p[0], msg) | ||
352 | |||
353 | //----------------------------------------------------------------- | ||
354 | @r7 depends on org || report@ | ||
355 | type T, T2; | ||
356 | expression x; | ||
357 | expression E1,E2; | ||
358 | statement S; | ||
359 | position p; | ||
360 | @@ | ||
361 | |||
362 | x = (T)kvmalloc@p(E1,E2); | ||
363 | if ((x==NULL) || ...) S | ||
364 | memset((T2)x,0,E1); | ||
365 | |||
366 | @script:python depends on org@ | ||
367 | p << r7.p; | ||
368 | x << r7.x; | ||
369 | @@ | ||
370 | |||
371 | msg="%s" % (x) | ||
372 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
373 | coccilib.org.print_todo(p[0], msg_safe) | ||
374 | |||
375 | @script:python depends on report@ | ||
376 | p << r7.p; | ||
377 | x << r7.x; | ||
378 | @@ | ||
379 | |||
380 | msg="WARNING: kvzalloc should be used for %s, instead of kvmalloc/memset" % (x) | ||
381 | coccilib.report.print_report(p[0], msg) | ||
382 | |||
383 | //----------------------------------------------------------------- | ||
384 | @r9 depends on org || report@ | ||
385 | type T, T2; | ||
386 | expression x; | ||
387 | expression E1,E2,E3; | ||
388 | statement S; | ||
389 | position p; | ||
390 | @@ | ||
391 | |||
392 | x = (T)kvmalloc_node@p(E1,E2,E3); | ||
393 | if ((x==NULL) || ...) S | ||
394 | memset((T2)x,0,E1); | ||
395 | |||
396 | @script:python depends on org@ | ||
397 | p << r9.p; | ||
398 | x << r9.x; | ||
399 | @@ | ||
400 | |||
401 | msg="%s" % (x) | ||
402 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
403 | coccilib.org.print_todo(p[0], msg_safe) | ||
404 | |||
405 | @script:python depends on report@ | ||
406 | p << r9.p; | ||
407 | x << r9.x; | ||
408 | @@ | ||
409 | |||
410 | msg="WARNING: kvzalloc_node should be used for %s, instead of kvmalloc_node/memset" % (x) | ||
411 | coccilib.report.print_report(p[0], msg) | ||
diff --git a/scripts/coccinelle/api/atomic_as_refcounter.cocci b/scripts/coccinelle/api/atomic_as_refcounter.cocci new file mode 100644 index 000000000..0f78d94ab --- /dev/null +++ b/scripts/coccinelle/api/atomic_as_refcounter.cocci | |||
@@ -0,0 +1,130 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | // Check if refcount_t type and API should be used | ||
3 | // instead of atomic_t type when dealing with refcounters | ||
4 | // | ||
5 | // Copyright (c) 2016-2017, Elena Reshetova, Intel Corporation | ||
6 | // | ||
7 | // Confidence: Moderate | ||
8 | // URL: http://coccinelle.lip6.fr/ | ||
9 | // Options: --include-headers --very-quiet | ||
10 | |||
11 | virtual report | ||
12 | |||
13 | @r1 exists@ | ||
14 | identifier a, x; | ||
15 | position p1, p2; | ||
16 | identifier fname =~ ".*free.*"; | ||
17 | identifier fname2 =~ ".*destroy.*"; | ||
18 | identifier fname3 =~ ".*del.*"; | ||
19 | identifier fname4 =~ ".*queue_work.*"; | ||
20 | identifier fname5 =~ ".*schedule_work.*"; | ||
21 | identifier fname6 =~ ".*call_rcu.*"; | ||
22 | |||
23 | @@ | ||
24 | |||
25 | ( | ||
26 | atomic_dec_and_test@p1(&(a)->x) | ||
27 | | | ||
28 | atomic_dec_and_lock@p1(&(a)->x, ...) | ||
29 | | | ||
30 | atomic_long_dec_and_lock@p1(&(a)->x, ...) | ||
31 | | | ||
32 | atomic_long_dec_and_test@p1(&(a)->x) | ||
33 | | | ||
34 | atomic64_dec_and_test@p1(&(a)->x) | ||
35 | | | ||
36 | local_dec_and_test@p1(&(a)->x) | ||
37 | ) | ||
38 | ... | ||
39 | ( | ||
40 | fname@p2(a, ...); | ||
41 | | | ||
42 | fname2@p2(...); | ||
43 | | | ||
44 | fname3@p2(...); | ||
45 | | | ||
46 | fname4@p2(...); | ||
47 | | | ||
48 | fname5@p2(...); | ||
49 | | | ||
50 | fname6@p2(...); | ||
51 | ) | ||
52 | |||
53 | |||
54 | @script:python depends on report@ | ||
55 | p1 << r1.p1; | ||
56 | p2 << r1.p2; | ||
57 | @@ | ||
58 | msg = "atomic_dec_and_test variation before object free at line %s." | ||
59 | coccilib.report.print_report(p1[0], msg % (p2[0].line)) | ||
60 | |||
61 | @r4 exists@ | ||
62 | identifier a, x, y; | ||
63 | position p1, p2; | ||
64 | identifier fname =~ ".*free.*"; | ||
65 | |||
66 | @@ | ||
67 | |||
68 | ( | ||
69 | atomic_dec_and_test@p1(&(a)->x) | ||
70 | | | ||
71 | atomic_dec_and_lock@p1(&(a)->x, ...) | ||
72 | | | ||
73 | atomic_long_dec_and_lock@p1(&(a)->x, ...) | ||
74 | | | ||
75 | atomic_long_dec_and_test@p1(&(a)->x) | ||
76 | | | ||
77 | atomic64_dec_and_test@p1(&(a)->x) | ||
78 | | | ||
79 | local_dec_and_test@p1(&(a)->x) | ||
80 | ) | ||
81 | ... | ||
82 | y=a | ||
83 | ... | ||
84 | fname@p2(y, ...); | ||
85 | |||
86 | |||
87 | @script:python depends on report@ | ||
88 | p1 << r4.p1; | ||
89 | p2 << r4.p2; | ||
90 | @@ | ||
91 | msg = "atomic_dec_and_test variation before object free at line %s." | ||
92 | coccilib.report.print_report(p1[0], msg % (p2[0].line)) | ||
93 | |||
94 | @r2 exists@ | ||
95 | identifier a, x; | ||
96 | position p1; | ||
97 | @@ | ||
98 | |||
99 | ( | ||
100 | atomic_add_unless(&(a)->x,-1,1)@p1 | ||
101 | | | ||
102 | atomic_long_add_unless(&(a)->x,-1,1)@p1 | ||
103 | | | ||
104 | atomic64_add_unless(&(a)->x,-1,1)@p1 | ||
105 | ) | ||
106 | |||
107 | @script:python depends on report@ | ||
108 | p1 << r2.p1; | ||
109 | @@ | ||
110 | msg = "atomic_add_unless" | ||
111 | coccilib.report.print_report(p1[0], msg) | ||
112 | |||
113 | @r3 exists@ | ||
114 | identifier x; | ||
115 | position p1; | ||
116 | @@ | ||
117 | |||
118 | ( | ||
119 | x = atomic_add_return@p1(-1, ...); | ||
120 | | | ||
121 | x = atomic_long_add_return@p1(-1, ...); | ||
122 | | | ||
123 | x = atomic64_add_return@p1(-1, ...); | ||
124 | ) | ||
125 | |||
126 | @script:python depends on report@ | ||
127 | p1 << r3.p1; | ||
128 | @@ | ||
129 | msg = "x = atomic_add_return(-1, ...)" | ||
130 | coccilib.report.print_report(p1[0], msg) | ||
diff --git a/scripts/coccinelle/api/check_bq27xxx_data.cocci b/scripts/coccinelle/api/check_bq27xxx_data.cocci new file mode 100644 index 000000000..fae539ef0 --- /dev/null +++ b/scripts/coccinelle/api/check_bq27xxx_data.cocci | |||
@@ -0,0 +1,162 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// Detect BQ27XXX_DATA structures with identical registers, dm registers or | ||
3 | /// properties. | ||
4 | //# Doesn't unfold macros used in register or property fields. | ||
5 | //# Requires OCaml scripting | ||
6 | /// | ||
7 | // Confidence: High | ||
8 | // Copyright: (C) 2017 Julia Lawall, Inria/LIP6, | ||
9 | // URL: http://coccinelle.lip6.fr/ | ||
10 | // Requires: 1.0.7 | ||
11 | // Keywords: BQ27XXX_DATA | ||
12 | |||
13 | virtual report | ||
14 | |||
15 | @initialize:ocaml@ | ||
16 | @@ | ||
17 | |||
18 | let print_report p msg = | ||
19 | let p = List.hd p in | ||
20 | Printf.printf "%s:%d:%d-%d: %s" p.file p.line p.col p.col_end msg | ||
21 | |||
22 | @str depends on report@ | ||
23 | type t; | ||
24 | identifier i,i1,i2; | ||
25 | expression e1,e2; | ||
26 | @@ | ||
27 | |||
28 | t i[] = { | ||
29 | ..., | ||
30 | [e1] = BQ27XXX_DATA(i1,...), | ||
31 | ..., | ||
32 | [e2] = BQ27XXX_DATA(i2,...), | ||
33 | ..., | ||
34 | }; | ||
35 | |||
36 | @script:ocaml tocheck@ | ||
37 | i1 << str.i1; | ||
38 | i2 << str.i2; | ||
39 | i1regs; i2regs; | ||
40 | i1dmregs; i2dmregs; | ||
41 | i1props; i2props; | ||
42 | @@ | ||
43 | |||
44 | if not(i1 = i2) | ||
45 | then | ||
46 | begin | ||
47 | i1regs := make_ident (i1 ^ "_regs"); | ||
48 | i2regs := make_ident (i2 ^ "_regs"); | ||
49 | i1dmregs := make_ident (i1 ^ "_dm_regs"); | ||
50 | i2dmregs := make_ident (i2 ^ "_dm_regs"); | ||
51 | i1props := make_ident (i1 ^ "_props"); | ||
52 | i2props := make_ident (i2 ^ "_props") | ||
53 | end | ||
54 | |||
55 | (* ---------------------------------------------------------------- *) | ||
56 | |||
57 | @getregs1@ | ||
58 | typedef u8; | ||
59 | identifier tocheck.i1regs; | ||
60 | initializer list i1regs_vals; | ||
61 | position p1; | ||
62 | @@ | ||
63 | |||
64 | u8 i1regs@p1[...] = { i1regs_vals, }; | ||
65 | |||
66 | @getregs2@ | ||
67 | identifier tocheck.i2regs; | ||
68 | initializer list i2regs_vals; | ||
69 | position p2; | ||
70 | @@ | ||
71 | |||
72 | u8 i2regs@p2[...] = { i2regs_vals, }; | ||
73 | |||
74 | @script:ocaml@ | ||
75 | (_,i1regs_vals) << getregs1.i1regs_vals; | ||
76 | (_,i2regs_vals) << getregs2.i2regs_vals; | ||
77 | i1regs << tocheck.i1regs; | ||
78 | i2regs << tocheck.i2regs; | ||
79 | p1 << getregs1.p1; | ||
80 | p2 << getregs2.p2; | ||
81 | @@ | ||
82 | |||
83 | if i1regs < i2regs && | ||
84 | List.sort compare i1regs_vals = List.sort compare i2regs_vals | ||
85 | then | ||
86 | let msg = | ||
87 | Printf.sprintf | ||
88 | "WARNING %s and %s (line %d) are identical\n" | ||
89 | i1regs i2regs (List.hd p2).line in | ||
90 | print_report p1 msg | ||
91 | |||
92 | (* ---------------------------------------------------------------- *) | ||
93 | |||
94 | @getdmregs1@ | ||
95 | identifier tocheck.i1dmregs; | ||
96 | initializer list i1dmregs_vals; | ||
97 | position p1; | ||
98 | @@ | ||
99 | |||
100 | struct bq27xxx_dm_reg i1dmregs@p1[] = { i1dmregs_vals, }; | ||
101 | |||
102 | @getdmregs2@ | ||
103 | identifier tocheck.i2dmregs; | ||
104 | initializer list i2dmregs_vals; | ||
105 | position p2; | ||
106 | @@ | ||
107 | |||
108 | struct bq27xxx_dm_reg i2dmregs@p2[] = { i2dmregs_vals, }; | ||
109 | |||
110 | @script:ocaml@ | ||
111 | (_,i1dmregs_vals) << getdmregs1.i1dmregs_vals; | ||
112 | (_,i2dmregs_vals) << getdmregs2.i2dmregs_vals; | ||
113 | i1dmregs << tocheck.i1dmregs; | ||
114 | i2dmregs << tocheck.i2dmregs; | ||
115 | p1 << getdmregs1.p1; | ||
116 | p2 << getdmregs2.p2; | ||
117 | @@ | ||
118 | |||
119 | if i1dmregs < i2dmregs && | ||
120 | List.sort compare i1dmregs_vals = List.sort compare i2dmregs_vals | ||
121 | then | ||
122 | let msg = | ||
123 | Printf.sprintf | ||
124 | "WARNING %s and %s (line %d) are identical\n" | ||
125 | i1dmregs i2dmregs (List.hd p2).line in | ||
126 | print_report p1 msg | ||
127 | |||
128 | (* ---------------------------------------------------------------- *) | ||
129 | |||
130 | @getprops1@ | ||
131 | identifier tocheck.i1props; | ||
132 | initializer list[n1] i1props_vals; | ||
133 | position p1; | ||
134 | @@ | ||
135 | |||
136 | enum power_supply_property i1props@p1[] = { i1props_vals, }; | ||
137 | |||
138 | @getprops2@ | ||
139 | identifier tocheck.i2props; | ||
140 | initializer list[n2] i2props_vals; | ||
141 | position p2; | ||
142 | @@ | ||
143 | |||
144 | enum power_supply_property i2props@p2[] = { i2props_vals, }; | ||
145 | |||
146 | @script:ocaml@ | ||
147 | (_,i1props_vals) << getprops1.i1props_vals; | ||
148 | (_,i2props_vals) << getprops2.i2props_vals; | ||
149 | i1props << tocheck.i1props; | ||
150 | i2props << tocheck.i2props; | ||
151 | p1 << getprops1.p1; | ||
152 | p2 << getprops2.p2; | ||
153 | @@ | ||
154 | |||
155 | if i1props < i2props && | ||
156 | List.sort compare i1props_vals = List.sort compare i2props_vals | ||
157 | then | ||
158 | let msg = | ||
159 | Printf.sprintf | ||
160 | "WARNING %s and %s (line %d) are identical\n" | ||
161 | i1props i2props (List.hd p2).line in | ||
162 | print_report p1 msg | ||
diff --git a/scripts/coccinelle/api/d_find_alias.cocci b/scripts/coccinelle/api/d_find_alias.cocci new file mode 100644 index 000000000..47e050166 --- /dev/null +++ b/scripts/coccinelle/api/d_find_alias.cocci | |||
@@ -0,0 +1,81 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /// Make sure calls to d_find_alias() have a corresponding call to dput(). | ||
3 | // | ||
4 | // Keywords: d_find_alias, dput | ||
5 | // | ||
6 | // Confidence: Moderate | ||
7 | // URL: http://coccinelle.lip6.fr/ | ||
8 | // Options: --include-headers | ||
9 | |||
10 | virtual context | ||
11 | virtual org | ||
12 | virtual patch | ||
13 | virtual report | ||
14 | |||
15 | @r exists@ | ||
16 | local idexpression struct dentry *dent; | ||
17 | expression E, E1; | ||
18 | statement S1, S2; | ||
19 | position p1, p2; | ||
20 | @@ | ||
21 | ( | ||
22 | if (!(dent@p1 = d_find_alias(...))) S1 | ||
23 | | | ||
24 | dent@p1 = d_find_alias(...) | ||
25 | ) | ||
26 | |||
27 | <...when != dput(dent) | ||
28 | when != if (...) { <+... dput(dent) ...+> } | ||
29 | when != true !dent || ... | ||
30 | when != dent = E | ||
31 | when != E = dent | ||
32 | if (!dent || ...) S2 | ||
33 | ...> | ||
34 | ( | ||
35 | return <+...dent...+>; | ||
36 | | | ||
37 | return @p2 ...; | ||
38 | | | ||
39 | dent@p2 = E1; | ||
40 | | | ||
41 | E1 = dent; | ||
42 | ) | ||
43 | |||
44 | @depends on context@ | ||
45 | local idexpression struct dentry *r.dent; | ||
46 | position r.p1,r.p2; | ||
47 | @@ | ||
48 | * dent@p1 = ... | ||
49 | ... | ||
50 | ( | ||
51 | * return@p2 ...; | ||
52 | | | ||
53 | * dent@p2 | ||
54 | ) | ||
55 | |||
56 | |||
57 | @script:python depends on org@ | ||
58 | p1 << r.p1; | ||
59 | p2 << r.p2; | ||
60 | @@ | ||
61 | cocci.print_main("Missing call to dput()",p1) | ||
62 | cocci.print_secs("",p2) | ||
63 | |||
64 | @depends on patch@ | ||
65 | local idexpression struct dentry *r.dent; | ||
66 | position r.p2; | ||
67 | @@ | ||
68 | ( | ||
69 | + dput(dent); | ||
70 | return @p2 ...; | ||
71 | | | ||
72 | + dput(dent); | ||
73 | dent@p2 = ...; | ||
74 | ) | ||
75 | |||
76 | @script:python depends on report@ | ||
77 | p1 << r.p1; | ||
78 | p2 << r.p2; | ||
79 | @@ | ||
80 | msg = "Missing call to dput() at line %s." | ||
81 | coccilib.report.print_report(p1[0], msg % (p2[0].line)) | ||
diff --git a/scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci b/scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci new file mode 100644 index 000000000..7c3123105 --- /dev/null +++ b/scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci | |||
@@ -0,0 +1,68 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /// Use DEFINE_DEBUGFS_ATTRIBUTE rather than DEFINE_SIMPLE_ATTRIBUTE | ||
3 | /// for debugfs files. | ||
4 | /// | ||
5 | //# Rationale: DEFINE_SIMPLE_ATTRIBUTE + debugfs_create_file() | ||
6 | //# imposes some significant overhead as compared to | ||
7 | //# DEFINE_DEBUGFS_ATTRIBUTE + debugfs_create_file_unsafe(). | ||
8 | // | ||
9 | // Copyright (C): 2016 Nicolai Stange | ||
10 | // Options: --no-includes | ||
11 | // | ||
12 | |||
13 | virtual context | ||
14 | virtual patch | ||
15 | virtual org | ||
16 | virtual report | ||
17 | |||
18 | @dsa@ | ||
19 | declarer name DEFINE_SIMPLE_ATTRIBUTE; | ||
20 | identifier dsa_fops; | ||
21 | expression dsa_get, dsa_set, dsa_fmt; | ||
22 | position p; | ||
23 | @@ | ||
24 | DEFINE_SIMPLE_ATTRIBUTE@p(dsa_fops, dsa_get, dsa_set, dsa_fmt); | ||
25 | |||
26 | @dcf@ | ||
27 | expression name, mode, parent, data; | ||
28 | identifier dsa.dsa_fops; | ||
29 | @@ | ||
30 | debugfs_create_file(name, mode, parent, data, &dsa_fops) | ||
31 | |||
32 | |||
33 | @context_dsa depends on context && dcf@ | ||
34 | declarer name DEFINE_DEBUGFS_ATTRIBUTE; | ||
35 | identifier dsa.dsa_fops; | ||
36 | expression dsa.dsa_get, dsa.dsa_set, dsa.dsa_fmt; | ||
37 | @@ | ||
38 | * DEFINE_SIMPLE_ATTRIBUTE(dsa_fops, dsa_get, dsa_set, dsa_fmt); | ||
39 | |||
40 | |||
41 | @patch_dcf depends on patch expression@ | ||
42 | expression name, mode, parent, data; | ||
43 | identifier dsa.dsa_fops; | ||
44 | @@ | ||
45 | - debugfs_create_file(name, mode, parent, data, &dsa_fops) | ||
46 | + debugfs_create_file_unsafe(name, mode, parent, data, &dsa_fops) | ||
47 | |||
48 | @patch_dsa depends on patch_dcf && patch@ | ||
49 | identifier dsa.dsa_fops; | ||
50 | expression dsa.dsa_get, dsa.dsa_set, dsa.dsa_fmt; | ||
51 | @@ | ||
52 | - DEFINE_SIMPLE_ATTRIBUTE(dsa_fops, dsa_get, dsa_set, dsa_fmt); | ||
53 | + DEFINE_DEBUGFS_ATTRIBUTE(dsa_fops, dsa_get, dsa_set, dsa_fmt); | ||
54 | |||
55 | |||
56 | @script:python depends on org && dcf@ | ||
57 | fops << dsa.dsa_fops; | ||
58 | p << dsa.p; | ||
59 | @@ | ||
60 | msg="%s should be defined with DEFINE_DEBUGFS_ATTRIBUTE" % (fops) | ||
61 | coccilib.org.print_todo(p[0], msg) | ||
62 | |||
63 | @script:python depends on report && dcf@ | ||
64 | fops << dsa.dsa_fops; | ||
65 | p << dsa.p; | ||
66 | @@ | ||
67 | msg="WARNING: %s should be defined with DEFINE_DEBUGFS_ATTRIBUTE" % (fops) | ||
68 | coccilib.report.print_report(p[0], msg) | ||
diff --git a/scripts/coccinelle/api/device_attr_show.cocci b/scripts/coccinelle/api/device_attr_show.cocci new file mode 100644 index 000000000..a28dc0616 --- /dev/null +++ b/scripts/coccinelle/api/device_attr_show.cocci | |||
@@ -0,0 +1,55 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// | ||
3 | /// From Documentation/filesystems/sysfs.rst: | ||
4 | /// show() must not use snprintf() when formatting the value to be | ||
5 | /// returned to user space. If you can guarantee that an overflow | ||
6 | /// will never happen you can use sprintf() otherwise you must use | ||
7 | /// scnprintf(). | ||
8 | /// | ||
9 | // Confidence: High | ||
10 | // Copyright: (C) 2020 Denis Efremov ISPRAS | ||
11 | // Options: --no-includes --include-headers | ||
12 | // | ||
13 | |||
14 | virtual report | ||
15 | virtual org | ||
16 | virtual context | ||
17 | virtual patch | ||
18 | |||
19 | @r depends on !patch@ | ||
20 | identifier show, dev, attr, buf; | ||
21 | position p; | ||
22 | @@ | ||
23 | |||
24 | ssize_t show(struct device *dev, struct device_attribute *attr, char *buf) | ||
25 | { | ||
26 | <... | ||
27 | * return snprintf@p(...); | ||
28 | ...> | ||
29 | } | ||
30 | |||
31 | @rp depends on patch@ | ||
32 | identifier show, dev, attr, buf; | ||
33 | @@ | ||
34 | |||
35 | ssize_t show(struct device *dev, struct device_attribute *attr, char *buf) | ||
36 | { | ||
37 | <... | ||
38 | return | ||
39 | - snprintf | ||
40 | + scnprintf | ||
41 | (...); | ||
42 | ...> | ||
43 | } | ||
44 | |||
45 | @script: python depends on report@ | ||
46 | p << r.p; | ||
47 | @@ | ||
48 | |||
49 | coccilib.report.print_report(p[0], "WARNING: use scnprintf or sprintf") | ||
50 | |||
51 | @script: python depends on org@ | ||
52 | p << r.p; | ||
53 | @@ | ||
54 | |||
55 | coccilib.org.print_todo(p[0], "WARNING: use scnprintf or sprintf") | ||
diff --git a/scripts/coccinelle/api/err_cast.cocci b/scripts/coccinelle/api/err_cast.cocci new file mode 100644 index 000000000..0e661c8d8 --- /dev/null +++ b/scripts/coccinelle/api/err_cast.cocci | |||
@@ -0,0 +1,57 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// | ||
3 | /// Use ERR_CAST inlined function instead of ERR_PTR(PTR_ERR(...)) | ||
4 | /// | ||
5 | // Confidence: High | ||
6 | // Copyright: (C) 2009, 2010 Nicolas Palix, DIKU. | ||
7 | // Copyright: (C) 2009, 2010 Julia Lawall, DIKU. | ||
8 | // Copyright: (C) 2009, 2010 Gilles Muller, INRIA/LiP6. | ||
9 | // URL: http://coccinelle.lip6.fr/ | ||
10 | // Options: | ||
11 | // | ||
12 | // Keywords: ERR_PTR, PTR_ERR, ERR_CAST | ||
13 | // Version min: 2.6.25 | ||
14 | // | ||
15 | |||
16 | virtual context | ||
17 | virtual patch | ||
18 | virtual org | ||
19 | virtual report | ||
20 | |||
21 | |||
22 | @ depends on context && !patch && !org && !report@ | ||
23 | expression x; | ||
24 | @@ | ||
25 | |||
26 | * ERR_PTR(PTR_ERR(x)) | ||
27 | |||
28 | @ depends on !context && patch && !org && !report @ | ||
29 | expression x; | ||
30 | @@ | ||
31 | |||
32 | - ERR_PTR(PTR_ERR(x)) | ||
33 | + ERR_CAST(x) | ||
34 | |||
35 | @r depends on !context && !patch && (org || report)@ | ||
36 | expression x; | ||
37 | position p; | ||
38 | @@ | ||
39 | |||
40 | ERR_PTR@p(PTR_ERR(x)) | ||
41 | |||
42 | @script:python depends on org@ | ||
43 | p << r.p; | ||
44 | x << r.x; | ||
45 | @@ | ||
46 | |||
47 | msg="WARNING ERR_CAST can be used with %s" % (x) | ||
48 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
49 | coccilib.org.print_todo(p[0], msg_safe) | ||
50 | |||
51 | @script:python depends on report@ | ||
52 | p << r.p; | ||
53 | x << r.x; | ||
54 | @@ | ||
55 | |||
56 | msg="WARNING: ERR_CAST can be used with %s" % (x) | ||
57 | coccilib.report.print_report(p[0], msg) | ||
diff --git a/scripts/coccinelle/api/kfree_mismatch.cocci b/scripts/coccinelle/api/kfree_mismatch.cocci new file mode 100644 index 000000000..d46a9b3eb --- /dev/null +++ b/scripts/coccinelle/api/kfree_mismatch.cocci | |||
@@ -0,0 +1,228 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// | ||
3 | /// Check that kvmalloc'ed memory is freed by kfree functions, | ||
4 | /// vmalloc'ed by vfree functions and kvmalloc'ed by kvfree | ||
5 | /// functions. | ||
6 | /// | ||
7 | // Confidence: High | ||
8 | // Copyright: (C) 2020 Denis Efremov ISPRAS | ||
9 | // Options: --no-includes --include-headers | ||
10 | // | ||
11 | |||
12 | virtual patch | ||
13 | virtual report | ||
14 | virtual org | ||
15 | virtual context | ||
16 | |||
17 | @alloc@ | ||
18 | expression E, E1; | ||
19 | position kok, vok; | ||
20 | @@ | ||
21 | |||
22 | ( | ||
23 | if (...) { | ||
24 | ... | ||
25 | E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\| | ||
26 | kmalloc_node\|kzalloc_node\|kmalloc_array\| | ||
27 | kmalloc_array_node\|kcalloc_node\)(...)@kok | ||
28 | ... | ||
29 | } else { | ||
30 | ... | ||
31 | E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\| | ||
32 | vzalloc_node\|vmalloc_exec\|vmalloc_32\| | ||
33 | vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\| | ||
34 | __vmalloc_node\)(...)@vok | ||
35 | ... | ||
36 | } | ||
37 | | | ||
38 | E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\|kmalloc_node\|kzalloc_node\| | ||
39 | kmalloc_array\|kmalloc_array_node\|kcalloc_node\)(...)@kok | ||
40 | ... when != E = E1 | ||
41 | when any | ||
42 | if (E == NULL) { | ||
43 | ... | ||
44 | E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\| | ||
45 | vzalloc_node\|vmalloc_exec\|vmalloc_32\| | ||
46 | vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\| | ||
47 | __vmalloc_node\)(...)@vok | ||
48 | ... | ||
49 | } | ||
50 | ) | ||
51 | |||
52 | @free@ | ||
53 | expression E; | ||
54 | position fok; | ||
55 | @@ | ||
56 | |||
57 | E = \(kvmalloc\|kvzalloc\|kvcalloc\|kvzalloc_node\|kvmalloc_node\| | ||
58 | kvmalloc_array\)(...) | ||
59 | ... | ||
60 | kvfree(E)@fok | ||
61 | |||
62 | @vfree depends on !patch@ | ||
63 | expression E; | ||
64 | position a != alloc.kok; | ||
65 | position f != free.fok; | ||
66 | @@ | ||
67 | |||
68 | * E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\|kmalloc_node\| | ||
69 | * kzalloc_node\|kmalloc_array\|kmalloc_array_node\| | ||
70 | * kcalloc_node\)(...)@a | ||
71 | ... when != if (...) { ... E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|__vmalloc_node\)(...); ... } | ||
72 | when != is_vmalloc_addr(E) | ||
73 | when any | ||
74 | * \(vfree\|vfree_atomic\|kvfree\)(E)@f | ||
75 | |||
76 | @depends on patch exists@ | ||
77 | expression E; | ||
78 | position a != alloc.kok; | ||
79 | position f != free.fok; | ||
80 | @@ | ||
81 | |||
82 | E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\|kmalloc_node\| | ||
83 | kzalloc_node\|kmalloc_array\|kmalloc_array_node\| | ||
84 | kcalloc_node\)(...)@a | ||
85 | ... when != if (...) { ... E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|__vmalloc_node\)(...); ... } | ||
86 | when != is_vmalloc_addr(E) | ||
87 | when any | ||
88 | - \(vfree\|vfree_atomic\|kvfree\)(E)@f | ||
89 | + kfree(E) | ||
90 | |||
91 | @kfree depends on !patch@ | ||
92 | expression E; | ||
93 | position a != alloc.vok; | ||
94 | position f != free.fok; | ||
95 | @@ | ||
96 | |||
97 | * E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\| | ||
98 | * vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\| | ||
99 | * __vmalloc_node_range\|__vmalloc_node\)(...)@a | ||
100 | ... when != is_vmalloc_addr(E) | ||
101 | when any | ||
102 | * \(kfree\|kfree_sensitive\|kvfree\)(E)@f | ||
103 | |||
104 | @depends on patch exists@ | ||
105 | expression E; | ||
106 | position a != alloc.vok; | ||
107 | position f != free.fok; | ||
108 | @@ | ||
109 | |||
110 | E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\| | ||
111 | vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\| | ||
112 | __vmalloc_node_range\|__vmalloc_node\)(...)@a | ||
113 | ... when != is_vmalloc_addr(E) | ||
114 | when any | ||
115 | - \(kfree\|kvfree\)(E)@f | ||
116 | + vfree(E) | ||
117 | |||
118 | @kvfree depends on !patch@ | ||
119 | expression E; | ||
120 | position a, f; | ||
121 | @@ | ||
122 | |||
123 | * E = \(kvmalloc\|kvzalloc\|kvcalloc\|kvzalloc_node\|kvmalloc_node\| | ||
124 | * kvmalloc_array\)(...)@a | ||
125 | ... when != is_vmalloc_addr(E) | ||
126 | when any | ||
127 | * \(kfree\|kfree_sensitive\|vfree\|vfree_atomic\)(E)@f | ||
128 | |||
129 | @depends on patch exists@ | ||
130 | expression E; | ||
131 | @@ | ||
132 | |||
133 | E = \(kvmalloc\|kvzalloc\|kvcalloc\|kvzalloc_node\|kvmalloc_node\| | ||
134 | kvmalloc_array\)(...) | ||
135 | ... when != is_vmalloc_addr(E) | ||
136 | when any | ||
137 | - \(kfree\|vfree\)(E) | ||
138 | + kvfree(E) | ||
139 | |||
140 | @kvfree_switch depends on !patch@ | ||
141 | expression alloc.E; | ||
142 | position f; | ||
143 | @@ | ||
144 | |||
145 | ... when != is_vmalloc_addr(E) | ||
146 | when any | ||
147 | * \(kfree\|kfree_sensitive\|vfree\|vfree_atomic\)(E)@f | ||
148 | |||
149 | @depends on patch exists@ | ||
150 | expression alloc.E; | ||
151 | position f; | ||
152 | @@ | ||
153 | |||
154 | ... when != is_vmalloc_addr(E) | ||
155 | when any | ||
156 | ( | ||
157 | - \(kfree\|vfree\)(E)@f | ||
158 | + kvfree(E) | ||
159 | | | ||
160 | - kfree_sensitive(E)@f | ||
161 | + kvfree_sensitive(E) | ||
162 | ) | ||
163 | |||
164 | @script: python depends on report@ | ||
165 | a << vfree.a; | ||
166 | f << vfree.f; | ||
167 | @@ | ||
168 | |||
169 | msg = "WARNING kmalloc is used to allocate this memory at line %s" % (a[0].line) | ||
170 | coccilib.report.print_report(f[0], msg) | ||
171 | |||
172 | @script: python depends on org@ | ||
173 | a << vfree.a; | ||
174 | f << vfree.f; | ||
175 | @@ | ||
176 | |||
177 | msg = "WARNING kmalloc is used to allocate this memory at line %s" % (a[0].line) | ||
178 | coccilib.org.print_todo(f[0], msg) | ||
179 | |||
180 | @script: python depends on report@ | ||
181 | a << kfree.a; | ||
182 | f << kfree.f; | ||
183 | @@ | ||
184 | |||
185 | msg = "WARNING vmalloc is used to allocate this memory at line %s" % (a[0].line) | ||
186 | coccilib.report.print_report(f[0], msg) | ||
187 | |||
188 | @script: python depends on org@ | ||
189 | a << kfree.a; | ||
190 | f << kfree.f; | ||
191 | @@ | ||
192 | |||
193 | msg = "WARNING vmalloc is used to allocate this memory at line %s" % (a[0].line) | ||
194 | coccilib.org.print_todo(f[0], msg) | ||
195 | |||
196 | @script: python depends on report@ | ||
197 | a << kvfree.a; | ||
198 | f << kvfree.f; | ||
199 | @@ | ||
200 | |||
201 | msg = "WARNING kvmalloc is used to allocate this memory at line %s" % (a[0].line) | ||
202 | coccilib.report.print_report(f[0], msg) | ||
203 | |||
204 | @script: python depends on org@ | ||
205 | a << kvfree.a; | ||
206 | f << kvfree.f; | ||
207 | @@ | ||
208 | |||
209 | msg = "WARNING kvmalloc is used to allocate this memory at line %s" % (a[0].line) | ||
210 | coccilib.org.print_todo(f[0], msg) | ||
211 | |||
212 | @script: python depends on report@ | ||
213 | ka << alloc.kok; | ||
214 | va << alloc.vok; | ||
215 | f << kvfree_switch.f; | ||
216 | @@ | ||
217 | |||
218 | msg = "WARNING kmalloc (line %s) && vmalloc (line %s) are used to allocate this memory" % (ka[0].line, va[0].line) | ||
219 | coccilib.report.print_report(f[0], msg) | ||
220 | |||
221 | @script: python depends on org@ | ||
222 | ka << alloc.kok; | ||
223 | va << alloc.vok; | ||
224 | f << kvfree_switch.f; | ||
225 | @@ | ||
226 | |||
227 | msg = "WARNING kmalloc (line %s) && vmalloc (line %s) are used to allocate this memory" % (ka[0].line, va[0].line) | ||
228 | coccilib.org.print_todo(f[0], msg) | ||
diff --git a/scripts/coccinelle/api/kfree_sensitive.cocci b/scripts/coccinelle/api/kfree_sensitive.cocci new file mode 100644 index 000000000..8d980ebf3 --- /dev/null +++ b/scripts/coccinelle/api/kfree_sensitive.cocci | |||
@@ -0,0 +1,100 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// | ||
3 | /// Use kfree_sensitive, kvfree_sensitive rather than memset or | ||
4 | /// memzero_explicit followed by kfree. | ||
5 | /// | ||
6 | // Confidence: High | ||
7 | // Copyright: (C) 2020 Denis Efremov ISPRAS | ||
8 | // Options: --no-includes --include-headers | ||
9 | // | ||
10 | // Keywords: kfree_sensitive, kvfree_sensitive | ||
11 | // | ||
12 | |||
13 | virtual context | ||
14 | virtual patch | ||
15 | virtual org | ||
16 | virtual report | ||
17 | |||
18 | @initialize:python@ | ||
19 | @@ | ||
20 | # kmalloc_oob_in_memset uses memset to explicitly trigger out-of-bounds access | ||
21 | filter = frozenset(['kmalloc_oob_in_memset', | ||
22 | 'kfree_sensitive', 'kvfree_sensitive']) | ||
23 | |||
24 | def relevant(p): | ||
25 | return not (filter & {el.current_element for el in p}) | ||
26 | |||
27 | @cond@ | ||
28 | position ok; | ||
29 | @@ | ||
30 | |||
31 | if (...) | ||
32 | \(memset@ok\|memzero_explicit@ok\)(...); | ||
33 | |||
34 | @r depends on !patch forall@ | ||
35 | expression E; | ||
36 | position p : script:python() { relevant(p) }; | ||
37 | position m != cond.ok; | ||
38 | type T; | ||
39 | @@ | ||
40 | |||
41 | ( | ||
42 | * memset@m((T)E, 0, ...); | ||
43 | | | ||
44 | * memzero_explicit@m((T)E, ...); | ||
45 | ) | ||
46 | ... when != E | ||
47 | when strict | ||
48 | * \(kfree\|vfree\|kvfree\)(E)@p; | ||
49 | |||
50 | @rp_memzero depends on patch@ | ||
51 | expression E, size; | ||
52 | position p : script:python() { relevant(p) }; | ||
53 | position m != cond.ok; | ||
54 | type T; | ||
55 | @@ | ||
56 | |||
57 | - memzero_explicit@m((T)E, size); | ||
58 | ... when != E | ||
59 | when strict | ||
60 | ( | ||
61 | - kfree(E)@p; | ||
62 | + kfree_sensitive(E); | ||
63 | | | ||
64 | - \(vfree\|kvfree\)(E)@p; | ||
65 | + kvfree_sensitive(E, size); | ||
66 | ) | ||
67 | |||
68 | @rp_memset depends on patch@ | ||
69 | expression E, size; | ||
70 | position p : script:python() { relevant(p) }; | ||
71 | position m != cond.ok; | ||
72 | type T; | ||
73 | @@ | ||
74 | |||
75 | - memset@m((T)E, 0, size); | ||
76 | ... when != E | ||
77 | when strict | ||
78 | ( | ||
79 | - kfree(E)@p; | ||
80 | + kfree_sensitive(E); | ||
81 | | | ||
82 | - \(vfree\|kvfree\)(E)@p; | ||
83 | + kvfree_sensitive(E, size); | ||
84 | ) | ||
85 | |||
86 | @script:python depends on report@ | ||
87 | p << r.p; | ||
88 | m << r.m; | ||
89 | @@ | ||
90 | |||
91 | msg = "WARNING opportunity for kfree_sensitive/kvfree_sensitive (memset at line %s)" | ||
92 | coccilib.report.print_report(p[0], msg % (m[0].line)) | ||
93 | |||
94 | @script:python depends on org@ | ||
95 | p << r.p; | ||
96 | m << r.m; | ||
97 | @@ | ||
98 | |||
99 | msg = "WARNING opportunity for kfree_sensitive/kvfree_sensitive (memset at line %s)" | ||
100 | coccilib.org.print_todo(p[0], msg % (m[0].line)) | ||
diff --git a/scripts/coccinelle/api/kobj_to_dev.cocci b/scripts/coccinelle/api/kobj_to_dev.cocci new file mode 100644 index 000000000..cd5d31c6f --- /dev/null +++ b/scripts/coccinelle/api/kobj_to_dev.cocci | |||
@@ -0,0 +1,45 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// | ||
3 | /// Use kobj_to_dev() instead of container_of() | ||
4 | /// | ||
5 | // Confidence: High | ||
6 | // Copyright: (C) 2020 Denis Efremov ISPRAS | ||
7 | // Options: --no-includes --include-headers | ||
8 | // | ||
9 | // Keywords: kobj_to_dev, container_of | ||
10 | // | ||
11 | |||
12 | virtual context | ||
13 | virtual report | ||
14 | virtual org | ||
15 | virtual patch | ||
16 | |||
17 | |||
18 | @r depends on !patch@ | ||
19 | expression ptr; | ||
20 | symbol kobj; | ||
21 | position p; | ||
22 | @@ | ||
23 | |||
24 | * container_of(ptr, struct device, kobj)@p | ||
25 | |||
26 | |||
27 | @depends on patch@ | ||
28 | expression ptr; | ||
29 | @@ | ||
30 | |||
31 | - container_of(ptr, struct device, kobj) | ||
32 | + kobj_to_dev(ptr) | ||
33 | |||
34 | |||
35 | @script:python depends on report@ | ||
36 | p << r.p; | ||
37 | @@ | ||
38 | |||
39 | coccilib.report.print_report(p[0], "WARNING opportunity for kobj_to_dev()") | ||
40 | |||
41 | @script:python depends on org@ | ||
42 | p << r.p; | ||
43 | @@ | ||
44 | |||
45 | coccilib.org.print_todo(p[0], "WARNING opportunity for kobj_to_dev()") | ||
diff --git a/scripts/coccinelle/api/kstrdup.cocci b/scripts/coccinelle/api/kstrdup.cocci new file mode 100644 index 000000000..3c6dc5469 --- /dev/null +++ b/scripts/coccinelle/api/kstrdup.cocci | |||
@@ -0,0 +1,105 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// Use kstrdup rather than duplicating its implementation | ||
3 | /// | ||
4 | // Confidence: High | ||
5 | // Copyright: (C) 2010-2012 Nicolas Palix. | ||
6 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. | ||
7 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. | ||
8 | // URL: http://coccinelle.lip6.fr/ | ||
9 | // Comments: | ||
10 | // Options: --no-includes --include-headers | ||
11 | |||
12 | virtual patch | ||
13 | virtual context | ||
14 | virtual org | ||
15 | virtual report | ||
16 | |||
17 | @depends on patch@ | ||
18 | expression from,to; | ||
19 | expression flag,E1,E2; | ||
20 | statement S; | ||
21 | @@ | ||
22 | |||
23 | - to = kmalloc(strlen(from) + 1,flag); | ||
24 | + to = kstrdup(from, flag); | ||
25 | ... when != \(from = E1 \| to = E1 \) | ||
26 | if (to==NULL || ...) S | ||
27 | ... when != \(from = E2 \| to = E2 \) | ||
28 | - strcpy(to, from); | ||
29 | |||
30 | @depends on patch@ | ||
31 | expression x,from,to; | ||
32 | expression flag,E1,E2,E3; | ||
33 | statement S; | ||
34 | @@ | ||
35 | |||
36 | - x = strlen(from) + 1; | ||
37 | ... when != \( x = E1 \| from = E1 \) | ||
38 | - to = \(kmalloc\|kzalloc\)(x,flag); | ||
39 | + to = kstrdup(from, flag); | ||
40 | ... when != \(x = E2 \| from = E2 \| to = E2 \) | ||
41 | if (to==NULL || ...) S | ||
42 | ... when != \(x = E3 \| from = E3 \| to = E3 \) | ||
43 | - memcpy(to, from, x); | ||
44 | |||
45 | // --------------------------------------------------------------------- | ||
46 | |||
47 | @r1 depends on !patch exists@ | ||
48 | expression from,to; | ||
49 | expression flag,E1,E2; | ||
50 | statement S; | ||
51 | position p1,p2; | ||
52 | @@ | ||
53 | |||
54 | * to = kmalloc@p1(strlen(from) + 1,flag); | ||
55 | ... when != \(from = E1 \| to = E1 \) | ||
56 | if (to==NULL || ...) S | ||
57 | ... when != \(from = E2 \| to = E2 \) | ||
58 | * strcpy@p2(to, from); | ||
59 | |||
60 | @r2 depends on !patch exists@ | ||
61 | expression x,from,to; | ||
62 | expression flag,E1,E2,E3; | ||
63 | statement S; | ||
64 | position p1,p2; | ||
65 | @@ | ||
66 | |||
67 | * x = strlen(from) + 1; | ||
68 | ... when != \( x = E1 \| from = E1 \) | ||
69 | * to = \(kmalloc@p1\|kzalloc@p1\)(x,flag); | ||
70 | ... when != \(x = E2 \| from = E2 \| to = E2 \) | ||
71 | if (to==NULL || ...) S | ||
72 | ... when != \(x = E3 \| from = E3 \| to = E3 \) | ||
73 | * memcpy@p2(to, from, x); | ||
74 | |||
75 | @script:python depends on org@ | ||
76 | p1 << r1.p1; | ||
77 | p2 << r1.p2; | ||
78 | @@ | ||
79 | |||
80 | cocci.print_main("WARNING opportunity for kstrdup",p1) | ||
81 | cocci.print_secs("strcpy",p2) | ||
82 | |||
83 | @script:python depends on org@ | ||
84 | p1 << r2.p1; | ||
85 | p2 << r2.p2; | ||
86 | @@ | ||
87 | |||
88 | cocci.print_main("WARNING opportunity for kstrdup",p1) | ||
89 | cocci.print_secs("memcpy",p2) | ||
90 | |||
91 | @script:python depends on report@ | ||
92 | p1 << r1.p1; | ||
93 | p2 << r1.p2; | ||
94 | @@ | ||
95 | |||
96 | msg = "WARNING opportunity for kstrdup (strcpy on line %s)" % (p2[0].line) | ||
97 | coccilib.report.print_report(p1[0], msg) | ||
98 | |||
99 | @script:python depends on report@ | ||
100 | p1 << r2.p1; | ||
101 | p2 << r2.p2; | ||
102 | @@ | ||
103 | |||
104 | msg = "WARNING opportunity for kstrdup (memcpy on line %s)" % (p2[0].line) | ||
105 | coccilib.report.print_report(p1[0], msg) | ||
diff --git a/scripts/coccinelle/api/kvmalloc.cocci b/scripts/coccinelle/api/kvmalloc.cocci new file mode 100644 index 000000000..c30dab718 --- /dev/null +++ b/scripts/coccinelle/api/kvmalloc.cocci | |||
@@ -0,0 +1,256 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// | ||
3 | /// Find if/else condition with kmalloc/vmalloc calls. | ||
4 | /// Suggest to use kvmalloc instead. Same for kvfree. | ||
5 | /// | ||
6 | // Confidence: High | ||
7 | // Copyright: (C) 2020 Denis Efremov ISPRAS | ||
8 | // Options: --no-includes --include-headers | ||
9 | // | ||
10 | |||
11 | virtual patch | ||
12 | virtual report | ||
13 | virtual org | ||
14 | virtual context | ||
15 | |||
16 | @initialize:python@ | ||
17 | @@ | ||
18 | filter = frozenset(['kvfree']) | ||
19 | |||
20 | def relevant(p): | ||
21 | return not (filter & {el.current_element for el in p}) | ||
22 | |||
23 | @kvmalloc depends on !patch@ | ||
24 | expression E, E1, size; | ||
25 | identifier flags; | ||
26 | binary operator cmp = {<=, <, ==, >, >=}; | ||
27 | identifier x; | ||
28 | type T; | ||
29 | position p; | ||
30 | @@ | ||
31 | |||
32 | ( | ||
33 | * if (size cmp E1 || ...)@p { | ||
34 | ... | ||
35 | * E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\| | ||
36 | * kmalloc_array\|kmalloc_array_node\|kcalloc_node\) | ||
37 | * (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...) | ||
38 | ... | ||
39 | } else { | ||
40 | ... | ||
41 | * E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...) | ||
42 | ... | ||
43 | } | ||
44 | | | ||
45 | * E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\| | ||
46 | * kmalloc_array\|kmalloc_array_node\|kcalloc_node\) | ||
47 | * (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...) | ||
48 | ... when != E = E1 | ||
49 | when != size = E1 | ||
50 | when any | ||
51 | * if (E == NULL)@p { | ||
52 | ... | ||
53 | * E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...) | ||
54 | ... | ||
55 | } | ||
56 | | | ||
57 | * T x = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\| | ||
58 | * kmalloc_array\|kmalloc_array_node\|kcalloc_node\) | ||
59 | * (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...); | ||
60 | ... when != x = E1 | ||
61 | when != size = E1 | ||
62 | when any | ||
63 | * if (x == NULL)@p { | ||
64 | ... | ||
65 | * x = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...) | ||
66 | ... | ||
67 | } | ||
68 | ) | ||
69 | |||
70 | @kvfree depends on !patch@ | ||
71 | expression E; | ||
72 | position p : script:python() { relevant(p) }; | ||
73 | @@ | ||
74 | |||
75 | * if (is_vmalloc_addr(E))@p { | ||
76 | ... | ||
77 | * vfree(E) | ||
78 | ... | ||
79 | } else { | ||
80 | ... when != krealloc(E, ...) | ||
81 | when any | ||
82 | * \(kfree\|kzfree\)(E) | ||
83 | ... | ||
84 | } | ||
85 | |||
86 | @depends on patch@ | ||
87 | expression E, E1, size, node; | ||
88 | binary operator cmp = {<=, <, ==, >, >=}; | ||
89 | identifier flags, x; | ||
90 | type T; | ||
91 | @@ | ||
92 | |||
93 | ( | ||
94 | - if (size cmp E1) | ||
95 | - E = kmalloc(size, flags); | ||
96 | - else | ||
97 | - E = vmalloc(size); | ||
98 | + E = kvmalloc(size, flags); | ||
99 | | | ||
100 | - if (size cmp E1) | ||
101 | - E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); | ||
102 | - else | ||
103 | - E = vmalloc(size); | ||
104 | + E = kvmalloc(size, GFP_KERNEL); | ||
105 | | | ||
106 | - E = kmalloc(size, flags | __GFP_NOWARN); | ||
107 | - if (E == NULL) | ||
108 | - E = vmalloc(size); | ||
109 | + E = kvmalloc(size, flags); | ||
110 | | | ||
111 | - E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); | ||
112 | - if (E == NULL) | ||
113 | - E = vmalloc(size); | ||
114 | + E = kvmalloc(size, GFP_KERNEL); | ||
115 | | | ||
116 | - T x = kmalloc(size, flags | __GFP_NOWARN); | ||
117 | - if (x == NULL) | ||
118 | - x = vmalloc(size); | ||
119 | + T x = kvmalloc(size, flags); | ||
120 | | | ||
121 | - T x = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); | ||
122 | - if (x == NULL) | ||
123 | - x = vmalloc(size); | ||
124 | + T x = kvmalloc(size, GFP_KERNEL); | ||
125 | | | ||
126 | - if (size cmp E1) | ||
127 | - E = kzalloc(size, flags); | ||
128 | - else | ||
129 | - E = vzalloc(size); | ||
130 | + E = kvzalloc(size, flags); | ||
131 | | | ||
132 | - if (size cmp E1) | ||
133 | - E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); | ||
134 | - else | ||
135 | - E = vzalloc(size); | ||
136 | + E = kvzalloc(size, GFP_KERNEL); | ||
137 | | | ||
138 | - E = kzalloc(size, flags | __GFP_NOWARN); | ||
139 | - if (E == NULL) | ||
140 | - E = vzalloc(size); | ||
141 | + E = kvzalloc(size, flags); | ||
142 | | | ||
143 | - E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); | ||
144 | - if (E == NULL) | ||
145 | - E = vzalloc(size); | ||
146 | + E = kvzalloc(size, GFP_KERNEL); | ||
147 | | | ||
148 | - T x = kzalloc(size, flags | __GFP_NOWARN); | ||
149 | - if (x == NULL) | ||
150 | - x = vzalloc(size); | ||
151 | + T x = kvzalloc(size, flags); | ||
152 | | | ||
153 | - T x = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); | ||
154 | - if (x == NULL) | ||
155 | - x = vzalloc(size); | ||
156 | + T x = kvzalloc(size, GFP_KERNEL); | ||
157 | | | ||
158 | - if (size cmp E1) | ||
159 | - E = kmalloc_node(size, flags, node); | ||
160 | - else | ||
161 | - E = vmalloc_node(size, node); | ||
162 | + E = kvmalloc_node(size, flags, node); | ||
163 | | | ||
164 | - if (size cmp E1) | ||
165 | - E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); | ||
166 | - else | ||
167 | - E = vmalloc_node(size, node); | ||
168 | + E = kvmalloc_node(size, GFP_KERNEL, node); | ||
169 | | | ||
170 | - E = kmalloc_node(size, flags | __GFP_NOWARN, node); | ||
171 | - if (E == NULL) | ||
172 | - E = vmalloc_node(size, node); | ||
173 | + E = kvmalloc_node(size, flags, node); | ||
174 | | | ||
175 | - E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); | ||
176 | - if (E == NULL) | ||
177 | - E = vmalloc_node(size, node); | ||
178 | + E = kvmalloc_node(size, GFP_KERNEL, node); | ||
179 | | | ||
180 | - T x = kmalloc_node(size, flags | __GFP_NOWARN, node); | ||
181 | - if (x == NULL) | ||
182 | - x = vmalloc_node(size, node); | ||
183 | + T x = kvmalloc_node(size, flags, node); | ||
184 | | | ||
185 | - T x = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); | ||
186 | - if (x == NULL) | ||
187 | - x = vmalloc_node(size, node); | ||
188 | + T x = kvmalloc_node(size, GFP_KERNEL, node); | ||
189 | | | ||
190 | - if (size cmp E1) | ||
191 | - E = kvzalloc_node(size, flags, node); | ||
192 | - else | ||
193 | - E = vzalloc_node(size, node); | ||
194 | + E = kvzalloc_node(size, flags, node); | ||
195 | | | ||
196 | - if (size cmp E1) | ||
197 | - E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); | ||
198 | - else | ||
199 | - E = vzalloc_node(size, node); | ||
200 | + E = kvzalloc_node(size, GFP_KERNEL, node); | ||
201 | | | ||
202 | - E = kvzalloc_node(size, flags | __GFP_NOWARN, node); | ||
203 | - if (E == NULL) | ||
204 | - E = vzalloc_node(size, node); | ||
205 | + E = kvzalloc_node(size, flags, node); | ||
206 | | | ||
207 | - E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); | ||
208 | - if (E == NULL) | ||
209 | - E = vzalloc_node(size, node); | ||
210 | + E = kvzalloc_node(size, GFP_KERNEL, node); | ||
211 | | | ||
212 | - T x = kvzalloc_node(size, flags | __GFP_NOWARN, node); | ||
213 | - if (x == NULL) | ||
214 | - x = vzalloc_node(size, node); | ||
215 | + T x = kvzalloc_node(size, flags, node); | ||
216 | | | ||
217 | - T x = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); | ||
218 | - if (x == NULL) | ||
219 | - x = vzalloc_node(size, node); | ||
220 | + T x = kvzalloc_node(size, GFP_KERNEL, node); | ||
221 | ) | ||
222 | |||
223 | @depends on patch@ | ||
224 | expression E; | ||
225 | position p : script:python() { relevant(p) }; | ||
226 | @@ | ||
227 | |||
228 | - if (is_vmalloc_addr(E))@p | ||
229 | - vfree(E); | ||
230 | - else | ||
231 | - kfree(E); | ||
232 | + kvfree(E); | ||
233 | |||
234 | @script: python depends on report@ | ||
235 | p << kvmalloc.p; | ||
236 | @@ | ||
237 | |||
238 | coccilib.report.print_report(p[0], "WARNING opportunity for kvmalloc") | ||
239 | |||
240 | @script: python depends on org@ | ||
241 | p << kvmalloc.p; | ||
242 | @@ | ||
243 | |||
244 | coccilib.org.print_todo(p[0], "WARNING opportunity for kvmalloc") | ||
245 | |||
246 | @script: python depends on report@ | ||
247 | p << kvfree.p; | ||
248 | @@ | ||
249 | |||
250 | coccilib.report.print_report(p[0], "WARNING opportunity for kvfree") | ||
251 | |||
252 | @script: python depends on org@ | ||
253 | p << kvfree.p; | ||
254 | @@ | ||
255 | |||
256 | coccilib.org.print_todo(p[0], "WARNING opportunity for kvfree") | ||
diff --git a/scripts/coccinelle/api/memdup.cocci b/scripts/coccinelle/api/memdup.cocci new file mode 100644 index 000000000..30b15df73 --- /dev/null +++ b/scripts/coccinelle/api/memdup.cocci | |||
@@ -0,0 +1,66 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// Use kmemdup rather than duplicating its implementation | ||
3 | /// | ||
4 | // Confidence: High | ||
5 | // Copyright: (C) 2010-2012 Nicolas Palix. | ||
6 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. | ||
7 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. | ||
8 | // URL: http://coccinelle.lip6.fr/ | ||
9 | // Comments: | ||
10 | // Options: --no-includes --include-headers | ||
11 | |||
12 | virtual patch | ||
13 | virtual context | ||
14 | virtual org | ||
15 | virtual report | ||
16 | |||
17 | @r1@ | ||
18 | expression from,to; | ||
19 | expression flag; | ||
20 | position p; | ||
21 | @@ | ||
22 | |||
23 | to = \(kmalloc@p\|kzalloc@p\)(strlen(from) + 1,flag); | ||
24 | |||
25 | @r2@ | ||
26 | expression x,from,to; | ||
27 | expression flag,E1; | ||
28 | position p; | ||
29 | @@ | ||
30 | |||
31 | x = strlen(from) + 1; | ||
32 | ... when != \( x = E1 \| from = E1 \) | ||
33 | to = \(kmalloc@p\|kzalloc@p\)(x,flag); | ||
34 | |||
35 | @depends on patch@ | ||
36 | expression from,to,size,flag; | ||
37 | position p != {r1.p,r2.p}; | ||
38 | statement S; | ||
39 | @@ | ||
40 | |||
41 | - to = \(kmalloc@p\|kzalloc@p\)(size,flag); | ||
42 | + to = kmemdup(from,size,flag); | ||
43 | if (to==NULL || ...) S | ||
44 | - memcpy(to, from, size); | ||
45 | |||
46 | @r depends on !patch@ | ||
47 | expression from,to,size,flag; | ||
48 | position p != {r1.p,r2.p}; | ||
49 | statement S; | ||
50 | @@ | ||
51 | |||
52 | * to = \(kmalloc@p\|kzalloc@p\)(size,flag); | ||
53 | if (to==NULL || ...) S | ||
54 | * memcpy(to, from, size); | ||
55 | |||
56 | @script:python depends on org@ | ||
57 | p << r.p; | ||
58 | @@ | ||
59 | |||
60 | coccilib.org.print_todo(p[0], "WARNING opportunity for kmemdup") | ||
61 | |||
62 | @script:python depends on report@ | ||
63 | p << r.p; | ||
64 | @@ | ||
65 | |||
66 | coccilib.report.print_report(p[0], "WARNING opportunity for kmemdup") | ||
diff --git a/scripts/coccinelle/api/memdup_user.cocci b/scripts/coccinelle/api/memdup_user.cocci new file mode 100644 index 000000000..e01e95108 --- /dev/null +++ b/scripts/coccinelle/api/memdup_user.cocci | |||
@@ -0,0 +1,119 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// Use memdup_user rather than duplicating its implementation | ||
3 | /// This is a little bit restricted to reduce false positives | ||
4 | /// | ||
5 | // Confidence: High | ||
6 | // Copyright: (C) 2010-2012 Nicolas Palix. | ||
7 | // Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. | ||
8 | // Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. | ||
9 | // URL: http://coccinelle.lip6.fr/ | ||
10 | // Comments: | ||
11 | // Options: --no-includes --include-headers | ||
12 | |||
13 | virtual patch | ||
14 | virtual context | ||
15 | virtual org | ||
16 | virtual report | ||
17 | |||
18 | @initialize:python@ | ||
19 | @@ | ||
20 | filter = frozenset(['memdup_user', 'vmemdup_user']) | ||
21 | |||
22 | def relevant(p): | ||
23 | return not (filter & {el.current_element for el in p}) | ||
24 | |||
25 | @depends on patch@ | ||
26 | expression from,to,size; | ||
27 | identifier l1,l2; | ||
28 | position p : script:python() { relevant(p) }; | ||
29 | @@ | ||
30 | |||
31 | - to = \(kmalloc@p\|kzalloc@p\) | ||
32 | - (size,\(GFP_KERNEL\|GFP_USER\| | ||
33 | - \(GFP_KERNEL\|GFP_USER\)|__GFP_NOWARN\)); | ||
34 | + to = memdup_user(from,size); | ||
35 | if ( | ||
36 | - to==NULL | ||
37 | + IS_ERR(to) | ||
38 | || ...) { | ||
39 | <+... when != goto l1; | ||
40 | - -ENOMEM | ||
41 | + PTR_ERR(to) | ||
42 | ...+> | ||
43 | } | ||
44 | - if (copy_from_user(to, from, size) != 0) { | ||
45 | - <+... when != goto l2; | ||
46 | - -EFAULT | ||
47 | - ...+> | ||
48 | - } | ||
49 | |||
50 | @depends on patch@ | ||
51 | expression from,to,size; | ||
52 | identifier l1,l2; | ||
53 | position p : script:python() { relevant(p) }; | ||
54 | @@ | ||
55 | |||
56 | - to = \(kvmalloc@p\|kvzalloc@p\)(size,\(GFP_KERNEL\|GFP_USER\)); | ||
57 | + to = vmemdup_user(from,size); | ||
58 | if ( | ||
59 | - to==NULL | ||
60 | + IS_ERR(to) | ||
61 | || ...) { | ||
62 | <+... when != goto l1; | ||
63 | - -ENOMEM | ||
64 | + PTR_ERR(to) | ||
65 | ...+> | ||
66 | } | ||
67 | - if (copy_from_user(to, from, size) != 0) { | ||
68 | - <+... when != goto l2; | ||
69 | - -EFAULT | ||
70 | - ...+> | ||
71 | - } | ||
72 | |||
73 | @r depends on !patch@ | ||
74 | expression from,to,size; | ||
75 | position p : script:python() { relevant(p) }; | ||
76 | statement S1,S2; | ||
77 | @@ | ||
78 | |||
79 | * to = \(kmalloc@p\|kzalloc@p\) | ||
80 | (size,\(GFP_KERNEL\|GFP_USER\| | ||
81 | \(GFP_KERNEL\|GFP_USER\)|__GFP_NOWARN\)); | ||
82 | if (to==NULL || ...) S1 | ||
83 | if (copy_from_user(to, from, size) != 0) | ||
84 | S2 | ||
85 | |||
86 | @rv depends on !patch@ | ||
87 | expression from,to,size; | ||
88 | position p : script:python() { relevant(p) }; | ||
89 | statement S1,S2; | ||
90 | @@ | ||
91 | |||
92 | * to = \(kvmalloc@p\|kvzalloc@p\)(size,\(GFP_KERNEL\|GFP_USER\)); | ||
93 | if (to==NULL || ...) S1 | ||
94 | if (copy_from_user(to, from, size) != 0) | ||
95 | S2 | ||
96 | |||
97 | @script:python depends on org@ | ||
98 | p << r.p; | ||
99 | @@ | ||
100 | |||
101 | coccilib.org.print_todo(p[0], "WARNING opportunity for memdup_user") | ||
102 | |||
103 | @script:python depends on report@ | ||
104 | p << r.p; | ||
105 | @@ | ||
106 | |||
107 | coccilib.report.print_report(p[0], "WARNING opportunity for memdup_user") | ||
108 | |||
109 | @script:python depends on org@ | ||
110 | p << rv.p; | ||
111 | @@ | ||
112 | |||
113 | coccilib.org.print_todo(p[0], "WARNING opportunity for vmemdup_user") | ||
114 | |||
115 | @script:python depends on report@ | ||
116 | p << rv.p; | ||
117 | @@ | ||
118 | |||
119 | coccilib.report.print_report(p[0], "WARNING opportunity for vmemdup_user") | ||
diff --git a/scripts/coccinelle/api/platform_get_irq.cocci b/scripts/coccinelle/api/platform_get_irq.cocci new file mode 100644 index 000000000..06b6a95e2 --- /dev/null +++ b/scripts/coccinelle/api/platform_get_irq.cocci | |||
@@ -0,0 +1,102 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /// Remove dev_err() messages after platform_get_irq*() failures | ||
3 | // | ||
4 | // Confidence: Medium | ||
5 | // Options: --include-headers | ||
6 | |||
7 | virtual patch | ||
8 | virtual context | ||
9 | virtual org | ||
10 | virtual report | ||
11 | |||
12 | @depends on context@ | ||
13 | expression ret; | ||
14 | struct platform_device *E; | ||
15 | @@ | ||
16 | |||
17 | ret = | ||
18 | ( | ||
19 | platform_get_irq | ||
20 | | | ||
21 | platform_get_irq_byname | ||
22 | )(E, ...); | ||
23 | |||
24 | if ( \( ret < 0 \| ret <= 0 \) ) | ||
25 | { | ||
26 | ( | ||
27 | if (ret != -EPROBE_DEFER) | ||
28 | { ... | ||
29 | *dev_err(...); | ||
30 | ... } | ||
31 | | | ||
32 | ... | ||
33 | *dev_err(...); | ||
34 | ) | ||
35 | ... | ||
36 | } | ||
37 | |||
38 | @depends on patch@ | ||
39 | expression ret; | ||
40 | struct platform_device *E; | ||
41 | @@ | ||
42 | |||
43 | ret = | ||
44 | ( | ||
45 | platform_get_irq | ||
46 | | | ||
47 | platform_get_irq_byname | ||
48 | )(E, ...); | ||
49 | |||
50 | if ( \( ret < 0 \| ret <= 0 \) ) | ||
51 | { | ||
52 | ( | ||
53 | -if (ret != -EPROBE_DEFER) | ||
54 | -{ ... | ||
55 | -dev_err(...); | ||
56 | -... } | ||
57 | | | ||
58 | ... | ||
59 | -dev_err(...); | ||
60 | ) | ||
61 | ... | ||
62 | } | ||
63 | |||
64 | @r depends on org || report@ | ||
65 | position p1; | ||
66 | expression ret; | ||
67 | struct platform_device *E; | ||
68 | @@ | ||
69 | |||
70 | ret = | ||
71 | ( | ||
72 | platform_get_irq | ||
73 | | | ||
74 | platform_get_irq_byname | ||
75 | )(E, ...); | ||
76 | |||
77 | if ( \( ret < 0 \| ret <= 0 \) ) | ||
78 | { | ||
79 | ( | ||
80 | if (ret != -EPROBE_DEFER) | ||
81 | { ... | ||
82 | dev_err@p1(...); | ||
83 | ... } | ||
84 | | | ||
85 | ... | ||
86 | dev_err@p1(...); | ||
87 | ) | ||
88 | ... | ||
89 | } | ||
90 | |||
91 | @script:python depends on org@ | ||
92 | p1 << r.p1; | ||
93 | @@ | ||
94 | |||
95 | cocci.print_main(p1) | ||
96 | |||
97 | @script:python depends on report@ | ||
98 | p1 << r.p1; | ||
99 | @@ | ||
100 | |||
101 | msg = "line %s is redundant because platform_get_irq() already prints an error" % (p1[0].line) | ||
102 | coccilib.report.print_report(p1[0],msg) | ||
diff --git a/scripts/coccinelle/api/platform_no_drv_owner.cocci b/scripts/coccinelle/api/platform_no_drv_owner.cocci new file mode 100644 index 000000000..8fa050eeb --- /dev/null +++ b/scripts/coccinelle/api/platform_no_drv_owner.cocci | |||
@@ -0,0 +1,180 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// Remove .owner field if calls are used which set it automatically | ||
3 | /// | ||
4 | // Confidence: High | ||
5 | // Copyright: (C) 2014 Wolfram Sang. | ||
6 | |||
7 | virtual patch | ||
8 | virtual context | ||
9 | virtual org | ||
10 | virtual report | ||
11 | |||
12 | @match1@ | ||
13 | declarer name module_i2c_driver; | ||
14 | declarer name module_platform_driver; | ||
15 | declarer name module_platform_driver_probe; | ||
16 | identifier __driver; | ||
17 | @@ | ||
18 | ( | ||
19 | module_i2c_driver(__driver); | ||
20 | | | ||
21 | module_platform_driver(__driver); | ||
22 | | | ||
23 | module_platform_driver_probe(__driver, ...); | ||
24 | ) | ||
25 | |||
26 | @fix1 depends on match1 && patch && !context && !org && !report@ | ||
27 | identifier match1.__driver; | ||
28 | @@ | ||
29 | static struct platform_driver __driver = { | ||
30 | .driver = { | ||
31 | - .owner = THIS_MODULE, | ||
32 | } | ||
33 | }; | ||
34 | |||
35 | @fix1_i2c depends on match1 && patch && !context && !org && !report@ | ||
36 | identifier match1.__driver; | ||
37 | @@ | ||
38 | static struct i2c_driver __driver = { | ||
39 | .driver = { | ||
40 | - .owner = THIS_MODULE, | ||
41 | } | ||
42 | }; | ||
43 | |||
44 | @match2@ | ||
45 | identifier __driver; | ||
46 | @@ | ||
47 | ( | ||
48 | platform_driver_register(&__driver) | ||
49 | | | ||
50 | platform_driver_probe(&__driver, ...) | ||
51 | | | ||
52 | platform_create_bundle(&__driver, ...) | ||
53 | | | ||
54 | i2c_add_driver(&__driver) | ||
55 | ) | ||
56 | |||
57 | @fix2 depends on match2 && patch && !context && !org && !report@ | ||
58 | identifier match2.__driver; | ||
59 | @@ | ||
60 | static struct platform_driver __driver = { | ||
61 | .driver = { | ||
62 | - .owner = THIS_MODULE, | ||
63 | } | ||
64 | }; | ||
65 | |||
66 | @fix2_i2c depends on match2 && patch && !context && !org && !report@ | ||
67 | identifier match2.__driver; | ||
68 | @@ | ||
69 | static struct i2c_driver __driver = { | ||
70 | .driver = { | ||
71 | - .owner = THIS_MODULE, | ||
72 | } | ||
73 | }; | ||
74 | |||
75 | // ---------------------------------------------------------------------------- | ||
76 | |||
77 | @fix1_context depends on match1 && !patch && (context || org || report)@ | ||
78 | identifier match1.__driver; | ||
79 | position j0; | ||
80 | @@ | ||
81 | |||
82 | static struct platform_driver __driver = { | ||
83 | .driver = { | ||
84 | * .owner@j0 = THIS_MODULE, | ||
85 | } | ||
86 | }; | ||
87 | |||
88 | @fix1_i2c_context depends on match1 && !patch && (context || org || report)@ | ||
89 | identifier match1.__driver; | ||
90 | position j0; | ||
91 | @@ | ||
92 | |||
93 | static struct i2c_driver __driver = { | ||
94 | .driver = { | ||
95 | * .owner@j0 = THIS_MODULE, | ||
96 | } | ||
97 | }; | ||
98 | |||
99 | @fix2_context depends on match2 && !patch && (context || org || report)@ | ||
100 | identifier match2.__driver; | ||
101 | position j0; | ||
102 | @@ | ||
103 | |||
104 | static struct platform_driver __driver = { | ||
105 | .driver = { | ||
106 | * .owner@j0 = THIS_MODULE, | ||
107 | } | ||
108 | }; | ||
109 | |||
110 | @fix2_i2c_context depends on match2 && !patch && (context || org || report)@ | ||
111 | identifier match2.__driver; | ||
112 | position j0; | ||
113 | @@ | ||
114 | |||
115 | static struct i2c_driver __driver = { | ||
116 | .driver = { | ||
117 | * .owner@j0 = THIS_MODULE, | ||
118 | } | ||
119 | }; | ||
120 | |||
121 | // ---------------------------------------------------------------------------- | ||
122 | |||
123 | @script:python fix1_org depends on org@ | ||
124 | j0 << fix1_context.j0; | ||
125 | @@ | ||
126 | |||
127 | msg = "No need to set .owner here. The core will do it." | ||
128 | coccilib.org.print_todo(j0[0], msg) | ||
129 | |||
130 | @script:python fix1_i2c_org depends on org@ | ||
131 | j0 << fix1_i2c_context.j0; | ||
132 | @@ | ||
133 | |||
134 | msg = "No need to set .owner here. The core will do it." | ||
135 | coccilib.org.print_todo(j0[0], msg) | ||
136 | |||
137 | @script:python fix2_org depends on org@ | ||
138 | j0 << fix2_context.j0; | ||
139 | @@ | ||
140 | |||
141 | msg = "No need to set .owner here. The core will do it." | ||
142 | coccilib.org.print_todo(j0[0], msg) | ||
143 | |||
144 | @script:python fix2_i2c_org depends on org@ | ||
145 | j0 << fix2_i2c_context.j0; | ||
146 | @@ | ||
147 | |||
148 | msg = "No need to set .owner here. The core will do it." | ||
149 | coccilib.org.print_todo(j0[0], msg) | ||
150 | |||
151 | // ---------------------------------------------------------------------------- | ||
152 | |||
153 | @script:python fix1_report depends on report@ | ||
154 | j0 << fix1_context.j0; | ||
155 | @@ | ||
156 | |||
157 | msg = "No need to set .owner here. The core will do it." | ||
158 | coccilib.report.print_report(j0[0], msg) | ||
159 | |||
160 | @script:python fix1_i2c_report depends on report@ | ||
161 | j0 << fix1_i2c_context.j0; | ||
162 | @@ | ||
163 | |||
164 | msg = "No need to set .owner here. The core will do it." | ||
165 | coccilib.report.print_report(j0[0], msg) | ||
166 | |||
167 | @script:python fix2_report depends on report@ | ||
168 | j0 << fix2_context.j0; | ||
169 | @@ | ||
170 | |||
171 | msg = "No need to set .owner here. The core will do it." | ||
172 | coccilib.report.print_report(j0[0], msg) | ||
173 | |||
174 | @script:python fix2_i2c_report depends on report@ | ||
175 | j0 << fix2_i2c_context.j0; | ||
176 | @@ | ||
177 | |||
178 | msg = "No need to set .owner here. The core will do it." | ||
179 | coccilib.report.print_report(j0[0], msg) | ||
180 | |||
diff --git a/scripts/coccinelle/api/pm_runtime.cocci b/scripts/coccinelle/api/pm_runtime.cocci new file mode 100644 index 000000000..1ccce3fd0 --- /dev/null +++ b/scripts/coccinelle/api/pm_runtime.cocci | |||
@@ -0,0 +1,114 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// Make sure pm_runtime_* calls does not use unnecessary IS_ERR_VALUE | ||
3 | /// | ||
4 | // Keywords: pm_runtime | ||
5 | // Confidence: Medium | ||
6 | // Copyright (C) 2013 Texas Instruments Incorporated - | ||
7 | // URL: http://coccinelle.lip6.fr/ | ||
8 | // Options: --include-headers | ||
9 | |||
10 | virtual patch | ||
11 | virtual context | ||
12 | virtual org | ||
13 | virtual report | ||
14 | |||
15 | //---------------------------------------------------------- | ||
16 | // Detection | ||
17 | //---------------------------------------------------------- | ||
18 | |||
19 | @runtime_bad_err_handle exists@ | ||
20 | expression ret; | ||
21 | position p; | ||
22 | @@ | ||
23 | ( | ||
24 | ret@p = \(pm_runtime_idle\| | ||
25 | pm_runtime_suspend\| | ||
26 | pm_runtime_autosuspend\| | ||
27 | pm_runtime_resume\| | ||
28 | pm_request_idle\| | ||
29 | pm_request_resume\| | ||
30 | pm_request_autosuspend\| | ||
31 | pm_runtime_get\| | ||
32 | pm_runtime_get_sync\| | ||
33 | pm_runtime_put\| | ||
34 | pm_runtime_put_autosuspend\| | ||
35 | pm_runtime_put_sync\| | ||
36 | pm_runtime_put_sync_suspend\| | ||
37 | pm_runtime_put_sync_autosuspend\| | ||
38 | pm_runtime_set_active\| | ||
39 | pm_schedule_suspend\| | ||
40 | pm_runtime_barrier\| | ||
41 | pm_generic_runtime_suspend\| | ||
42 | pm_generic_runtime_resume\)(...); | ||
43 | ... | ||
44 | IS_ERR_VALUE(ret) | ||
45 | ... | ||
46 | ) | ||
47 | |||
48 | //---------------------------------------------------------- | ||
49 | // For context mode | ||
50 | //---------------------------------------------------------- | ||
51 | |||
52 | @depends on context@ | ||
53 | identifier pm_runtime_api; | ||
54 | expression ret; | ||
55 | position runtime_bad_err_handle.p; | ||
56 | @@ | ||
57 | ( | ||
58 | ret@p = pm_runtime_api(...); | ||
59 | ... | ||
60 | * IS_ERR_VALUE(ret) | ||
61 | ... | ||
62 | ) | ||
63 | |||
64 | //---------------------------------------------------------- | ||
65 | // For patch mode | ||
66 | //---------------------------------------------------------- | ||
67 | |||
68 | @depends on patch@ | ||
69 | identifier pm_runtime_api; | ||
70 | expression ret; | ||
71 | position runtime_bad_err_handle.p; | ||
72 | @@ | ||
73 | ( | ||
74 | ret@p = pm_runtime_api(...); | ||
75 | ... | ||
76 | - IS_ERR_VALUE(ret) | ||
77 | + ret < 0 | ||
78 | ... | ||
79 | ) | ||
80 | |||
81 | //---------------------------------------------------------- | ||
82 | // For org and report mode | ||
83 | //---------------------------------------------------------- | ||
84 | |||
85 | @r depends on (org || report) exists@ | ||
86 | position p1, p2; | ||
87 | identifier pm_runtime_api; | ||
88 | expression ret; | ||
89 | position runtime_bad_err_handle.p; | ||
90 | @@ | ||
91 | ( | ||
92 | ret@p = pm_runtime_api@p1(...); | ||
93 | ... | ||
94 | IS_ERR_VALUE@p2(ret) | ||
95 | ... | ||
96 | ) | ||
97 | |||
98 | @script:python depends on org@ | ||
99 | p1 << r.p1; | ||
100 | p2 << r.p2; | ||
101 | pm_runtime_api << r.pm_runtime_api; | ||
102 | @@ | ||
103 | |||
104 | cocci.print_main(pm_runtime_api,p1) | ||
105 | cocci.print_secs("IS_ERR_VALUE",p2) | ||
106 | |||
107 | @script:python depends on report@ | ||
108 | p1 << r.p1; | ||
109 | p2 << r.p2; | ||
110 | pm_runtime_api << r.pm_runtime_api; | ||
111 | @@ | ||
112 | |||
113 | msg = "%s returns < 0 as error. Unecessary IS_ERR_VALUE at line %s" % (pm_runtime_api, p2[0].line) | ||
114 | coccilib.report.print_report(p1[0],msg) | ||
diff --git a/scripts/coccinelle/api/ptr_ret.cocci b/scripts/coccinelle/api/ptr_ret.cocci new file mode 100644 index 000000000..e76cd5d90 --- /dev/null +++ b/scripts/coccinelle/api/ptr_ret.cocci | |||
@@ -0,0 +1,97 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// | ||
3 | /// Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR | ||
4 | /// | ||
5 | // Confidence: High | ||
6 | // Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. | ||
7 | // Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. | ||
8 | // URL: http://coccinelle.lip6.fr/ | ||
9 | // Options: --no-includes --include-headers | ||
10 | // | ||
11 | // Keywords: ERR_PTR, PTR_ERR, PTR_ERR_OR_ZERO | ||
12 | // Version min: 2.6.39 | ||
13 | // | ||
14 | |||
15 | virtual context | ||
16 | virtual patch | ||
17 | virtual org | ||
18 | virtual report | ||
19 | |||
20 | @depends on patch@ | ||
21 | expression ptr; | ||
22 | @@ | ||
23 | |||
24 | - if (IS_ERR(ptr)) return PTR_ERR(ptr); else return 0; | ||
25 | + return PTR_ERR_OR_ZERO(ptr); | ||
26 | |||
27 | @depends on patch@ | ||
28 | expression ptr; | ||
29 | @@ | ||
30 | |||
31 | - if (IS_ERR(ptr)) return PTR_ERR(ptr); return 0; | ||
32 | + return PTR_ERR_OR_ZERO(ptr); | ||
33 | |||
34 | @depends on patch@ | ||
35 | expression ptr; | ||
36 | @@ | ||
37 | |||
38 | - (IS_ERR(ptr) ? PTR_ERR(ptr) : 0) | ||
39 | + PTR_ERR_OR_ZERO(ptr) | ||
40 | |||
41 | @r1 depends on !patch@ | ||
42 | expression ptr; | ||
43 | position p1; | ||
44 | @@ | ||
45 | |||
46 | * if@p1 (IS_ERR(ptr)) return PTR_ERR(ptr); else return 0; | ||
47 | |||
48 | @r2 depends on !patch@ | ||
49 | expression ptr; | ||
50 | position p2; | ||
51 | @@ | ||
52 | |||
53 | * if@p2 (IS_ERR(ptr)) return PTR_ERR(ptr); return 0; | ||
54 | |||
55 | @r3 depends on !patch@ | ||
56 | expression ptr; | ||
57 | position p3; | ||
58 | @@ | ||
59 | |||
60 | * IS_ERR@p3(ptr) ? PTR_ERR(ptr) : 0 | ||
61 | |||
62 | @script:python depends on org@ | ||
63 | p << r1.p1; | ||
64 | @@ | ||
65 | |||
66 | coccilib.org.print_todo(p[0], "WARNING: PTR_ERR_OR_ZERO can be used") | ||
67 | |||
68 | |||
69 | @script:python depends on org@ | ||
70 | p << r2.p2; | ||
71 | @@ | ||
72 | |||
73 | coccilib.org.print_todo(p[0], "WARNING: PTR_ERR_OR_ZERO can be used") | ||
74 | |||
75 | @script:python depends on org@ | ||
76 | p << r3.p3; | ||
77 | @@ | ||
78 | |||
79 | coccilib.org.print_todo(p[0], "WARNING: PTR_ERR_OR_ZERO can be used") | ||
80 | |||
81 | @script:python depends on report@ | ||
82 | p << r1.p1; | ||
83 | @@ | ||
84 | |||
85 | coccilib.report.print_report(p[0], "WARNING: PTR_ERR_OR_ZERO can be used") | ||
86 | |||
87 | @script:python depends on report@ | ||
88 | p << r2.p2; | ||
89 | @@ | ||
90 | |||
91 | coccilib.report.print_report(p[0], "WARNING: PTR_ERR_OR_ZERO can be used") | ||
92 | |||
93 | @script:python depends on report@ | ||
94 | p << r3.p3; | ||
95 | @@ | ||
96 | |||
97 | coccilib.report.print_report(p[0], "WARNING: PTR_ERR_OR_ZERO can be used") | ||
diff --git a/scripts/coccinelle/api/resource_size.cocci b/scripts/coccinelle/api/resource_size.cocci new file mode 100644 index 000000000..a9a571ac0 --- /dev/null +++ b/scripts/coccinelle/api/resource_size.cocci | |||
@@ -0,0 +1,94 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0-only | ||
2 | /// | ||
3 | /// Use resource_size function on resource object | ||
4 | /// instead of explicit computation. | ||
5 | /// | ||
6 | // Confidence: High | ||
7 | // Copyright: (C) 2009, 2010 Nicolas Palix, DIKU. | ||
8 | // Copyright: (C) 2009, 2010 Julia Lawall, DIKU. | ||
9 | // Copyright: (C) 2009, 2010 Gilles Muller, INRIA/LiP6. | ||
10 | // URL: http://coccinelle.lip6.fr/ | ||
11 | // Options: | ||
12 | // | ||
13 | // Keywords: resource_size | ||
14 | // Version min: 2.6.27 resource_size | ||
15 | // | ||
16 | |||
17 | virtual context | ||
18 | virtual patch | ||
19 | virtual org | ||
20 | virtual report | ||
21 | |||
22 | //---------------------------------------------------------- | ||
23 | // For context mode | ||
24 | //---------------------------------------------------------- | ||
25 | |||
26 | @r_context depends on context && !patch && !org@ | ||
27 | struct resource *res; | ||
28 | @@ | ||
29 | |||
30 | * (res->end - res->start) + 1 | ||
31 | |||
32 | //---------------------------------------------------------- | ||
33 | // For patch mode | ||
34 | //---------------------------------------------------------- | ||
35 | |||
36 | @r_patch depends on !context && patch && !org@ | ||
37 | struct resource *res; | ||
38 | @@ | ||
39 | |||
40 | - (res->end - res->start) + 1 | ||
41 | + resource_size(res) | ||
42 | |||
43 | //---------------------------------------------------------- | ||
44 | // For org mode | ||
45 | //---------------------------------------------------------- | ||
46 | |||
47 | |||
48 | @r_org depends on !context && !patch && (org || report)@ | ||
49 | struct resource *res; | ||
50 | position p; | ||
51 | @@ | ||
52 | |||
53 | (res->end@p - res->start) + 1 | ||
54 | |||
55 | @rbad_org depends on !context && !patch && (org || report)@ | ||
56 | struct resource *res; | ||
57 | position p != r_org.p; | ||
58 | @@ | ||
59 | |||
60 | res->end@p - res->start | ||
61 | |||
62 | @script:python depends on org@ | ||
63 | p << r_org.p; | ||
64 | x << r_org.res; | ||
65 | @@ | ||
66 | |||
67 | msg="ERROR with %s" % (x) | ||
68 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
69 | coccilib.org.print_todo(p[0], msg_safe) | ||
70 | |||
71 | @script:python depends on report@ | ||
72 | p << r_org.p; | ||
73 | x << r_org.res; | ||
74 | @@ | ||
75 | |||
76 | msg="ERROR: Missing resource_size with %s" % (x) | ||
77 | coccilib.report.print_report(p[0], msg) | ||
78 | |||
79 | @script:python depends on org@ | ||
80 | p << rbad_org.p; | ||
81 | x << rbad_org.res; | ||
82 | @@ | ||
83 | |||
84 | msg="WARNING with %s" % (x) | ||
85 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
86 | coccilib.org.print_todo(p[0], msg_safe) | ||
87 | |||
88 | @script:python depends on report@ | ||
89 | p << rbad_org.p; | ||
90 | x << rbad_org.res; | ||
91 | @@ | ||
92 | |||
93 | msg="WARNING: Suspicious code. resource_size is maybe missing with %s" % (x) | ||
94 | coccilib.report.print_report(p[0], msg) | ||
diff --git a/scripts/coccinelle/api/simple_open.cocci b/scripts/coccinelle/api/simple_open.cocci new file mode 100644 index 000000000..c121876d5 --- /dev/null +++ b/scripts/coccinelle/api/simple_open.cocci | |||
@@ -0,0 +1,71 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /// Remove an open coded simple_open() function | ||
3 | /// and replace file operations references to the function | ||
4 | /// with simple_open() instead. | ||
5 | /// | ||
6 | // Confidence: High | ||
7 | // Comments: | ||
8 | // Options: --no-includes --include-headers | ||
9 | |||
10 | virtual patch | ||
11 | virtual report | ||
12 | |||
13 | @ open depends on patch @ | ||
14 | identifier open_f != simple_open; | ||
15 | identifier i, f; | ||
16 | @@ | ||
17 | -int open_f(struct inode *i, struct file *f) | ||
18 | -{ | ||
19 | ( | ||
20 | -if (i->i_private) | ||
21 | -f->private_data = i->i_private; | ||
22 | | | ||
23 | -f->private_data = i->i_private; | ||
24 | ) | ||
25 | -return 0; | ||
26 | -} | ||
27 | |||
28 | @ has_open depends on open @ | ||
29 | identifier fops; | ||
30 | identifier open.open_f; | ||
31 | @@ | ||
32 | struct file_operations fops = { | ||
33 | ..., | ||
34 | -.open = open_f, | ||
35 | +.open = simple_open, | ||
36 | ... | ||
37 | }; | ||
38 | |||
39 | @ openr depends on report @ | ||
40 | identifier open_f != simple_open; | ||
41 | identifier i, f; | ||
42 | position p; | ||
43 | @@ | ||
44 | int open_f@p(struct inode *i, struct file *f) | ||
45 | { | ||
46 | ( | ||
47 | if (i->i_private) | ||
48 | f->private_data = i->i_private; | ||
49 | | | ||
50 | f->private_data = i->i_private; | ||
51 | ) | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | @ has_openr depends on openr @ | ||
56 | identifier fops; | ||
57 | identifier openr.open_f; | ||
58 | position p; | ||
59 | @@ | ||
60 | struct file_operations fops = { | ||
61 | ..., | ||
62 | .open = open_f@p, | ||
63 | ... | ||
64 | }; | ||
65 | |||
66 | @script:python@ | ||
67 | pf << openr.p; | ||
68 | ps << has_openr.p; | ||
69 | @@ | ||
70 | |||
71 | coccilib.report.print_report(pf[0],"WARNING opportunity for simple_open, see also structure on line %s"%(ps[0].line)) | ||
diff --git a/scripts/coccinelle/api/stream_open.cocci b/scripts/coccinelle/api/stream_open.cocci new file mode 100644 index 000000000..df00d6619 --- /dev/null +++ b/scripts/coccinelle/api/stream_open.cocci | |||
@@ -0,0 +1,370 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | // Author: Kirill Smelkov (kirr@nexedi.com) | ||
3 | // | ||
4 | // Search for stream-like files that are using nonseekable_open and convert | ||
5 | // them to stream_open. A stream-like file is a file that does not use ppos in | ||
6 | // its read and write. Rationale for the conversion is to avoid deadlock in | ||
7 | // between read and write. | ||
8 | |||
9 | virtual report | ||
10 | virtual patch | ||
11 | virtual explain // explain decisions in the patch (SPFLAGS="-D explain") | ||
12 | |||
13 | // stream-like reader & writer - ones that do not depend on f_pos. | ||
14 | @ stream_reader @ | ||
15 | identifier readstream, ppos; | ||
16 | identifier f, buf, len; | ||
17 | type loff_t; | ||
18 | @@ | ||
19 | ssize_t readstream(struct file *f, char *buf, size_t len, loff_t *ppos) | ||
20 | { | ||
21 | ... when != ppos | ||
22 | } | ||
23 | |||
24 | @ stream_writer @ | ||
25 | identifier writestream, ppos; | ||
26 | identifier f, buf, len; | ||
27 | type loff_t; | ||
28 | @@ | ||
29 | ssize_t writestream(struct file *f, const char *buf, size_t len, loff_t *ppos) | ||
30 | { | ||
31 | ... when != ppos | ||
32 | } | ||
33 | |||
34 | |||
35 | // a function that blocks | ||
36 | @ blocks @ | ||
37 | identifier block_f; | ||
38 | identifier wait =~ "^wait_.*"; | ||
39 | @@ | ||
40 | block_f(...) { | ||
41 | ... when exists | ||
42 | wait(...) | ||
43 | ... when exists | ||
44 | } | ||
45 | |||
46 | // stream_reader that can block inside. | ||
47 | // | ||
48 | // XXX wait_* can be called not directly from current function (e.g. func -> f -> g -> wait()) | ||
49 | // XXX currently reader_blocks supports only direct and 1-level indirect cases. | ||
50 | @ reader_blocks_direct @ | ||
51 | identifier stream_reader.readstream; | ||
52 | identifier wait =~ "^wait_.*"; | ||
53 | @@ | ||
54 | readstream(...) | ||
55 | { | ||
56 | ... when exists | ||
57 | wait(...) | ||
58 | ... when exists | ||
59 | } | ||
60 | |||
61 | @ reader_blocks_1 @ | ||
62 | identifier stream_reader.readstream; | ||
63 | identifier blocks.block_f; | ||
64 | @@ | ||
65 | readstream(...) | ||
66 | { | ||
67 | ... when exists | ||
68 | block_f(...) | ||
69 | ... when exists | ||
70 | } | ||
71 | |||
72 | @ reader_blocks depends on reader_blocks_direct || reader_blocks_1 @ | ||
73 | identifier stream_reader.readstream; | ||
74 | @@ | ||
75 | readstream(...) { | ||
76 | ... | ||
77 | } | ||
78 | |||
79 | |||
80 | // file_operations + whether they have _any_ .read, .write, .llseek ... at all. | ||
81 | // | ||
82 | // XXX add support for file_operations xxx[N] = ... (sound/core/pcm_native.c) | ||
83 | @ fops0 @ | ||
84 | identifier fops; | ||
85 | @@ | ||
86 | struct file_operations fops = { | ||
87 | ... | ||
88 | }; | ||
89 | |||
90 | @ has_read @ | ||
91 | identifier fops0.fops; | ||
92 | identifier read_f; | ||
93 | @@ | ||
94 | struct file_operations fops = { | ||
95 | .read = read_f, | ||
96 | }; | ||
97 | |||
98 | @ has_read_iter @ | ||
99 | identifier fops0.fops; | ||
100 | identifier read_iter_f; | ||
101 | @@ | ||
102 | struct file_operations fops = { | ||
103 | .read_iter = read_iter_f, | ||
104 | }; | ||
105 | |||
106 | @ has_write @ | ||
107 | identifier fops0.fops; | ||
108 | identifier write_f; | ||
109 | @@ | ||
110 | struct file_operations fops = { | ||
111 | .write = write_f, | ||
112 | }; | ||
113 | |||
114 | @ has_write_iter @ | ||
115 | identifier fops0.fops; | ||
116 | identifier write_iter_f; | ||
117 | @@ | ||
118 | struct file_operations fops = { | ||
119 | .write_iter = write_iter_f, | ||
120 | }; | ||
121 | |||
122 | @ has_llseek @ | ||
123 | identifier fops0.fops; | ||
124 | identifier llseek_f; | ||
125 | @@ | ||
126 | struct file_operations fops = { | ||
127 | .llseek = llseek_f, | ||
128 | }; | ||
129 | |||
130 | @ has_no_llseek @ | ||
131 | identifier fops0.fops; | ||
132 | @@ | ||
133 | struct file_operations fops = { | ||
134 | .llseek = no_llseek, | ||
135 | }; | ||
136 | |||
137 | @ has_noop_llseek @ | ||
138 | identifier fops0.fops; | ||
139 | @@ | ||
140 | struct file_operations fops = { | ||
141 | .llseek = noop_llseek, | ||
142 | }; | ||
143 | |||
144 | @ has_mmap @ | ||
145 | identifier fops0.fops; | ||
146 | identifier mmap_f; | ||
147 | @@ | ||
148 | struct file_operations fops = { | ||
149 | .mmap = mmap_f, | ||
150 | }; | ||
151 | |||
152 | @ has_copy_file_range @ | ||
153 | identifier fops0.fops; | ||
154 | identifier copy_file_range_f; | ||
155 | @@ | ||
156 | struct file_operations fops = { | ||
157 | .copy_file_range = copy_file_range_f, | ||
158 | }; | ||
159 | |||
160 | @ has_remap_file_range @ | ||
161 | identifier fops0.fops; | ||
162 | identifier remap_file_range_f; | ||
163 | @@ | ||
164 | struct file_operations fops = { | ||
165 | .remap_file_range = remap_file_range_f, | ||
166 | }; | ||
167 | |||
168 | @ has_splice_read @ | ||
169 | identifier fops0.fops; | ||
170 | identifier splice_read_f; | ||
171 | @@ | ||
172 | struct file_operations fops = { | ||
173 | .splice_read = splice_read_f, | ||
174 | }; | ||
175 | |||
176 | @ has_splice_write @ | ||
177 | identifier fops0.fops; | ||
178 | identifier splice_write_f; | ||
179 | @@ | ||
180 | struct file_operations fops = { | ||
181 | .splice_write = splice_write_f, | ||
182 | }; | ||
183 | |||
184 | |||
185 | // file_operations that is candidate for stream_open conversion - it does not | ||
186 | // use mmap and other methods that assume @offset access to file. | ||
187 | // | ||
188 | // XXX for simplicity require no .{read/write}_iter and no .splice_{read/write} for now. | ||
189 | // XXX maybe_steam.fops cannot be used in other rules - it gives "bad rule maybe_stream or bad variable fops". | ||
190 | @ maybe_stream depends on (!has_llseek || has_no_llseek || has_noop_llseek) && !has_mmap && !has_copy_file_range && !has_remap_file_range && !has_read_iter && !has_write_iter && !has_splice_read && !has_splice_write @ | ||
191 | identifier fops0.fops; | ||
192 | @@ | ||
193 | struct file_operations fops = { | ||
194 | }; | ||
195 | |||
196 | |||
197 | // ---- conversions ---- | ||
198 | |||
199 | // XXX .open = nonseekable_open -> .open = stream_open | ||
200 | // XXX .open = func -> openfunc -> nonseekable_open | ||
201 | |||
202 | // read & write | ||
203 | // | ||
204 | // if both are used in the same file_operations together with an opener - | ||
205 | // under that conditions we can use stream_open instead of nonseekable_open. | ||
206 | @ fops_rw depends on maybe_stream @ | ||
207 | identifier fops0.fops, openfunc; | ||
208 | identifier stream_reader.readstream; | ||
209 | identifier stream_writer.writestream; | ||
210 | @@ | ||
211 | struct file_operations fops = { | ||
212 | .open = openfunc, | ||
213 | .read = readstream, | ||
214 | .write = writestream, | ||
215 | }; | ||
216 | |||
217 | @ report_rw depends on report @ | ||
218 | identifier fops_rw.openfunc; | ||
219 | position p1; | ||
220 | @@ | ||
221 | openfunc(...) { | ||
222 | <... | ||
223 | nonseekable_open@p1 | ||
224 | ...> | ||
225 | } | ||
226 | |||
227 | @ script:python depends on report && reader_blocks @ | ||
228 | fops << fops0.fops; | ||
229 | p << report_rw.p1; | ||
230 | @@ | ||
231 | coccilib.report.print_report(p[0], | ||
232 | "ERROR: %s: .read() can deadlock .write(); change nonseekable_open -> stream_open to fix." % (fops,)) | ||
233 | |||
234 | @ script:python depends on report && !reader_blocks @ | ||
235 | fops << fops0.fops; | ||
236 | p << report_rw.p1; | ||
237 | @@ | ||
238 | coccilib.report.print_report(p[0], | ||
239 | "WARNING: %s: .read() and .write() have stream semantic; safe to change nonseekable_open -> stream_open." % (fops,)) | ||
240 | |||
241 | |||
242 | @ explain_rw_deadlocked depends on explain && reader_blocks @ | ||
243 | identifier fops_rw.openfunc; | ||
244 | @@ | ||
245 | openfunc(...) { | ||
246 | <... | ||
247 | - nonseekable_open | ||
248 | + nonseekable_open /* read & write (was deadlock) */ | ||
249 | ...> | ||
250 | } | ||
251 | |||
252 | |||
253 | @ explain_rw_nodeadlock depends on explain && !reader_blocks @ | ||
254 | identifier fops_rw.openfunc; | ||
255 | @@ | ||
256 | openfunc(...) { | ||
257 | <... | ||
258 | - nonseekable_open | ||
259 | + nonseekable_open /* read & write (no direct deadlock) */ | ||
260 | ...> | ||
261 | } | ||
262 | |||
263 | @ patch_rw depends on patch @ | ||
264 | identifier fops_rw.openfunc; | ||
265 | @@ | ||
266 | openfunc(...) { | ||
267 | <... | ||
268 | - nonseekable_open | ||
269 | + stream_open | ||
270 | ...> | ||
271 | } | ||
272 | |||
273 | |||
274 | // read, but not write | ||
275 | @ fops_r depends on maybe_stream && !has_write @ | ||
276 | identifier fops0.fops, openfunc; | ||
277 | identifier stream_reader.readstream; | ||
278 | @@ | ||
279 | struct file_operations fops = { | ||
280 | .open = openfunc, | ||
281 | .read = readstream, | ||
282 | }; | ||
283 | |||
284 | @ report_r depends on report @ | ||
285 | identifier fops_r.openfunc; | ||
286 | position p1; | ||
287 | @@ | ||
288 | openfunc(...) { | ||
289 | <... | ||
290 | nonseekable_open@p1 | ||
291 | ...> | ||
292 | } | ||
293 | |||
294 | @ script:python depends on report @ | ||
295 | fops << fops0.fops; | ||
296 | p << report_r.p1; | ||
297 | @@ | ||
298 | coccilib.report.print_report(p[0], | ||
299 | "WARNING: %s: .read() has stream semantic; safe to change nonseekable_open -> stream_open." % (fops,)) | ||
300 | |||
301 | @ explain_r depends on explain @ | ||
302 | identifier fops_r.openfunc; | ||
303 | @@ | ||
304 | openfunc(...) { | ||
305 | <... | ||
306 | - nonseekable_open | ||
307 | + nonseekable_open /* read only */ | ||
308 | ...> | ||
309 | } | ||
310 | |||
311 | @ patch_r depends on patch @ | ||
312 | identifier fops_r.openfunc; | ||
313 | @@ | ||
314 | openfunc(...) { | ||
315 | <... | ||
316 | - nonseekable_open | ||
317 | + stream_open | ||
318 | ...> | ||
319 | } | ||
320 | |||
321 | |||
322 | // write, but not read | ||
323 | @ fops_w depends on maybe_stream && !has_read @ | ||
324 | identifier fops0.fops, openfunc; | ||
325 | identifier stream_writer.writestream; | ||
326 | @@ | ||
327 | struct file_operations fops = { | ||
328 | .open = openfunc, | ||
329 | .write = writestream, | ||
330 | }; | ||
331 | |||
332 | @ report_w depends on report @ | ||
333 | identifier fops_w.openfunc; | ||
334 | position p1; | ||
335 | @@ | ||
336 | openfunc(...) { | ||
337 | <... | ||
338 | nonseekable_open@p1 | ||
339 | ...> | ||
340 | } | ||
341 | |||
342 | @ script:python depends on report @ | ||
343 | fops << fops0.fops; | ||
344 | p << report_w.p1; | ||
345 | @@ | ||
346 | coccilib.report.print_report(p[0], | ||
347 | "WARNING: %s: .write() has stream semantic; safe to change nonseekable_open -> stream_open." % (fops,)) | ||
348 | |||
349 | @ explain_w depends on explain @ | ||
350 | identifier fops_w.openfunc; | ||
351 | @@ | ||
352 | openfunc(...) { | ||
353 | <... | ||
354 | - nonseekable_open | ||
355 | + nonseekable_open /* write only */ | ||
356 | ...> | ||
357 | } | ||
358 | |||
359 | @ patch_w depends on patch @ | ||
360 | identifier fops_w.openfunc; | ||
361 | @@ | ||
362 | openfunc(...) { | ||
363 | <... | ||
364 | - nonseekable_open | ||
365 | + stream_open | ||
366 | ...> | ||
367 | } | ||
368 | |||
369 | |||
370 | // no read, no write - don't change anything | ||
diff --git a/scripts/coccinelle/api/vma_pages.cocci b/scripts/coccinelle/api/vma_pages.cocci new file mode 100644 index 000000000..10511b9bf --- /dev/null +++ b/scripts/coccinelle/api/vma_pages.cocci | |||
@@ -0,0 +1,61 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /// | ||
3 | /// Use vma_pages function on vma object instead of explicit computation. | ||
4 | /// | ||
5 | // Confidence: High | ||
6 | // Keywords: vma_pages vma | ||
7 | // Comment: Based on resource_size.cocci | ||
8 | |||
9 | virtual context | ||
10 | virtual patch | ||
11 | virtual org | ||
12 | virtual report | ||
13 | |||
14 | //---------------------------------------------------------- | ||
15 | // For context mode | ||
16 | //---------------------------------------------------------- | ||
17 | |||
18 | @r_context depends on context && !patch && !org && !report@ | ||
19 | struct vm_area_struct *vma; | ||
20 | @@ | ||
21 | |||
22 | * (vma->vm_end - vma->vm_start) >> PAGE_SHIFT | ||
23 | |||
24 | //---------------------------------------------------------- | ||
25 | // For patch mode | ||
26 | //---------------------------------------------------------- | ||
27 | |||
28 | @r_patch depends on !context && patch && !org && !report@ | ||
29 | struct vm_area_struct *vma; | ||
30 | @@ | ||
31 | |||
32 | - ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) | ||
33 | + vma_pages(vma) | ||
34 | |||
35 | //---------------------------------------------------------- | ||
36 | // For org mode | ||
37 | //---------------------------------------------------------- | ||
38 | |||
39 | @r_org depends on !context && !patch && (org || report)@ | ||
40 | struct vm_area_struct *vma; | ||
41 | position p; | ||
42 | @@ | ||
43 | |||
44 | (vma->vm_end@p - vma->vm_start) >> PAGE_SHIFT | ||
45 | |||
46 | @script:python depends on report@ | ||
47 | p << r_org.p; | ||
48 | x << r_org.vma; | ||
49 | @@ | ||
50 | |||
51 | msg="WARNING: Consider using vma_pages helper on %s" % (x) | ||
52 | coccilib.report.print_report(p[0], msg) | ||
53 | |||
54 | @script:python depends on org@ | ||
55 | p << r_org.p; | ||
56 | x << r_org.vma; | ||
57 | @@ | ||
58 | |||
59 | msg="WARNING: Consider using vma_pages helper on %s" % (x) | ||
60 | msg_safe=msg.replace("[","@(").replace("]",")") | ||
61 | coccilib.org.print_todo(p[0], msg_safe) | ||