| // SPDX-License-Identifier: GPL-2.0-only |
| /// |
| /// Find if/else condition with kmalloc/vmalloc calls. |
| /// Suggest to use kvmalloc instead. Same for kvfree. |
| /// |
| // Confidence: High |
| // Copyright: (C) 2020 Denis Efremov ISPRAS |
| // Options: --no-includes --include-headers |
| // |
| |
| virtual patch |
| virtual report |
| virtual org |
| virtual context |
| |
| @initialize:python@ |
| @@ |
| filter = frozenset(['kvfree']) |
| |
| def relevant(p): |
| return not (filter & {el.current_element for el in p}) |
| |
| @kvmalloc depends on !patch@ |
| expression E, E1, size; |
| identifier flags; |
| binary operator cmp = {<=, <, ==, >, >=}; |
| identifier x; |
| type T; |
| position p; |
| @@ |
| |
| ( |
| * if (size cmp E1 || ...)@p { |
| ... |
| * E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\| |
| * kmalloc_array\|kmalloc_array_node\|kcalloc_node\) |
| * (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...) |
| ... |
| } else { |
| ... |
| * E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...) |
| ... |
| } |
| | |
| * E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\| |
| * kmalloc_array\|kmalloc_array_node\|kcalloc_node\) |
| * (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...) |
| ... when != E = E1 |
| when != size = E1 |
| when any |
| * if (E == NULL)@p { |
| ... |
| * E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...) |
| ... |
| } |
| | |
| * T x = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\| |
| * kmalloc_array\|kmalloc_array_node\|kcalloc_node\) |
| * (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...); |
| ... when != x = E1 |
| when != size = E1 |
| when any |
| * if (x == NULL)@p { |
| ... |
| * x = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...) |
| ... |
| } |
| ) |
| |
| @kvfree depends on !patch@ |
| expression E; |
| position p : script:python() { relevant(p) }; |
| @@ |
| |
| * if (is_vmalloc_addr(E))@p { |
| ... |
| * vfree(E) |
| ... |
| } else { |
| ... when != krealloc(E, ...) |
| when any |
| * \(kfree\|kfree_sensitive\)(E) |
| ... |
| } |
| |
| @depends on patch@ |
| expression E, E1, size, node; |
| binary operator cmp = {<=, <, ==, >, >=}; |
| identifier flags, x; |
| type T; |
| @@ |
| |
| ( |
| - if (size cmp E1) |
| - E = kmalloc(size, flags); |
| - else |
| - E = vmalloc(size); |
| + E = kvmalloc(size, flags); |
| | |
| - if (size cmp E1) |
| - E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); |
| - else |
| - E = vmalloc(size); |
| + E = kvmalloc(size, GFP_KERNEL); |
| | |
| - E = kmalloc(size, flags | __GFP_NOWARN); |
| - if (E == NULL) |
| - E = vmalloc(size); |
| + E = kvmalloc(size, flags); |
| | |
| - E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); |
| - if (E == NULL) |
| - E = vmalloc(size); |
| + E = kvmalloc(size, GFP_KERNEL); |
| | |
| - T x = kmalloc(size, flags | __GFP_NOWARN); |
| - if (x == NULL) |
| - x = vmalloc(size); |
| + T x = kvmalloc(size, flags); |
| | |
| - T x = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); |
| - if (x == NULL) |
| - x = vmalloc(size); |
| + T x = kvmalloc(size, GFP_KERNEL); |
| | |
| - if (size cmp E1) |
| - E = kzalloc(size, flags); |
| - else |
| - E = vzalloc(size); |
| + E = kvzalloc(size, flags); |
| | |
| - if (size cmp E1) |
| - E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); |
| - else |
| - E = vzalloc(size); |
| + E = kvzalloc(size, GFP_KERNEL); |
| | |
| - E = kzalloc(size, flags | __GFP_NOWARN); |
| - if (E == NULL) |
| - E = vzalloc(size); |
| + E = kvzalloc(size, flags); |
| | |
| - E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); |
| - if (E == NULL) |
| - E = vzalloc(size); |
| + E = kvzalloc(size, GFP_KERNEL); |
| | |
| - T x = kzalloc(size, flags | __GFP_NOWARN); |
| - if (x == NULL) |
| - x = vzalloc(size); |
| + T x = kvzalloc(size, flags); |
| | |
| - T x = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); |
| - if (x == NULL) |
| - x = vzalloc(size); |
| + T x = kvzalloc(size, GFP_KERNEL); |
| | |
| - if (size cmp E1) |
| - E = kmalloc_node(size, flags, node); |
| - else |
| - E = vmalloc_node(size, node); |
| + E = kvmalloc_node(size, flags, node); |
| | |
| - if (size cmp E1) |
| - E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); |
| - else |
| - E = vmalloc_node(size, node); |
| + E = kvmalloc_node(size, GFP_KERNEL, node); |
| | |
| - E = kmalloc_node(size, flags | __GFP_NOWARN, node); |
| - if (E == NULL) |
| - E = vmalloc_node(size, node); |
| + E = kvmalloc_node(size, flags, node); |
| | |
| - E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); |
| - if (E == NULL) |
| - E = vmalloc_node(size, node); |
| + E = kvmalloc_node(size, GFP_KERNEL, node); |
| | |
| - T x = kmalloc_node(size, flags | __GFP_NOWARN, node); |
| - if (x == NULL) |
| - x = vmalloc_node(size, node); |
| + T x = kvmalloc_node(size, flags, node); |
| | |
| - T x = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); |
| - if (x == NULL) |
| - x = vmalloc_node(size, node); |
| + T x = kvmalloc_node(size, GFP_KERNEL, node); |
| | |
| - if (size cmp E1) |
| - E = kvzalloc_node(size, flags, node); |
| - else |
| - E = vzalloc_node(size, node); |
| + E = kvzalloc_node(size, flags, node); |
| | |
| - if (size cmp E1) |
| - E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); |
| - else |
| - E = vzalloc_node(size, node); |
| + E = kvzalloc_node(size, GFP_KERNEL, node); |
| | |
| - E = kvzalloc_node(size, flags | __GFP_NOWARN, node); |
| - if (E == NULL) |
| - E = vzalloc_node(size, node); |
| + E = kvzalloc_node(size, flags, node); |
| | |
| - E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); |
| - if (E == NULL) |
| - E = vzalloc_node(size, node); |
| + E = kvzalloc_node(size, GFP_KERNEL, node); |
| | |
| - T x = kvzalloc_node(size, flags | __GFP_NOWARN, node); |
| - if (x == NULL) |
| - x = vzalloc_node(size, node); |
| + T x = kvzalloc_node(size, flags, node); |
| | |
| - T x = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); |
| - if (x == NULL) |
| - x = vzalloc_node(size, node); |
| + T x = kvzalloc_node(size, GFP_KERNEL, node); |
| ) |
| |
| @depends on patch@ |
| expression E; |
| position p : script:python() { relevant(p) }; |
| @@ |
| |
| - if (is_vmalloc_addr(E))@p |
| - vfree(E); |
| - else |
| - kfree(E); |
| + kvfree(E); |
| |
| @script: python depends on report@ |
| p << kvmalloc.p; |
| @@ |
| |
| coccilib.report.print_report(p[0], "WARNING opportunity for kvmalloc") |
| |
| @script: python depends on org@ |
| p << kvmalloc.p; |
| @@ |
| |
| coccilib.org.print_todo(p[0], "WARNING opportunity for kvmalloc") |
| |
| @script: python depends on report@ |
| p << kvfree.p; |
| @@ |
| |
| coccilib.report.print_report(p[0], "WARNING opportunity for kvfree") |
| |
| @script: python depends on org@ |
| p << kvfree.p; |
| @@ |
| |
| coccilib.org.print_todo(p[0], "WARNING opportunity for kvfree") |