aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/coccinelle/free
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/coccinelle/free')
-rw-r--r--scripts/coccinelle/free/clk_put.cocci68
-rw-r--r--scripts/coccinelle/free/devm_free.cocci143
-rw-r--r--scripts/coccinelle/free/ifnullfree.cocci67
-rw-r--r--scripts/coccinelle/free/iounmap.cocci68
-rw-r--r--scripts/coccinelle/free/kfree.cocci134
-rw-r--r--scripts/coccinelle/free/kfreeaddr.cocci37
-rw-r--r--scripts/coccinelle/free/pci_free_consistent.cocci53
-rw-r--r--scripts/coccinelle/free/put_device.cocci56
8 files changed, 626 insertions, 0 deletions
diff --git a/scripts/coccinelle/free/clk_put.cocci b/scripts/coccinelle/free/clk_put.cocci
new file mode 100644
index 000000000..7237b4949
--- /dev/null
+++ b/scripts/coccinelle/free/clk_put.cocci
@@ -0,0 +1,68 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/// Find missing clk_puts.
3///
4//# This only signals a missing clk_put when there is a clk_put later
5//# in the same function.
6//# False positives can be due to loops.
7//
8// Confidence: Moderate
9// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
10// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
11// URL: http://coccinelle.lip6.fr/
12// Comments:
13// Options:
14
15virtual context
16virtual org
17virtual report
18
19@clk@
20expression e;
21statement S,S1;
22int ret;
23position p1,p2,p3;
24@@
25
26e = clk_get@p1(...)
27... when != clk_put(e)
28if (<+...e...+>) S
29... when any
30 when != clk_put(e)
31 when != if (...) { ... clk_put(e); ... }
32(
33 if (ret == 0) S1
34|
35if (...)
36 { ...
37 return 0; }
38|
39if (...)
40 { ...
41 return <+...e...+>; }
42|
43*if@p2 (...)
44 { ... when != clk_put(e)
45 when forall
46 return@p3 ...; }
47)
48... when any
49clk_put(e);
50
51@script:python depends on org@
52p1 << clk.p1;
53p2 << clk.p2;
54p3 << clk.p3;
55@@
56
57cocci.print_main("clk_get",p1)
58cocci.print_secs("if",p2)
59cocci.print_secs("needed clk_put",p3)
60
61@script:python depends on report@
62p1 << clk.p1;
63p2 << clk.p2;
64p3 << clk.p3;
65@@
66
67msg = "ERROR: missing clk_put; clk_get on line %s and execution via conditional on line %s" % (p1[0].line,p2[0].line)
68coccilib.report.print_report(p3[0],msg)
diff --git a/scripts/coccinelle/free/devm_free.cocci b/scripts/coccinelle/free/devm_free.cocci
new file mode 100644
index 000000000..da80050b9
--- /dev/null
+++ b/scripts/coccinelle/free/devm_free.cocci
@@ -0,0 +1,143 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/// Find uses of standard freeing functons on values allocated using devm_
3/// functions. Values allocated using the devm_functions are freed when
4/// the device is detached, and thus the use of the standard freeing
5/// function would cause a double free.
6/// See Documentation/driver-api/driver-model/devres.rst for more information.
7///
8/// A difficulty of detecting this problem is that the standard freeing
9/// function might be called from a different function than the one
10/// containing the allocation function. It is thus necessary to make the
11/// connection between the allocation function and the freeing function.
12/// Here this is done using the specific argument text, which is prone to
13/// false positives. There is no rule for the request_region and
14/// request_mem_region variants because this heuristic seems to be a bit
15/// less reliable in these cases.
16///
17// Confidence: Moderate
18// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6.
19// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6.
20// URL: http://coccinelle.lip6.fr/
21// Comments:
22// Options: --no-includes --include-headers
23
24virtual org
25virtual report
26virtual context
27
28@r depends on context || org || report@
29expression x;
30@@
31
32(
33 x = devm_kmalloc(...)
34|
35 x = devm_kvasprintf(...)
36|
37 x = devm_kasprintf(...)
38|
39 x = devm_kzalloc(...)
40|
41 x = devm_kmalloc_array(...)
42|
43 x = devm_kcalloc(...)
44|
45 x = devm_kstrdup(...)
46|
47 x = devm_kmemdup(...)
48|
49 x = devm_get_free_pages(...)
50|
51 x = devm_request_irq(...)
52|
53 x = devm_ioremap(...)
54|
55 x = devm_ioport_map(...)
56)
57
58@safe depends on context || org || report exists@
59expression x;
60position p;
61@@
62
63(
64 x = kmalloc(...)
65|
66 x = kvasprintf(...)
67|
68 x = kasprintf(...)
69|
70 x = kzalloc(...)
71|
72 x = kmalloc_array(...)
73|
74 x = kcalloc(...)
75|
76 x = kstrdup(...)
77|
78 x = kmemdup(...)
79|
80 x = get_free_pages(...)
81|
82 x = request_irq(...)
83|
84 x = ioremap(...)
85|
86 x = ioport_map(...)
87)
88...
89(
90 kfree@p(x)
91|
92 kfree_sensitive@p(x)
93|
94 krealloc@p(x, ...)
95|
96 free_pages@p(x, ...)
97|
98 free_page@p(x)
99|
100 free_irq@p(x)
101|
102 iounmap@p(x)
103|
104 ioport_unmap@p(x)
105)
106
107@pb@
108expression r.x;
109position p != safe.p;
110@@
111
112(
113* kfree@p(x)
114|
115* kfree_sensitive@p(x)
116|
117* krealloc@p(x, ...)
118|
119* free_pages@p(x, ...)
120|
121* free_page@p(x)
122|
123* free_irq@p(x)
124|
125* iounmap@p(x)
126|
127* ioport_unmap@p(x)
128)
129
130@script:python depends on org@
131p << pb.p;
132@@
133
134msg="WARNING: invalid free of devm_ allocated data"
135coccilib.org.print_todo(p[0], msg)
136
137@script:python depends on report@
138p << pb.p;
139@@
140
141msg="WARNING: invalid free of devm_ allocated data"
142coccilib.report.print_report(p[0], msg)
143
diff --git a/scripts/coccinelle/free/ifnullfree.cocci b/scripts/coccinelle/free/ifnullfree.cocci
new file mode 100644
index 000000000..285b92d5c
--- /dev/null
+++ b/scripts/coccinelle/free/ifnullfree.cocci
@@ -0,0 +1,67 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/// NULL check before some freeing functions is not needed.
3///
4/// Based on checkpatch warning
5/// "kfree(NULL) is safe this check is probably not required"
6/// and kfreeaddr.cocci by Julia Lawall.
7///
8// Copyright: (C) 2014 Fabian Frederick.
9// Comments: -
10// Options: --no-includes --include-headers
11
12virtual patch
13virtual org
14virtual report
15virtual context
16
17@r2 depends on patch@
18expression E;
19@@
20- if (E != NULL)
21(
22 kfree(E);
23|
24 kvfree(E);
25|
26 kfree_sensitive(E);
27|
28 kvfree_sensitive(E, ...);
29|
30 vfree(E);
31|
32 debugfs_remove(E);
33|
34 debugfs_remove_recursive(E);
35|
36 usb_free_urb(E);
37|
38 kmem_cache_destroy(E);
39|
40 mempool_destroy(E);
41|
42 dma_pool_destroy(E);
43)
44
45@r depends on context || report || org @
46expression E;
47position p;
48@@
49
50* if (E != NULL)
51* \(kfree@p\|kvfree@p\|kfree_sensitive@p\|kvfree_sensitive@p\|vfree@p\|
52* debugfs_remove@p\|debugfs_remove_recursive@p\|
53* usb_free_urb@p\|kmem_cache_destroy@p\|mempool_destroy@p\|
54* dma_pool_destroy@p\)(E, ...);
55
56@script:python depends on org@
57p << r.p;
58@@
59
60cocci.print_main("NULL check before that freeing function is not needed", p)
61
62@script:python depends on report@
63p << r.p;
64@@
65
66msg = "WARNING: NULL check before some freeing functions is not needed."
67coccilib.report.print_report(p[0], msg)
diff --git a/scripts/coccinelle/free/iounmap.cocci b/scripts/coccinelle/free/iounmap.cocci
new file mode 100644
index 000000000..63b81d0c9
--- /dev/null
+++ b/scripts/coccinelle/free/iounmap.cocci
@@ -0,0 +1,68 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/// Find missing iounmaps.
3///
4//# This only signals a missing iounmap when there is an iounmap later
5//# in the same function.
6//# False positives can be due to loops.
7//
8// Confidence: Moderate
9// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
10// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
11// URL: http://coccinelle.lip6.fr/
12// Comments:
13// Options:
14
15virtual context
16virtual org
17virtual report
18
19@iom@
20expression e;
21statement S,S1;
22int ret;
23position p1,p2,p3;
24@@
25
26e = \(ioremap@p1\)(...)
27... when != iounmap(e)
28if (<+...e...+>) S
29... when any
30 when != iounmap(e)
31 when != if (...) { ... iounmap(e); ... }
32(
33 if (ret == 0) S1
34|
35if (...)
36 { ...
37 return 0; }
38|
39if (...)
40 { ...
41 return <+...e...+>; }
42|
43*if@p2 (...)
44 { ... when != iounmap(e)
45 when forall
46 return@p3 ...; }
47)
48... when any
49iounmap(e);
50
51@script:python depends on org@
52p1 << iom.p1;
53p2 << iom.p2;
54p3 << iom.p3;
55@@
56
57cocci.print_main("ioremap",p1)
58cocci.print_secs("if",p2)
59cocci.print_secs("needed iounmap",p3)
60
61@script:python depends on report@
62p1 << iom.p1;
63p2 << iom.p2;
64p3 << iom.p3;
65@@
66
67msg = "ERROR: missing iounmap; ioremap on line %s and execution via conditional on line %s" % (p1[0].line,p2[0].line)
68coccilib.report.print_report(p3[0],msg)
diff --git a/scripts/coccinelle/free/kfree.cocci b/scripts/coccinelle/free/kfree.cocci
new file mode 100644
index 000000000..168568386
--- /dev/null
+++ b/scripts/coccinelle/free/kfree.cocci
@@ -0,0 +1,134 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/// Find a use after free.
3//# Values of variables may imply that some
4//# execution paths are not possible, resulting in false positives.
5//# Another source of false positives are macros such as
6//# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument
7///
8// Confidence: Moderate
9// Copyright: (C) 2010-2012 Nicolas Palix.
10// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6.
11// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6.
12// URL: http://coccinelle.lip6.fr/
13// Comments:
14// Options: --no-includes --include-headers
15
16virtual org
17virtual report
18
19@free@
20expression E;
21position p1;
22@@
23
24(
25* kfree@p1(E)
26|
27* kfree_sensitive@p1(E)
28)
29
30@print expression@
31constant char [] c;
32expression free.E,E2;
33type T;
34position p;
35identifier f;
36@@
37
38(
39 f(...,c,...,(T)E@p,...)
40|
41 E@p == E2
42|
43 E@p != E2
44|
45 E2 == E@p
46|
47 E2 != E@p
48|
49 !E@p
50|
51 E@p || ...
52)
53
54@sz@
55expression free.E;
56position p;
57@@
58
59 sizeof(<+...E@p...+>)
60
61@loop exists@
62expression E;
63identifier l;
64position ok;
65@@
66
67while (1) { ...
68(
69* kfree@ok(E)
70|
71* kfree_sensitive@ok(E)
72)
73 ... when != break;
74 when != goto l;
75 when forall
76}
77
78@r exists@
79expression free.E, subE<=free.E, E2;
80expression E1;
81iterator iter;
82statement S;
83position free.p1!=loop.ok,p2!={print.p,sz.p};
84@@
85
86(
87* kfree@p1(E,...)
88|
89* kfree_sensitive@p1(E,...)
90)
91...
92(
93 iter(...,subE,...) S // no use
94|
95 list_remove_head(E1,subE,...)
96|
97 subE = E2
98|
99 subE++
100|
101 ++subE
102|
103 --subE
104|
105 subE--
106|
107 &subE
108|
109 BUG(...)
110|
111 BUG_ON(...)
112|
113 return_VALUE(...)
114|
115 return_ACPI_STATUS(...)
116|
117 E@p2 // bad use
118)
119
120@script:python depends on org@
121p1 << free.p1;
122p2 << r.p2;
123@@
124
125cocci.print_main("kfree",p1)
126cocci.print_secs("ref",p2)
127
128@script:python depends on report@
129p1 << free.p1;
130p2 << r.p2;
131@@
132
133msg = "ERROR: reference preceded by free on line %s" % (p1[0].line)
134coccilib.report.print_report(p2[0],msg)
diff --git a/scripts/coccinelle/free/kfreeaddr.cocci b/scripts/coccinelle/free/kfreeaddr.cocci
new file mode 100644
index 000000000..142af6337
--- /dev/null
+++ b/scripts/coccinelle/free/kfreeaddr.cocci
@@ -0,0 +1,37 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/// Free of a structure field
3///
4// Confidence: High
5// Copyright: (C) 2013 Julia Lawall, INRIA/LIP6.
6// URL: http://coccinelle.lip6.fr/
7// Comments:
8// Options: --no-includes --include-headers
9
10virtual org
11virtual report
12virtual context
13
14@r depends on context || report || org @
15expression e;
16identifier f;
17position p;
18@@
19
20(
21* kfree@p(&e->f)
22|
23* kfree_sensitive@p(&e->f)
24)
25
26@script:python depends on org@
27p << r.p;
28@@
29
30cocci.print_main("kfree",p)
31
32@script:python depends on report@
33p << r.p;
34@@
35
36msg = "ERROR: invalid free of structure field"
37coccilib.report.print_report(p[0],msg)
diff --git a/scripts/coccinelle/free/pci_free_consistent.cocci b/scripts/coccinelle/free/pci_free_consistent.cocci
new file mode 100644
index 000000000..d51e92556
--- /dev/null
+++ b/scripts/coccinelle/free/pci_free_consistent.cocci
@@ -0,0 +1,53 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/// Find missing pci_free_consistent for every pci_alloc_consistent.
3///
4// Confidence: Moderate
5// Copyright: (C) 2013 Petr Strnad.
6// URL: http://coccinelle.lip6.fr/
7// Keywords: pci_free_consistent, pci_alloc_consistent
8// Options: --no-includes --include-headers
9
10virtual report
11virtual org
12
13@search@
14local idexpression id;
15expression x,y,z,e;
16position p1,p2;
17type T;
18@@
19
20id = pci_alloc_consistent@p1(x,y,&z)
21... when != e = id
22if (id == NULL || ...) { ... return ...; }
23... when != pci_free_consistent(x,y,id,z)
24 when != if (id) { ... pci_free_consistent(x,y,id,z) ... }
25 when != if (y) { ... pci_free_consistent(x,y,id,z) ... }
26 when != e = (T)id
27 when exists
28(
29return 0;
30|
31return 1;
32|
33return id;
34|
35return@p2 ...;
36)
37
38@script:python depends on report@
39p1 << search.p1;
40p2 << search.p2;
41@@
42
43msg = "ERROR: missing pci_free_consistent; pci_alloc_consistent on line %s and return without freeing on line %s" % (p1[0].line,p2[0].line)
44coccilib.report.print_report(p2[0],msg)
45
46@script:python depends on org@
47p1 << search.p1;
48p2 << search.p2;
49@@
50
51msg = "ERROR: missing pci_free_consistent; pci_alloc_consistent on line %s and return without freeing on line %s" % (p1[0].line,p2[0].line)
52cocci.print_main(msg,p1)
53cocci.print_secs("",p2)
diff --git a/scripts/coccinelle/free/put_device.cocci b/scripts/coccinelle/free/put_device.cocci
new file mode 100644
index 000000000..120921366
--- /dev/null
+++ b/scripts/coccinelle/free/put_device.cocci
@@ -0,0 +1,56 @@
1// SPDX-License-Identifier: GPL-2.0
2/// Find missing put_device for every of_find_device_by_node.
3///
4// Confidence: Moderate
5// Copyright: (C) 2018-2019 Wen Yang, ZTE.
6// Comments:
7// Options: --no-includes --include-headers
8
9virtual report
10virtual org
11
12@search exists@
13local idexpression id;
14expression x,e,e1;
15position p1,p2;
16type T,T1,T2,T3;
17@@
18
19id = of_find_device_by_node@p1(x)
20... when != e = id
21if (id == NULL || ...) { ... return ...; }
22... when != put_device(&id->dev)
23 when != platform_device_put(id)
24 when != of_dev_put(id)
25 when != if (id) { ... put_device(&id->dev) ... }
26 when != e1 = (T)id
27 when != e1 = (T)(&id->dev)
28 when != e1 = get_device(&id->dev)
29 when != e1 = (T1)platform_get_drvdata(id)
30(
31 return
32( id
33| (T2)dev_get_drvdata(&id->dev)
34| (T3)platform_get_drvdata(id)
35| &id->dev
36);
37| return@p2 ...;
38)
39
40@script:python depends on report@
41p1 << search.p1;
42p2 << search.p2;
43@@
44
45coccilib.report.print_report(p2[0],
46 "ERROR: missing put_device; call of_find_device_by_node on line "
47 + p1[0].line
48 + ", but without a corresponding object release within this function.")
49
50@script:python depends on org@
51p1 << search.p1;
52p2 << search.p2;
53@@
54
55cocci.print_main("of_find_device_by_node", p1)
56cocci.print_secs("needed put_device", p2)