1// SPDX-License-Identifier: GPL-2.0-only
2/// Find functions that refer to GFP_KERNEL but are called with locks held.
3//# The proposed change of converting the GFP_KERNEL is not necessarily the
4//# correct one.  It may be desired to unlock the lock, or to not call the
5//# function under the lock in the first place.
6///
7// Confidence: Moderate
8// Copyright: (C) 2012 Nicolas Palix.
9// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.
10// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6.
11// URL: https://coccinelle.gitlabpages.inria.fr/website
12// Comments:
13// Options: --no-includes --include-headers
14
15virtual patch
16virtual context
17virtual org
18virtual report
19
20@gfp exists@
21identifier fn;
22position p;
23@@
24
25fn(...) {
26 ... when != read_unlock_irq(...)
27     when != write_unlock_irq(...)
28     when != read_unlock_irqrestore(...)
29     when != write_unlock_irqrestore(...)
30     when != spin_unlock(...)
31     when != spin_unlock_irq(...)
32     when != spin_unlock_irqrestore(...)
33     when != local_irq_enable(...)
34     when any
35 GFP_KERNEL@p
36 ... when any
37}
38
39@locked exists@
40identifier gfp.fn;
41position p1,p2;
42@@
43
44(
45read_lock_irq@p1
46|
47write_lock_irq@p1
48|
49read_lock_irqsave@p1
50|
51write_lock_irqsave@p1
52|
53spin_lock@p1
54|
55spin_trylock@p1
56|
57spin_lock_irq@p1
58|
59spin_lock_irqsave@p1
60|
61local_irq_disable@p1
62)
63 (...)
64...  when != read_unlock_irq(...)
65     when != write_unlock_irq(...)
66     when != read_unlock_irqrestore(...)
67     when != write_unlock_irqrestore(...)
68     when != spin_unlock(...)
69     when != spin_unlock_irq(...)
70     when != spin_unlock_irqrestore(...)
71     when != local_irq_enable(...)
72fn@p2(...)
73
74@depends on locked && patch@
75position gfp.p;
76@@
77
78- GFP_KERNEL@p
79+ GFP_ATOMIC
80
81@depends on locked && !patch@
82position gfp.p;
83@@
84
85* GFP_KERNEL@p
86
87@script:python depends on !patch && org@
88p << gfp.p;
89fn << gfp.fn;
90p1 << locked.p1;
91p2 << locked.p2;
92@@
93
94cocci.print_main("lock",p1)
95cocci.print_secs("call",p2)
96cocci.print_secs("GFP_KERNEL",p)
97
98@script:python depends on !patch && report@
99p << gfp.p;
100fn << gfp.fn;
101p1 << locked.p1;
102p2 << locked.p2;
103@@
104
105msg = "ERROR: function %s called on line %s inside lock on line %s but uses GFP_KERNEL" % (fn,p2[0].line,p1[0].line)
106coccilib.report.print_report(p[0], msg)
107