diff options
Diffstat (limited to 'scripts/coccinelle/free/devm_free.cocci')
-rw-r--r-- | scripts/coccinelle/free/devm_free.cocci | 143 |
1 files changed, 143 insertions, 0 deletions
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 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// Find uses of standard freeing functons on values allocated using devm_ +/// functions. Values allocated using the devm_functions are freed when +/// the device is detached, and thus the use of the standard freeing +/// function would cause a double free. +/// See Documentation/driver-api/driver-model/devres.rst for more information. +/// +/// A difficulty of detecting this problem is that the standard freeing +/// function might be called from a different function than the one +/// containing the allocation function. It is thus necessary to make the +/// connection between the allocation function and the freeing function. +/// Here this is done using the specific argument text, which is prone to +/// false positives. There is no rule for the request_region and +/// request_mem_region variants because this heuristic seems to be a bit +/// less reliable in these cases. +/// +// Confidence: Moderate +// Copyright: (C) 2011 Julia Lawall, INRIA/LIP6. +// Copyright: (C) 2011 Gilles Muller, INRIA/LiP6. +// URL: http://coccinelle.lip6.fr/ +// Comments: +// Options: --no-includes --include-headers + +virtual org +virtual report +virtual context + +@r depends on context || org || report@ +expression x; +@@ + +( + x = devm_kmalloc(...) +| + x = devm_kvasprintf(...) +| + x = devm_kasprintf(...) +| + x = devm_kzalloc(...) +| + x = devm_kmalloc_array(...) +| + x = devm_kcalloc(...) +| + x = devm_kstrdup(...) +| + x = devm_kmemdup(...) +| + x = devm_get_free_pages(...) +| + x = devm_request_irq(...) +| + x = devm_ioremap(...) +| + x = devm_ioport_map(...) +) + +@safe depends on context || org || report exists@ +expression x; +position p; +@@ + +( + x = kmalloc(...) +| + x = kvasprintf(...) +| + x = kasprintf(...) +| + x = kzalloc(...) +| + x = kmalloc_array(...) +| + x = kcalloc(...) +| + x = kstrdup(...) +| + x = kmemdup(...) +| + x = get_free_pages(...) +| + x = request_irq(...) +| + x = ioremap(...) +| + x = ioport_map(...) +) +... +( + kfree@p(x) +| + kfree_sensitive@p(x) +| + krealloc@p(x, ...) +| + free_pages@p(x, ...) +| + free_page@p(x) +| + free_irq@p(x) +| + iounmap@p(x) +| + ioport_unmap@p(x) +) + +@pb@ +expression r.x; +position p != safe.p; +@@ + +( +* kfree@p(x) +| +* kfree_sensitive@p(x) +| +* krealloc@p(x, ...) +| +* free_pages@p(x, ...) +| +* free_page@p(x) +| +* free_irq@p(x) +| +* iounmap@p(x) +| +* ioport_unmap@p(x) +) + +@script:python depends on org@ +p << pb.p; +@@ + +msg="WARNING: invalid free of devm_ allocated data" +coccilib.org.print_todo(p[0], msg) + +@script:python depends on report@ +p << pb.p; +@@ + +msg="WARNING: invalid free of devm_ allocated data" +coccilib.report.print_report(p[0], msg) + |