144d8870fSDenis Efremov// SPDX-License-Identifier: GPL-2.0-only
244d8870fSDenis Efremov///
344d8870fSDenis Efremov/// Find if/else condition with kmalloc/vmalloc calls.
444d8870fSDenis Efremov/// Suggest to use kvmalloc instead. Same for kvfree.
544d8870fSDenis Efremov///
644d8870fSDenis Efremov// Confidence: High
744d8870fSDenis Efremov// Copyright: (C) 2020 Denis Efremov ISPRAS
844d8870fSDenis Efremov// Options: --no-includes --include-headers
944d8870fSDenis Efremov//
1044d8870fSDenis Efremov
1144d8870fSDenis Efremovvirtual patch
1244d8870fSDenis Efremovvirtual report
1344d8870fSDenis Efremovvirtual org
1444d8870fSDenis Efremovvirtual context
1544d8870fSDenis Efremov
1644d8870fSDenis Efremov@initialize:python@
1744d8870fSDenis Efremov@@
1844d8870fSDenis Efremovfilter = frozenset(['kvfree'])
1944d8870fSDenis Efremov
2044d8870fSDenis Efremovdef relevant(p):
2144d8870fSDenis Efremov    return not (filter & {el.current_element for el in p})
2244d8870fSDenis Efremov
2344d8870fSDenis Efremov@kvmalloc depends on !patch@
2444d8870fSDenis Efremovexpression E, E1, size;
2544d8870fSDenis Efremovidentifier flags;
2644d8870fSDenis Efremovbinary operator cmp = {<=, <, ==, >, >=};
2744d8870fSDenis Efremovidentifier x;
2844d8870fSDenis Efremovtype T;
2944d8870fSDenis Efremovposition p;
3044d8870fSDenis Efremov@@
3144d8870fSDenis Efremov
3244d8870fSDenis Efremov(
3344d8870fSDenis Efremov* if (size cmp E1 || ...)@p {
3444d8870fSDenis Efremov    ...
3544d8870fSDenis Efremov*    E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
3644d8870fSDenis Efremov*          kmalloc_array\|kmalloc_array_node\|kcalloc_node\)
3744d8870fSDenis Efremov*          (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...)
3844d8870fSDenis Efremov    ...
3944d8870fSDenis Efremov  } else {
4044d8870fSDenis Efremov    ...
4144d8870fSDenis Efremov*    E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...)
4244d8870fSDenis Efremov    ...
4344d8870fSDenis Efremov  }
4444d8870fSDenis Efremov|
4544d8870fSDenis Efremov* E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
4644d8870fSDenis Efremov*       kmalloc_array\|kmalloc_array_node\|kcalloc_node\)
4744d8870fSDenis Efremov*       (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...)
4844d8870fSDenis Efremov  ... when != E = E1
4944d8870fSDenis Efremov      when != size = E1
5044d8870fSDenis Efremov      when any
5144d8870fSDenis Efremov* if (E == NULL)@p {
5244d8870fSDenis Efremov    ...
5344d8870fSDenis Efremov*   E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...)
5444d8870fSDenis Efremov    ...
5544d8870fSDenis Efremov  }
5644d8870fSDenis Efremov|
5744d8870fSDenis Efremov* T x = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
5844d8870fSDenis Efremov*         kmalloc_array\|kmalloc_array_node\|kcalloc_node\)
5944d8870fSDenis Efremov*         (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...);
6044d8870fSDenis Efremov  ... when != x = E1
6144d8870fSDenis Efremov      when != size = E1
6244d8870fSDenis Efremov      when any
6344d8870fSDenis Efremov* if (x == NULL)@p {
6444d8870fSDenis Efremov    ...
6544d8870fSDenis Efremov*   x = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...)
6644d8870fSDenis Efremov    ...
6744d8870fSDenis Efremov  }
6844d8870fSDenis Efremov)
6944d8870fSDenis Efremov
7044d8870fSDenis Efremov@kvfree depends on !patch@
7144d8870fSDenis Efremovexpression E;
7244d8870fSDenis Efremovposition p : script:python() { relevant(p) };
7344d8870fSDenis Efremov@@
7444d8870fSDenis Efremov
7544d8870fSDenis Efremov* if (is_vmalloc_addr(E))@p {
7644d8870fSDenis Efremov    ...
7744d8870fSDenis Efremov*   vfree(E)
7844d8870fSDenis Efremov    ...
7944d8870fSDenis Efremov  } else {
8044d8870fSDenis Efremov    ... when != krealloc(E, ...)
8144d8870fSDenis Efremov        when any
82*9eec0792SWeizhao Ouyang*   \(kfree\|kfree_sensitive\)(E)
8344d8870fSDenis Efremov    ...
8444d8870fSDenis Efremov  }
8544d8870fSDenis Efremov
8644d8870fSDenis Efremov@depends on patch@
8744d8870fSDenis Efremovexpression E, E1, size, node;
8844d8870fSDenis Efremovbinary operator cmp = {<=, <, ==, >, >=};
8944d8870fSDenis Efremovidentifier flags, x;
9044d8870fSDenis Efremovtype T;
9144d8870fSDenis Efremov@@
9244d8870fSDenis Efremov
9344d8870fSDenis Efremov(
9444d8870fSDenis Efremov- if (size cmp E1)
9544d8870fSDenis Efremov-    E = kmalloc(size, flags);
9644d8870fSDenis Efremov- else
9744d8870fSDenis Efremov-    E = vmalloc(size);
9844d8870fSDenis Efremov+ E = kvmalloc(size, flags);
9944d8870fSDenis Efremov|
10044d8870fSDenis Efremov- if (size cmp E1)
10144d8870fSDenis Efremov-    E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
10244d8870fSDenis Efremov- else
10344d8870fSDenis Efremov-    E = vmalloc(size);
10444d8870fSDenis Efremov+ E = kvmalloc(size, GFP_KERNEL);
10544d8870fSDenis Efremov|
10644d8870fSDenis Efremov- E = kmalloc(size, flags | __GFP_NOWARN);
10744d8870fSDenis Efremov- if (E == NULL)
10844d8870fSDenis Efremov-   E = vmalloc(size);
10944d8870fSDenis Efremov+ E = kvmalloc(size, flags);
11044d8870fSDenis Efremov|
11144d8870fSDenis Efremov- E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
11244d8870fSDenis Efremov- if (E == NULL)
11344d8870fSDenis Efremov-   E = vmalloc(size);
11444d8870fSDenis Efremov+ E = kvmalloc(size, GFP_KERNEL);
11544d8870fSDenis Efremov|
11644d8870fSDenis Efremov- T x = kmalloc(size, flags | __GFP_NOWARN);
11744d8870fSDenis Efremov- if (x == NULL)
11844d8870fSDenis Efremov-   x = vmalloc(size);
11944d8870fSDenis Efremov+ T x = kvmalloc(size, flags);
12044d8870fSDenis Efremov|
12144d8870fSDenis Efremov- T x = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
12244d8870fSDenis Efremov- if (x == NULL)
12344d8870fSDenis Efremov-   x = vmalloc(size);
12444d8870fSDenis Efremov+ T x = kvmalloc(size, GFP_KERNEL);
12544d8870fSDenis Efremov|
12644d8870fSDenis Efremov- if (size cmp E1)
12744d8870fSDenis Efremov-    E = kzalloc(size, flags);
12844d8870fSDenis Efremov- else
12944d8870fSDenis Efremov-    E = vzalloc(size);
13044d8870fSDenis Efremov+ E = kvzalloc(size, flags);
13144d8870fSDenis Efremov|
13244d8870fSDenis Efremov- if (size cmp E1)
13344d8870fSDenis Efremov-    E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
13444d8870fSDenis Efremov- else
13544d8870fSDenis Efremov-    E = vzalloc(size);
13644d8870fSDenis Efremov+ E = kvzalloc(size, GFP_KERNEL);
13744d8870fSDenis Efremov|
13844d8870fSDenis Efremov- E = kzalloc(size, flags | __GFP_NOWARN);
13944d8870fSDenis Efremov- if (E == NULL)
14044d8870fSDenis Efremov-   E = vzalloc(size);
14144d8870fSDenis Efremov+ E = kvzalloc(size, flags);
14244d8870fSDenis Efremov|
14344d8870fSDenis Efremov- E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
14444d8870fSDenis Efremov- if (E == NULL)
14544d8870fSDenis Efremov-   E = vzalloc(size);
14644d8870fSDenis Efremov+ E = kvzalloc(size, GFP_KERNEL);
14744d8870fSDenis Efremov|
14844d8870fSDenis Efremov- T x = kzalloc(size, flags | __GFP_NOWARN);
14944d8870fSDenis Efremov- if (x == NULL)
15044d8870fSDenis Efremov-   x = vzalloc(size);
15144d8870fSDenis Efremov+ T x = kvzalloc(size, flags);
15244d8870fSDenis Efremov|
15344d8870fSDenis Efremov- T x = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
15444d8870fSDenis Efremov- if (x == NULL)
15544d8870fSDenis Efremov-   x = vzalloc(size);
15644d8870fSDenis Efremov+ T x = kvzalloc(size, GFP_KERNEL);
15744d8870fSDenis Efremov|
15844d8870fSDenis Efremov- if (size cmp E1)
15944d8870fSDenis Efremov-    E = kmalloc_node(size, flags, node);
16044d8870fSDenis Efremov- else
16144d8870fSDenis Efremov-    E = vmalloc_node(size, node);
16244d8870fSDenis Efremov+ E = kvmalloc_node(size, flags, node);
16344d8870fSDenis Efremov|
16444d8870fSDenis Efremov- if (size cmp E1)
16544d8870fSDenis Efremov-    E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
16644d8870fSDenis Efremov- else
16744d8870fSDenis Efremov-    E = vmalloc_node(size, node);
16844d8870fSDenis Efremov+ E = kvmalloc_node(size, GFP_KERNEL, node);
16944d8870fSDenis Efremov|
17044d8870fSDenis Efremov- E = kmalloc_node(size, flags | __GFP_NOWARN, node);
17144d8870fSDenis Efremov- if (E == NULL)
17244d8870fSDenis Efremov-   E = vmalloc_node(size, node);
17344d8870fSDenis Efremov+ E = kvmalloc_node(size, flags, node);
17444d8870fSDenis Efremov|
17544d8870fSDenis Efremov- E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
17644d8870fSDenis Efremov- if (E == NULL)
17744d8870fSDenis Efremov-   E = vmalloc_node(size, node);
17844d8870fSDenis Efremov+ E = kvmalloc_node(size, GFP_KERNEL, node);
17944d8870fSDenis Efremov|
18044d8870fSDenis Efremov- T x = kmalloc_node(size, flags | __GFP_NOWARN, node);
18144d8870fSDenis Efremov- if (x == NULL)
18244d8870fSDenis Efremov-   x = vmalloc_node(size, node);
18344d8870fSDenis Efremov+ T x = kvmalloc_node(size, flags, node);
18444d8870fSDenis Efremov|
18544d8870fSDenis Efremov- T x = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
18644d8870fSDenis Efremov- if (x == NULL)
18744d8870fSDenis Efremov-   x = vmalloc_node(size, node);
18844d8870fSDenis Efremov+ T x = kvmalloc_node(size, GFP_KERNEL, node);
18944d8870fSDenis Efremov|
19044d8870fSDenis Efremov- if (size cmp E1)
19144d8870fSDenis Efremov-    E = kvzalloc_node(size, flags, node);
19244d8870fSDenis Efremov- else
19344d8870fSDenis Efremov-    E = vzalloc_node(size, node);
19444d8870fSDenis Efremov+ E = kvzalloc_node(size, flags, node);
19544d8870fSDenis Efremov|
19644d8870fSDenis Efremov- if (size cmp E1)
19744d8870fSDenis Efremov-    E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
19844d8870fSDenis Efremov- else
19944d8870fSDenis Efremov-    E = vzalloc_node(size, node);
20044d8870fSDenis Efremov+ E = kvzalloc_node(size, GFP_KERNEL, node);
20144d8870fSDenis Efremov|
20244d8870fSDenis Efremov- E = kvzalloc_node(size, flags | __GFP_NOWARN, node);
20344d8870fSDenis Efremov- if (E == NULL)
20444d8870fSDenis Efremov-   E = vzalloc_node(size, node);
20544d8870fSDenis Efremov+ E = kvzalloc_node(size, flags, node);
20644d8870fSDenis Efremov|
20744d8870fSDenis Efremov- E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
20844d8870fSDenis Efremov- if (E == NULL)
20944d8870fSDenis Efremov-   E = vzalloc_node(size, node);
21044d8870fSDenis Efremov+ E = kvzalloc_node(size, GFP_KERNEL, node);
21144d8870fSDenis Efremov|
21244d8870fSDenis Efremov- T x = kvzalloc_node(size, flags | __GFP_NOWARN, node);
21344d8870fSDenis Efremov- if (x == NULL)
21444d8870fSDenis Efremov-   x = vzalloc_node(size, node);
21544d8870fSDenis Efremov+ T x = kvzalloc_node(size, flags, node);
21644d8870fSDenis Efremov|
21744d8870fSDenis Efremov- T x = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
21844d8870fSDenis Efremov- if (x == NULL)
21944d8870fSDenis Efremov-   x = vzalloc_node(size, node);
22044d8870fSDenis Efremov+ T x = kvzalloc_node(size, GFP_KERNEL, node);
22144d8870fSDenis Efremov)
22244d8870fSDenis Efremov
22344d8870fSDenis Efremov@depends on patch@
22444d8870fSDenis Efremovexpression E;
22544d8870fSDenis Efremovposition p : script:python() { relevant(p) };
22644d8870fSDenis Efremov@@
22744d8870fSDenis Efremov
22844d8870fSDenis Efremov- if (is_vmalloc_addr(E))@p
22944d8870fSDenis Efremov-   vfree(E);
23044d8870fSDenis Efremov- else
23144d8870fSDenis Efremov-   kfree(E);
23244d8870fSDenis Efremov+ kvfree(E);
23344d8870fSDenis Efremov
23444d8870fSDenis Efremov@script: python depends on report@
23544d8870fSDenis Efremovp << kvmalloc.p;
23644d8870fSDenis Efremov@@
23744d8870fSDenis Efremov
23844d8870fSDenis Efremovcoccilib.report.print_report(p[0], "WARNING opportunity for kvmalloc")
23944d8870fSDenis Efremov
24044d8870fSDenis Efremov@script: python depends on org@
24144d8870fSDenis Efremovp << kvmalloc.p;
24244d8870fSDenis Efremov@@
24344d8870fSDenis Efremov
24444d8870fSDenis Efremovcoccilib.org.print_todo(p[0], "WARNING opportunity for kvmalloc")
24544d8870fSDenis Efremov
24644d8870fSDenis Efremov@script: python depends on report@
24744d8870fSDenis Efremovp << kvfree.p;
24844d8870fSDenis Efremov@@
24944d8870fSDenis Efremov
25044d8870fSDenis Efremovcoccilib.report.print_report(p[0], "WARNING opportunity for kvfree")
25144d8870fSDenis Efremov
25244d8870fSDenis Efremov@script: python depends on org@
25344d8870fSDenis Efremovp << kvfree.p;
25444d8870fSDenis Efremov@@
25544d8870fSDenis Efremov
25644d8870fSDenis Efremovcoccilib.org.print_todo(p[0], "WARNING opportunity for kvfree")
257