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