162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci///
362306a36Sopenharmony_ci/// Find if/else condition with kmalloc/vmalloc calls.
462306a36Sopenharmony_ci/// Suggest to use kvmalloc instead. Same for kvfree.
562306a36Sopenharmony_ci///
662306a36Sopenharmony_ci// Confidence: High
762306a36Sopenharmony_ci// Copyright: (C) 2020 Denis Efremov ISPRAS
862306a36Sopenharmony_ci// Options: --no-includes --include-headers
962306a36Sopenharmony_ci//
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_civirtual patch
1262306a36Sopenharmony_civirtual report
1362306a36Sopenharmony_civirtual org
1462306a36Sopenharmony_civirtual context
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci@initialize:python@
1762306a36Sopenharmony_ci@@
1862306a36Sopenharmony_cifilter = frozenset(['kvfree'])
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cidef relevant(p):
2162306a36Sopenharmony_ci    return not (filter & {el.current_element for el in p})
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci@kvmalloc depends on !patch@
2462306a36Sopenharmony_ciexpression E, E1, size;
2562306a36Sopenharmony_ciidentifier flags;
2662306a36Sopenharmony_cibinary operator cmp = {<=, <, ==, >, >=};
2762306a36Sopenharmony_ciidentifier x;
2862306a36Sopenharmony_citype T;
2962306a36Sopenharmony_ciposition p;
3062306a36Sopenharmony_ci@@
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci(
3362306a36Sopenharmony_ci* if (size cmp E1 || ...)@p {
3462306a36Sopenharmony_ci    ...
3562306a36Sopenharmony_ci*    E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
3662306a36Sopenharmony_ci*          kmalloc_array\|kmalloc_array_node\|kcalloc_node\)
3762306a36Sopenharmony_ci*          (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...)
3862306a36Sopenharmony_ci    ...
3962306a36Sopenharmony_ci  } else {
4062306a36Sopenharmony_ci    ...
4162306a36Sopenharmony_ci*    E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...)
4262306a36Sopenharmony_ci    ...
4362306a36Sopenharmony_ci  }
4462306a36Sopenharmony_ci|
4562306a36Sopenharmony_ci* E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
4662306a36Sopenharmony_ci*       kmalloc_array\|kmalloc_array_node\|kcalloc_node\)
4762306a36Sopenharmony_ci*       (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...)
4862306a36Sopenharmony_ci  ... when != E = E1
4962306a36Sopenharmony_ci      when != size = E1
5062306a36Sopenharmony_ci      when any
5162306a36Sopenharmony_ci* if (E == NULL)@p {
5262306a36Sopenharmony_ci    ...
5362306a36Sopenharmony_ci*   E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...)
5462306a36Sopenharmony_ci    ...
5562306a36Sopenharmony_ci  }
5662306a36Sopenharmony_ci|
5762306a36Sopenharmony_ci* T x = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
5862306a36Sopenharmony_ci*         kmalloc_array\|kmalloc_array_node\|kcalloc_node\)
5962306a36Sopenharmony_ci*         (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...);
6062306a36Sopenharmony_ci  ... when != x = E1
6162306a36Sopenharmony_ci      when != size = E1
6262306a36Sopenharmony_ci      when any
6362306a36Sopenharmony_ci* if (x == NULL)@p {
6462306a36Sopenharmony_ci    ...
6562306a36Sopenharmony_ci*   x = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...)
6662306a36Sopenharmony_ci    ...
6762306a36Sopenharmony_ci  }
6862306a36Sopenharmony_ci)
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci@kvfree depends on !patch@
7162306a36Sopenharmony_ciexpression E;
7262306a36Sopenharmony_ciposition p : script:python() { relevant(p) };
7362306a36Sopenharmony_ci@@
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci* if (is_vmalloc_addr(E))@p {
7662306a36Sopenharmony_ci    ...
7762306a36Sopenharmony_ci*   vfree(E)
7862306a36Sopenharmony_ci    ...
7962306a36Sopenharmony_ci  } else {
8062306a36Sopenharmony_ci    ... when != krealloc(E, ...)
8162306a36Sopenharmony_ci        when any
8262306a36Sopenharmony_ci*   \(kfree\|kfree_sensitive\)(E)
8362306a36Sopenharmony_ci    ...
8462306a36Sopenharmony_ci  }
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci@depends on patch@
8762306a36Sopenharmony_ciexpression E, E1, size, node;
8862306a36Sopenharmony_cibinary operator cmp = {<=, <, ==, >, >=};
8962306a36Sopenharmony_ciidentifier flags, x;
9062306a36Sopenharmony_citype T;
9162306a36Sopenharmony_ci@@
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci(
9462306a36Sopenharmony_ci- if (size cmp E1)
9562306a36Sopenharmony_ci-    E = kmalloc(size, flags);
9662306a36Sopenharmony_ci- else
9762306a36Sopenharmony_ci-    E = vmalloc(size);
9862306a36Sopenharmony_ci+ E = kvmalloc(size, flags);
9962306a36Sopenharmony_ci|
10062306a36Sopenharmony_ci- if (size cmp E1)
10162306a36Sopenharmony_ci-    E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
10262306a36Sopenharmony_ci- else
10362306a36Sopenharmony_ci-    E = vmalloc(size);
10462306a36Sopenharmony_ci+ E = kvmalloc(size, GFP_KERNEL);
10562306a36Sopenharmony_ci|
10662306a36Sopenharmony_ci- E = kmalloc(size, flags | __GFP_NOWARN);
10762306a36Sopenharmony_ci- if (E == NULL)
10862306a36Sopenharmony_ci-   E = vmalloc(size);
10962306a36Sopenharmony_ci+ E = kvmalloc(size, flags);
11062306a36Sopenharmony_ci|
11162306a36Sopenharmony_ci- E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
11262306a36Sopenharmony_ci- if (E == NULL)
11362306a36Sopenharmony_ci-   E = vmalloc(size);
11462306a36Sopenharmony_ci+ E = kvmalloc(size, GFP_KERNEL);
11562306a36Sopenharmony_ci|
11662306a36Sopenharmony_ci- T x = kmalloc(size, flags | __GFP_NOWARN);
11762306a36Sopenharmony_ci- if (x == NULL)
11862306a36Sopenharmony_ci-   x = vmalloc(size);
11962306a36Sopenharmony_ci+ T x = kvmalloc(size, flags);
12062306a36Sopenharmony_ci|
12162306a36Sopenharmony_ci- T x = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
12262306a36Sopenharmony_ci- if (x == NULL)
12362306a36Sopenharmony_ci-   x = vmalloc(size);
12462306a36Sopenharmony_ci+ T x = kvmalloc(size, GFP_KERNEL);
12562306a36Sopenharmony_ci|
12662306a36Sopenharmony_ci- if (size cmp E1)
12762306a36Sopenharmony_ci-    E = kzalloc(size, flags);
12862306a36Sopenharmony_ci- else
12962306a36Sopenharmony_ci-    E = vzalloc(size);
13062306a36Sopenharmony_ci+ E = kvzalloc(size, flags);
13162306a36Sopenharmony_ci|
13262306a36Sopenharmony_ci- if (size cmp E1)
13362306a36Sopenharmony_ci-    E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
13462306a36Sopenharmony_ci- else
13562306a36Sopenharmony_ci-    E = vzalloc(size);
13662306a36Sopenharmony_ci+ E = kvzalloc(size, GFP_KERNEL);
13762306a36Sopenharmony_ci|
13862306a36Sopenharmony_ci- E = kzalloc(size, flags | __GFP_NOWARN);
13962306a36Sopenharmony_ci- if (E == NULL)
14062306a36Sopenharmony_ci-   E = vzalloc(size);
14162306a36Sopenharmony_ci+ E = kvzalloc(size, flags);
14262306a36Sopenharmony_ci|
14362306a36Sopenharmony_ci- E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
14462306a36Sopenharmony_ci- if (E == NULL)
14562306a36Sopenharmony_ci-   E = vzalloc(size);
14662306a36Sopenharmony_ci+ E = kvzalloc(size, GFP_KERNEL);
14762306a36Sopenharmony_ci|
14862306a36Sopenharmony_ci- T x = kzalloc(size, flags | __GFP_NOWARN);
14962306a36Sopenharmony_ci- if (x == NULL)
15062306a36Sopenharmony_ci-   x = vzalloc(size);
15162306a36Sopenharmony_ci+ T x = kvzalloc(size, flags);
15262306a36Sopenharmony_ci|
15362306a36Sopenharmony_ci- T x = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
15462306a36Sopenharmony_ci- if (x == NULL)
15562306a36Sopenharmony_ci-   x = vzalloc(size);
15662306a36Sopenharmony_ci+ T x = kvzalloc(size, GFP_KERNEL);
15762306a36Sopenharmony_ci|
15862306a36Sopenharmony_ci- if (size cmp E1)
15962306a36Sopenharmony_ci-    E = kmalloc_node(size, flags, node);
16062306a36Sopenharmony_ci- else
16162306a36Sopenharmony_ci-    E = vmalloc_node(size, node);
16262306a36Sopenharmony_ci+ E = kvmalloc_node(size, flags, node);
16362306a36Sopenharmony_ci|
16462306a36Sopenharmony_ci- if (size cmp E1)
16562306a36Sopenharmony_ci-    E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
16662306a36Sopenharmony_ci- else
16762306a36Sopenharmony_ci-    E = vmalloc_node(size, node);
16862306a36Sopenharmony_ci+ E = kvmalloc_node(size, GFP_KERNEL, node);
16962306a36Sopenharmony_ci|
17062306a36Sopenharmony_ci- E = kmalloc_node(size, flags | __GFP_NOWARN, node);
17162306a36Sopenharmony_ci- if (E == NULL)
17262306a36Sopenharmony_ci-   E = vmalloc_node(size, node);
17362306a36Sopenharmony_ci+ E = kvmalloc_node(size, flags, node);
17462306a36Sopenharmony_ci|
17562306a36Sopenharmony_ci- E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
17662306a36Sopenharmony_ci- if (E == NULL)
17762306a36Sopenharmony_ci-   E = vmalloc_node(size, node);
17862306a36Sopenharmony_ci+ E = kvmalloc_node(size, GFP_KERNEL, node);
17962306a36Sopenharmony_ci|
18062306a36Sopenharmony_ci- T x = kmalloc_node(size, flags | __GFP_NOWARN, node);
18162306a36Sopenharmony_ci- if (x == NULL)
18262306a36Sopenharmony_ci-   x = vmalloc_node(size, node);
18362306a36Sopenharmony_ci+ T x = kvmalloc_node(size, flags, node);
18462306a36Sopenharmony_ci|
18562306a36Sopenharmony_ci- T x = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
18662306a36Sopenharmony_ci- if (x == NULL)
18762306a36Sopenharmony_ci-   x = vmalloc_node(size, node);
18862306a36Sopenharmony_ci+ T x = kvmalloc_node(size, GFP_KERNEL, node);
18962306a36Sopenharmony_ci|
19062306a36Sopenharmony_ci- if (size cmp E1)
19162306a36Sopenharmony_ci-    E = kvzalloc_node(size, flags, node);
19262306a36Sopenharmony_ci- else
19362306a36Sopenharmony_ci-    E = vzalloc_node(size, node);
19462306a36Sopenharmony_ci+ E = kvzalloc_node(size, flags, node);
19562306a36Sopenharmony_ci|
19662306a36Sopenharmony_ci- if (size cmp E1)
19762306a36Sopenharmony_ci-    E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
19862306a36Sopenharmony_ci- else
19962306a36Sopenharmony_ci-    E = vzalloc_node(size, node);
20062306a36Sopenharmony_ci+ E = kvzalloc_node(size, GFP_KERNEL, node);
20162306a36Sopenharmony_ci|
20262306a36Sopenharmony_ci- E = kvzalloc_node(size, flags | __GFP_NOWARN, node);
20362306a36Sopenharmony_ci- if (E == NULL)
20462306a36Sopenharmony_ci-   E = vzalloc_node(size, node);
20562306a36Sopenharmony_ci+ E = kvzalloc_node(size, flags, node);
20662306a36Sopenharmony_ci|
20762306a36Sopenharmony_ci- E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
20862306a36Sopenharmony_ci- if (E == NULL)
20962306a36Sopenharmony_ci-   E = vzalloc_node(size, node);
21062306a36Sopenharmony_ci+ E = kvzalloc_node(size, GFP_KERNEL, node);
21162306a36Sopenharmony_ci|
21262306a36Sopenharmony_ci- T x = kvzalloc_node(size, flags | __GFP_NOWARN, node);
21362306a36Sopenharmony_ci- if (x == NULL)
21462306a36Sopenharmony_ci-   x = vzalloc_node(size, node);
21562306a36Sopenharmony_ci+ T x = kvzalloc_node(size, flags, node);
21662306a36Sopenharmony_ci|
21762306a36Sopenharmony_ci- T x = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
21862306a36Sopenharmony_ci- if (x == NULL)
21962306a36Sopenharmony_ci-   x = vzalloc_node(size, node);
22062306a36Sopenharmony_ci+ T x = kvzalloc_node(size, GFP_KERNEL, node);
22162306a36Sopenharmony_ci)
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci@depends on patch@
22462306a36Sopenharmony_ciexpression E;
22562306a36Sopenharmony_ciposition p : script:python() { relevant(p) };
22662306a36Sopenharmony_ci@@
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci- if (is_vmalloc_addr(E))@p
22962306a36Sopenharmony_ci-   vfree(E);
23062306a36Sopenharmony_ci- else
23162306a36Sopenharmony_ci-   kfree(E);
23262306a36Sopenharmony_ci+ kvfree(E);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci@script: python depends on report@
23562306a36Sopenharmony_cip << kvmalloc.p;
23662306a36Sopenharmony_ci@@
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cicoccilib.report.print_report(p[0], "WARNING opportunity for kvmalloc")
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci@script: python depends on org@
24162306a36Sopenharmony_cip << kvmalloc.p;
24262306a36Sopenharmony_ci@@
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_cicoccilib.org.print_todo(p[0], "WARNING opportunity for kvmalloc")
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci@script: python depends on report@
24762306a36Sopenharmony_cip << kvfree.p;
24862306a36Sopenharmony_ci@@
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_cicoccilib.report.print_report(p[0], "WARNING opportunity for kvfree")
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci@script: python depends on org@
25362306a36Sopenharmony_cip << kvfree.p;
25462306a36Sopenharmony_ci@@
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cicoccilib.org.print_todo(p[0], "WARNING opportunity for kvfree")
257