|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
| 2 | +/// |
| 3 | +/// Use kzfree, 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: kzfree, 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', 'kzfree', 'kvfree_sensitive']) |
| 22 | +
|
| 23 | +def relevant(p): |
| 24 | + return not (filter & {el.current_element for el in p}) |
| 25 | +
|
| 26 | +@cond@ |
| 27 | +position ok; |
| 28 | +@@ |
| 29 | + |
| 30 | +if (...) |
| 31 | + \(memset@ok\|memzero_explicit@ok\)(...); |
| 32 | + |
| 33 | +@r depends on !patch forall@ |
| 34 | +expression E; |
| 35 | +position p : script:python() { relevant(p) }; |
| 36 | +position m != cond.ok; |
| 37 | +type T; |
| 38 | +@@ |
| 39 | + |
| 40 | +( |
| 41 | +* memset@m((T)E, 0, ...); |
| 42 | +| |
| 43 | +* memzero_explicit@m((T)E, ...); |
| 44 | +) |
| 45 | + ... when != E |
| 46 | + when strict |
| 47 | +* \(kfree\|vfree\|kvfree\)(E)@p; |
| 48 | + |
| 49 | +@rp_memzero depends on patch@ |
| 50 | +expression E, size; |
| 51 | +position p : script:python() { relevant(p) }; |
| 52 | +position m != cond.ok; |
| 53 | +type T; |
| 54 | +@@ |
| 55 | + |
| 56 | +- memzero_explicit@m((T)E, size); |
| 57 | + ... when != E |
| 58 | + when strict |
| 59 | +// TODO: uncomment when kfree_sensitive will be merged. |
| 60 | +// Only this case is commented out because developers |
| 61 | +// may not like patches like this since kzfree uses memset |
| 62 | +// internally (not memzero_explicit). |
| 63 | +//( |
| 64 | +//- kfree(E)@p; |
| 65 | +//+ kfree_sensitive(E); |
| 66 | +//| |
| 67 | +- \(vfree\|kvfree\)(E)@p; |
| 68 | ++ kvfree_sensitive(E, size); |
| 69 | +//) |
| 70 | + |
| 71 | +@rp_memset depends on patch@ |
| 72 | +expression E, size; |
| 73 | +position p : script:python() { relevant(p) }; |
| 74 | +position m != cond.ok; |
| 75 | +type T; |
| 76 | +@@ |
| 77 | + |
| 78 | +- memset@m((T)E, 0, size); |
| 79 | + ... when != E |
| 80 | + when strict |
| 81 | +( |
| 82 | +- kfree(E)@p; |
| 83 | ++ kzfree(E); |
| 84 | +| |
| 85 | +- \(vfree\|kvfree\)(E)@p; |
| 86 | ++ kvfree_sensitive(E, size); |
| 87 | +) |
| 88 | + |
| 89 | +@script:python depends on report@ |
| 90 | +p << r.p; |
| 91 | +@@ |
| 92 | +
|
| 93 | +coccilib.report.print_report(p[0], |
| 94 | + "WARNING: opportunity for kzfree/kvfree_sensitive") |
| 95 | +
|
| 96 | +@script:python depends on org@ |
| 97 | +p << r.p; |
| 98 | +@@ |
| 99 | +
|
| 100 | +coccilib.org.print_todo(p[0], |
| 101 | + "WARNING: opportunity for kzfree/kvfree_sensitive") |
0 commit comments