Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/jlawall/linux

Pull coccinelle updates from Julia Lawall:
"New semantic patches and semantic patch improvements from Denis
Efremov"

* 'for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/jlawall/linux:
coccinelle: api: filter out memdup_user definitions
coccinelle: api: extend memdup_user rule with vmemdup_user()
coccinelle: api: extend memdup_user transformation with GFP_USER
coccinelle: api: add kzfree script
coccinelle: misc: add array_size_dup script to detect missed overflow checks
coccinelle: api/kstrdup: fix coccinelle position
coccinelle: api: add device_attr_show script

+427 -4
+55
scripts/coccinelle/api/device_attr_show.cocci
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /// 3 + /// From Documentation/filesystems/sysfs.txt: 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")
+1 -1
scripts/coccinelle/api/kstrdup.cocci
··· 66 66 67 67 * x = strlen(from) + 1; 68 68 ... when != \( x = E1 \| from = E1 \) 69 - * to = \(kmalloc@p1\|kzalloc@p2\)(x,flag); 69 + * to = \(kmalloc@p1\|kzalloc@p1\)(x,flag); 70 70 ... when != \(x = E2 \| from = E2 \| to = E2 \) 71 71 if (to==NULL || ...) S 72 72 ... when != \(x = E3 \| from = E3 \| to = E3 \)
+101
scripts/coccinelle/api/kzfree.cocci
··· 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")
+61 -3
scripts/coccinelle/api/memdup_user.cocci
··· 15 15 virtual org 16 16 virtual report 17 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 + 18 25 @depends on patch@ 19 26 expression from,to,size; 20 27 identifier l1,l2; 28 + position p : script:python() { relevant(p) }; 21 29 @@ 22 30 23 - - to = \(kmalloc\|kzalloc\)(size,GFP_KERNEL); 31 + - to = \(kmalloc@p\|kzalloc@p\) 32 + - (size,\(GFP_KERNEL\|GFP_USER\| 33 + - \(GFP_KERNEL\|GFP_USER\)|__GFP_NOWARN\)); 24 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); 25 58 if ( 26 59 - to==NULL 27 60 + IS_ERR(to) ··· 72 39 73 40 @r depends on !patch@ 74 41 expression from,to,size; 75 - position p; 42 + position p : script:python() { relevant(p) }; 76 43 statement S1,S2; 77 44 @@ 78 45 79 - * to = \(kmalloc@p\|kzalloc@p\)(size,GFP_KERNEL); 46 + * to = \(kmalloc@p\|kzalloc@p\) 47 + (size,\(GFP_KERNEL\|GFP_USER\| 48 + \(GFP_KERNEL\|GFP_USER\)|__GFP_NOWARN\)); 49 + if (to==NULL || ...) S1 50 + if (copy_from_user(to, from, size) != 0) 51 + S2 52 + 53 + @rv depends on !patch@ 54 + expression from,to,size; 55 + position p : script:python() { relevant(p) }; 56 + statement S1,S2; 57 + @@ 58 + 59 + * to = \(kvmalloc@p\|kvzalloc@p\)(size,\(GFP_KERNEL\|GFP_USER\)); 80 60 if (to==NULL || ...) S1 81 61 if (copy_from_user(to, from, size) != 0) 82 62 S2 ··· 105 59 @@ 106 60 107 61 coccilib.report.print_report(p[0], "WARNING opportunity for memdup_user") 62 + 63 + @script:python depends on org@ 64 + p << rv.p; 65 + @@ 66 + 67 + coccilib.org.print_todo(p[0], "WARNING opportunity for vmemdup_user") 68 + 69 + @script:python depends on report@ 70 + p << rv.p; 71 + @@ 72 + 73 + coccilib.report.print_report(p[0], "WARNING opportunity for vmemdup_user")
+209
scripts/coccinelle/misc/array_size_dup.cocci
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /// 3 + /// Check for array_size(), array3_size(), struct_size() duplicates. 4 + /// These patterns are detected: 5 + /// 1. An opencoded expression is used before array_size() to compute the same size 6 + /// 2. An opencoded expression is used after array_size() to compute the same size 7 + /// From security point of view only first case is relevant. These functions 8 + /// perform arithmetic overflow check. Thus, if we use an opencoded expression 9 + /// before a call to the *_size() function we can miss an overflow. 10 + /// 11 + // Confidence: High 12 + // Copyright: (C) 2020 Denis Efremov ISPRAS 13 + // Options: --no-includes --include-headers --no-loops 14 + 15 + virtual context 16 + virtual report 17 + virtual org 18 + 19 + @as@ 20 + expression E1, E2; 21 + @@ 22 + 23 + array_size(E1, E2) 24 + 25 + @as_next@ 26 + expression subE1 <= as.E1; 27 + expression subE2 <= as.E2; 28 + expression as.E1, as.E2, E3; 29 + assignment operator aop; 30 + position p1, p2; 31 + @@ 32 + 33 + * E1 * E2@p1 34 + ... when != \(subE1\|subE2\) aop E3 35 + when != &\(subE1\|subE2\) 36 + * array_size(E1, E2)@p2 37 + 38 + @script:python depends on report@ 39 + p1 << as_next.p1; 40 + p2 << as_next.p2; 41 + @@ 42 + 43 + msg = "WARNING: array_size is used later (line %s) to compute the same size" % (p2[0].line) 44 + coccilib.report.print_report(p1[0], msg) 45 + 46 + @script:python depends on org@ 47 + p1 << as_next.p1; 48 + p2 << as_next.p2; 49 + @@ 50 + 51 + msg = "WARNING: array_size is used later (line %s) to compute the same size" % (p2[0].line) 52 + coccilib.org.print_todo(p1[0], msg) 53 + 54 + @as_prev@ 55 + expression subE1 <= as.E1; 56 + expression subE2 <= as.E2; 57 + expression as.E1, as.E2, E3; 58 + assignment operator aop; 59 + position p1, p2; 60 + @@ 61 + 62 + * array_size(E1, E2)@p1 63 + ... when != \(subE1\|subE2\) aop E3 64 + when != &\(subE1\|subE2\) 65 + * E1 * E2@p2 66 + 67 + @script:python depends on report@ 68 + p1 << as_prev.p1; 69 + p2 << as_prev.p2; 70 + @@ 71 + 72 + msg = "WARNING: array_size is already used (line %s) to compute the same size" % (p1[0].line) 73 + coccilib.report.print_report(p2[0], msg) 74 + 75 + @script:python depends on org@ 76 + p1 << as_prev.p1; 77 + p2 << as_prev.p2; 78 + @@ 79 + 80 + msg = "WARNING: array_size is already used (line %s) to compute the same size" % (p1[0].line) 81 + coccilib.org.print_todo(p2[0], msg) 82 + 83 + @as3@ 84 + expression E1, E2, E3; 85 + @@ 86 + 87 + array3_size(E1, E2, E3) 88 + 89 + @as3_next@ 90 + expression subE1 <= as3.E1; 91 + expression subE2 <= as3.E2; 92 + expression subE3 <= as3.E3; 93 + expression as3.E1, as3.E2, as3.E3, E4; 94 + assignment operator aop; 95 + position p1, p2; 96 + @@ 97 + 98 + * E1 * E2 * E3@p1 99 + ... when != \(subE1\|subE2\|subE3\) aop E4 100 + when != &\(subE1\|subE2\|subE3\) 101 + * array3_size(E1, E2, E3)@p2 102 + 103 + @script:python depends on report@ 104 + p1 << as3_next.p1; 105 + p2 << as3_next.p2; 106 + @@ 107 + 108 + msg = "WARNING: array3_size is used later (line %s) to compute the same size" % (p2[0].line) 109 + coccilib.report.print_report(p1[0], msg) 110 + 111 + @script:python depends on org@ 112 + p1 << as3_next.p1; 113 + p2 << as3_next.p2; 114 + @@ 115 + 116 + msg = "WARNING: array3_size is used later (line %s) to compute the same size" % (p2[0].line) 117 + coccilib.org.print_todo(p1[0], msg) 118 + 119 + @as3_prev@ 120 + expression subE1 <= as3.E1; 121 + expression subE2 <= as3.E2; 122 + expression subE3 <= as3.E3; 123 + expression as3.E1, as3.E2, as3.E3, E4; 124 + assignment operator aop; 125 + position p1, p2; 126 + @@ 127 + 128 + * array3_size(E1, E2, E3)@p1 129 + ... when != \(subE1\|subE2\|subE3\) aop E4 130 + when != &\(subE1\|subE2\|subE3\) 131 + * E1 * E2 * E3@p2 132 + 133 + @script:python depends on report@ 134 + p1 << as3_prev.p1; 135 + p2 << as3_prev.p2; 136 + @@ 137 + 138 + msg = "WARNING: array3_size is already used (line %s) to compute the same size" % (p1[0].line) 139 + coccilib.report.print_report(p2[0], msg) 140 + 141 + @script:python depends on org@ 142 + p1 << as3_prev.p1; 143 + p2 << as3_prev.p2; 144 + @@ 145 + 146 + msg = "WARNING: array3_size is already used (line %s) to compute the same size" % (p1[0].line) 147 + coccilib.org.print_todo(p2[0], msg) 148 + 149 + @ss@ 150 + expression E1, E2, E3; 151 + @@ 152 + 153 + struct_size(E1, E2, E3) 154 + 155 + @ss_next@ 156 + expression subE3 <= ss.E3; 157 + expression ss.E1, ss.E2, ss.E3, E4; 158 + assignment operator aop; 159 + position p1, p2; 160 + @@ 161 + 162 + * E1 * E2 + E3@p1 163 + ... when != subE3 aop E4 164 + when != &subE3 165 + * struct_size(E1, E2, E3)@p2 166 + 167 + @script:python depends on report@ 168 + p1 << ss_next.p1; 169 + p2 << ss_next.p2; 170 + @@ 171 + 172 + msg = "WARNING: struct_size is used later (line %s) to compute the same size" % (p2[0].line) 173 + coccilib.report.print_report(p1[0], msg) 174 + 175 + @script:python depends on org@ 176 + p1 << ss_next.p1; 177 + p2 << ss_next.p2; 178 + @@ 179 + 180 + msg = "WARNING: struct_size is used later (line %s) to compute the same size" % (p2[0].line) 181 + coccilib.org.print_todo(p1[0], msg) 182 + 183 + @ss_prev@ 184 + expression subE3 <= ss.E3; 185 + expression ss.E1, ss.E2, ss.E3, E4; 186 + assignment operator aop; 187 + position p1, p2; 188 + @@ 189 + 190 + * struct_size(E1, E2, E3)@p1 191 + ... when != subE3 aop E4 192 + when != &subE3 193 + * E1 * E2 + E3@p2 194 + 195 + @script:python depends on report@ 196 + p1 << ss_prev.p1; 197 + p2 << ss_prev.p2; 198 + @@ 199 + 200 + msg = "WARNING: struct_size is already used (line %s) to compute the same size" % (p1[0].line) 201 + coccilib.report.print_report(p2[0], msg) 202 + 203 + @script:python depends on org@ 204 + p1 << ss_prev.p1; 205 + p2 << ss_prev.p2; 206 + @@ 207 + 208 + msg = "WARNING: struct_size is already used (line %s) to compute the same size" % (p1[0].line) 209 + coccilib.org.print_todo(p2[0], msg)