// 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")