mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] checkpatch: add vmalloc() and vzalloc() to alloc with multiplies check
@ 2026-10-15  0:20 Iurii Trukhin
  2026-10-19  7:19 ` Alejandro Colomar
  2026-10-19  9:30 ` [PATCH v2] " Iurii Trukhin
  0 siblings, 2 replies; 4+ messages in thread
From: Iurii Trukhin @ 2026-10-15  0:20 UTC (permalink / raw)
  To: Andy Whitcroft, Joe Perches
  Cc: Andrew Morton, Kees Cook, Gustavo A. R. Silva, linux-hardening,
	linux-kernel, Iurii Trukhin

vmalloc() and vzalloc() have 2-factor multiplication argument forms
vmalloc_array() and vcalloc() in <linux/vmalloc.h> that protect against
integer overflow during size calculation.

Commit 070580b0b174 ("checkpatch: Suggest kmalloc_obj family for sizeof
allocations") updated ALLOC_WITH_MULTIPLY for the (kv|k)[mz]alloc()
family to suggest kmalloc_objs(type, count, gfp), while vmalloc_array()
and vcalloc() retain the (count, size) signature.

Extend ALLOC_WITH_MULTIPLY to warn when vmalloc() or vzalloc() is called
with a 2-factor sizeof() multiplication and suggest vmalloc_array() or
vcalloc() respectively, including --fix support. Also include the 'v'
prefix in ALLOC_ARRAY_ARGS so swapped sizeof() first arguments to
vmalloc_array() and vcalloc() are flagged.

Link: https://github.com/KSPP/linux/issues/342
Signed-off-by: Iurii Trukhin <yuri@trukhin.com>
---
 scripts/checkpatch.pl | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 8a7787d228a6..651a46f1fc40 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -7355,10 +7355,11 @@ sub process {
 		}


-# check for (kv|k)[mz]alloc with multiplies that could be
kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs
+# check for (kv|k|v)[mz]alloc with multiplies that could be
+# kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs/vmalloc_array/vcalloc
 		if ($perl_version_ok &&
 		    defined $stat &&
-		    $stat =~
/^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/)
{
+		    $stat =~
/^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*(?:,|\))/)
{
 			my $oldfunc = $3;
 			my $a1 = $4;
 			my $a2 = $10;
@@ -7366,6 +7367,8 @@ sub process {
 			$newfunc = "kvmalloc_objs" if ($oldfunc eq "kvmalloc");
 			$newfunc = "kvzalloc_objs" if ($oldfunc eq "kvzalloc");
 			$newfunc = "kzalloc_objs" if ($oldfunc eq "kzalloc");
+			$newfunc = "vmalloc_array" if ($oldfunc eq "vmalloc");
+			$newfunc = "vcalloc" if ($oldfunc eq "vzalloc");
 			my $r1 = $a1;
 			my $r2 = $a2;
 			if ($a1 =~ /^sizeof\s*\S/) {
@@ -7381,9 +7384,13 @@ sub process {
 					 "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
 				    $cnt == 1 &&
 				    $fix) {
-					my $sized = trim($r2);
-					$sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;
-					$fixed[$fixlinenr] =~
s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1
. ' = ' . "$newfunc(" . $sized . ', ' . trim($r1)/e;
+					if ($oldfunc =~ /^v/) {
+						$fixed[$fixlinenr] =~
s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(v[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1
. ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
+					} else {
+						my $sized = trim($r2);
+						$sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;
+						$fixed[$fixlinenr] =~
s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1
. ' = ' . "$newfunc(" . $sized . ', ' . trim($r1)/e;
+					}
 				}
 			}
 		}
@@ -7397,7 +7404,7 @@ sub process {
 		}

 # check for alloc argument mismatch
-		if ($line =~
/\b((?:devm_)?((?:k|kv)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/)
{
+		if ($line =~
/\b((?:devm_)?((?:k|kv|v)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/)
{
 			WARN("ALLOC_ARRAY_ARGS",
 			     "$1 uses number as first arg, sizeof is generally wrong\n" .
$herecurr);
 		}
-- 
2.56.0

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] checkpatch: add vmalloc() and vzalloc() to alloc with multiplies check
  2026-10-15  0:20 [PATCH] checkpatch: add vmalloc() and vzalloc() to alloc with multiplies check Iurii Trukhin
@ 2026-10-19  7:19 ` Alejandro Colomar
  2026-10-19  9:30   ` Iurii Trukhin
  2026-10-19  9:30 ` [PATCH v2] " Iurii Trukhin
  1 sibling, 1 reply; 4+ messages in thread
From: Alejandro Colomar @ 2026-10-19  7:19 UTC (permalink / raw)
  To: Iurii Trukhin
  Cc: Andy Whitcroft, Joe Perches, Andrew Morton, Kees Cook,
	Gustavo A. R. Silva, linux-hardening, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 4411 bytes --]

Hi Iurii, Kees,

> Date: 2026-10-14 20:20:06-0400
> From: Iurii Trukhin <yuri@trukhin.com>
>
> vmalloc() and vzalloc() have 2-factor multiplication argument forms
> vmalloc_array() and vcalloc() in <linux/vmalloc.h> that protect against
> integer overflow during size calculation.
> 
> Commit 070580b0b174 ("checkpatch: Suggest kmalloc_obj family for sizeof
> allocations") updated ALLOC_WITH_MULTIPLY for the (kv|k)[mz]alloc()
> family to suggest kmalloc_objs(type, count, gfp), while vmalloc_array()
> and vcalloc() retain the (count, size) signature.
> 
> Extend ALLOC_WITH_MULTIPLY to warn when vmalloc() or vzalloc() is called
> with a 2-factor sizeof() multiplication and suggest vmalloc_array() or
> vcalloc() respectively, including --fix support. Also include the 'v'
> prefix in ALLOC_ARRAY_ARGS so swapped sizeof() first arguments to
> vmalloc_array() and vcalloc() are flagged.
> 
> Link: https://github.com/KSPP/linux/issues/342
> Signed-off-by: Iurii Trukhin <yuri@trukhin.com>
> ---
>  scripts/checkpatch.pl | 19 +++++++++++++------
>  1 file changed, 13 insertions(+), 6 deletions(-)
> 
> diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
> index 8a7787d228a6..651a46f1fc40 100755
> --- a/scripts/checkpatch.pl
> +++ b/scripts/checkpatch.pl
> @@ -7355,10 +7355,11 @@ sub process {
>  		}
> 
> 
> -# check for (kv|k)[mz]alloc with multiplies that could be
> kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs
> +# check for (kv|k|v)[mz]alloc with multiplies that could be
> +# kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs/vmalloc_array/vcalloc
>  		if ($perl_version_ok &&
>  		    defined $stat &&
> -		    $stat =~
> /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/)
> {
> +		    $stat =~
> /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*(?:,|\))/)
> {
>  			my $oldfunc = $3;
>  			my $a1 = $4;
>  			my $a2 = $10;
> @@ -7366,6 +7367,8 @@ sub process {
>  			$newfunc = "kvmalloc_objs" if ($oldfunc eq "kvmalloc");
>  			$newfunc = "kvzalloc_objs" if ($oldfunc eq "kvzalloc");
>  			$newfunc = "kzalloc_objs" if ($oldfunc eq "kzalloc");
> +			$newfunc = "vmalloc_array" if ($oldfunc eq "vmalloc");
> +			$newfunc = "vcalloc" if ($oldfunc eq "vzalloc");
>  			my $r1 = $a1;
>  			my $r2 = $a2;
>  			if ($a1 =~ /^sizeof\s*\S/) {
> @@ -7381,9 +7384,13 @@ sub process {
>  					 "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
>  				    $cnt == 1 &&
>  				    $fix) {
> -					my $sized = trim($r2);
> -					$sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;
> -					$fixed[$fixlinenr] =~
> s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1
> . ' = ' . "$newfunc(" . $sized . ', ' . trim($r1)/e;
> +					if ($oldfunc =~ /^v/) {
> +						$fixed[$fixlinenr] =~
> s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(v[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1
> . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
> +					} else {
> +						my $sized = trim($r2);
> +						$sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;
> +						$fixed[$fixlinenr] =~
> s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1
> . ' = ' . "$newfunc(" . $sized . ', ' . trim($r1)/e;
> +					}

Could the suggested fix add a typeof() to the first parameter?  The only
reason (AFAIK) Kees avoided adding typeof() in the first parameter was
to minimize churn, but if someone is going to fix new code, it would be
better if they do it good.  The good thing about using types explicitly
is that it's safer.

That is, it should suggest
	kmalloc_objs(typeof(*p), count, gfp)
instead of
	kmalloc_objs(*p, count, gfp)


What do you think?


Have a lovely day!
Alex

>  				}
>  			}
>  		}
> @@ -7397,7 +7404,7 @@ sub process {
>  		}
> 
>  # check for alloc argument mismatch
> -		if ($line =~
> /\b((?:devm_)?((?:k|kv)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/)
> {
> +		if ($line =~
> /\b((?:devm_)?((?:k|kv|v)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/)
> {
>  			WARN("ALLOC_ARRAY_ARGS",
>  			     "$1 uses number as first arg, sizeof is generally wrong\n" .
> $herecurr);
>  		}
> -- 
> 2.56.0
> 

-- 
<https://www.alejandro-colomar.es>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] checkpatch: add vmalloc() and vzalloc() to alloc with multiplies check
  2026-10-19  7:19 ` Alejandro Colomar
@ 2026-10-19  9:30   ` Iurii Trukhin
  0 siblings, 0 replies; 4+ messages in thread
From: Iurii Trukhin @ 2026-10-19  9:30 UTC (permalink / raw)
  To: Alejandro Colomar
  Cc: Andy Whitcroft, Joe Perches, Andrew Morton, Kees Cook,
	Gustavo A. R. Silva, linux-hardening, linux-kernel

Hi Alex,

Using typeof(*p) for the existing k/kv object helpers makes sense.
vmalloc_array() and vcalloc() take a count and a byte size, so their
fix needs to retain sizeof(...).

I suggest handling the k/kv change separately. While testing this patch,
I also found that the new vmalloc --fix path could copy masked strings
or comments from checkpatch's parsed statement. The prepared v2 uses
the original source instead; the regression tests cover those cases
and check the existing k/kv behavior.

Kees, would you prefer the typeof() change here or as a follow-up?

Thanks,
Iurii


On Mon, 19 Oct 2026 09:19:48 +0200, Alejandro Colomar
<alx+linux-hardening@kernel.org> wrote:
> Hi Iurii, Kees,
>
> > Date: 2026-10-14 20:20:06-0400
> > From: Iurii Trukhin <yuri@trukhin.com>
> >
> > vmalloc() and vzalloc() have 2-factor multiplication argument forms
> > vmalloc_array() and vcalloc() in <linux/vmalloc.h> that protect against
> > integer overflow during size calculation.
> >
> > Commit 070580b0b174 ("checkpatch: Suggest kmalloc_obj family for sizeof
> > allocations") updated ALLOC_WITH_MULTIPLY for the (kv|k)[mz]alloc()
> > family to suggest kmalloc_objs(type, count, gfp), while vmalloc_array()
> > and vcalloc() retain the (count, size) signature.
> >
> > Extend ALLOC_WITH_MULTIPLY to warn when vmalloc() or vzalloc() is called
> > with a 2-factor sizeof() multiplication and suggest vmalloc_array() or
> > vcalloc() respectively, including --fix support. Also include the 'v'
> > prefix in ALLOC_ARRAY_ARGS so swapped sizeof() first arguments to
> > vmalloc_array() and vcalloc() are flagged.
> >
> > Link: https://github.com/KSPP/linux/issues/342
> > Signed-off-by: Iurii Trukhin <yuri@trukhin.com>
> > ---
> >  scripts/checkpatch.pl | 19 +++++++++++++------
> >  1 file changed, 13 insertions(+), 6 deletions(-)
> >
> > diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
> > index 8a7787d228a6..651a46f1fc40 100755
> > --- a/scripts/checkpatch.pl
> > +++ b/scripts/checkpatch.pl
> > @@ -7355,10 +7355,11 @@ sub process {
> >  		}
> >
> >
> > -# check for (kv|k)[mz]alloc with multiplies that could be
> > kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs
> > +# check for (kv|k|v)[mz]alloc with multiplies that could be
> > +# kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs/vmalloc_array/vcalloc
> >  		if ($perl_version_ok &&
> >  		    defined $stat &&
> > -		    $stat =~
> > /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/)
> > {
> > +		    $stat =~
> > /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*(?:,|\))/)
> > {
> >  			my $oldfunc = $3;
> >  			my $a1 = $4;
> >  			my $a2 = $10;
> > @@ -7366,6 +7367,8 @@ sub process {
> >  			$newfunc = "kvmalloc_objs" if ($oldfunc eq "kvmalloc");
> >  			$newfunc = "kvzalloc_objs" if ($oldfunc eq "kvzalloc");
> >  			$newfunc = "kzalloc_objs" if ($oldfunc eq "kzalloc");
> > +			$newfunc = "vmalloc_array" if ($oldfunc eq "vmalloc");
> > +			$newfunc = "vcalloc" if ($oldfunc eq "vzalloc");
> >  			my $r1 = $a1;
> >  			my $r2 = $a2;
> >  			if ($a1 =~ /^sizeof\s*\S/) {
> > @@ -7381,9 +7384,13 @@ sub process {
> >  					 "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
> >  				    $cnt == 1 &&
> >  				    $fix) {
> > -					my $sized = trim($r2);
> > -					$sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;
> > -					$fixed[$fixlinenr] =~
> > s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1
> > . ' = ' . "$newfunc(" . $sized . ', ' . trim($r1)/e;
> > +					if ($oldfunc =~ /^v/) {
> > +						$fixed[$fixlinenr] =~
> > s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(v[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1
> > . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
> > +					} else {
> > +						my $sized = trim($r2);
> > +						$sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;
> > +						$fixed[$fixlinenr] =~
> > s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1
> > . ' = ' . "$newfunc(" . $sized . ', ' . trim($r1)/e;
> > +					}
>
> Could the suggested fix add a typeof() to the first parameter?  The only
> reason (AFAIK) Kees avoided adding typeof() in the first parameter was
> to minimize churn, but if someone is going to fix new code, it would be
> better if they do it good.  The good thing about using types explicitly
> is that it's safer.
>
> That is, it should suggest
> 	kmalloc_objs(typeof(*p), count, gfp)
> instead of
> 	kmalloc_objs(*p, count, gfp)
>
>
> What do you think?
>
>
> Have a lovely day!
> Alex
>
> >  				}
> >  			}
> >  		}
> > @@ -7397,7 +7404,7 @@ sub process {
> >  		}
> >
> >  # check for alloc argument mismatch
> > -		if ($line =~
> > /\b((?:devm_)?((?:k|kv)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/)
> > {
> > +		if ($line =~
> > /\b((?:devm_)?((?:k|kv|v)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/)
> > {
> >  			WARN("ALLOC_ARRAY_ARGS",
> >  			     "$1 uses number as first arg, sizeof is generally wrong\n" .
> > $herecurr);
> >  		}
> > --
> > 2.56.0
> >
>
> --
> <https://www.alejandro-colomar.es>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2] checkpatch: add vmalloc() and vzalloc() to alloc with multiplies check
  2026-10-15  0:20 [PATCH] checkpatch: add vmalloc() and vzalloc() to alloc with multiplies check Iurii Trukhin
  2026-10-19  7:19 ` Alejandro Colomar
@ 2026-10-19  9:30 ` Iurii Trukhin
  1 sibling, 0 replies; 4+ messages in thread
From: Iurii Trukhin @ 2026-10-19  9:30 UTC (permalink / raw)
  To: Andy Whitcroft, Joe Perches
  Cc: Alejandro Colomar, Andrew Morton, Kees Cook, Gustavo A. R. Silva,
	linux-hardening, linux-kernel

vmalloc() and vzalloc() take a byte count, but ALLOC_WITH_MULTIPLY does
not suggest their overflow-checking array helpers for allocations such
as vmalloc(n * sizeof(*p)).

Extend the check to suggest vmalloc_array() and vcalloc(). Unlike the
k/kv object helpers, these functions take a count and a size, so keep
the sizeof expression when generating a fix. Use the original source
for both factors to preserve strings and comments masked in the parsed
statement, and leave the fix alone if another check has changed the line.

Also include the v prefix in ALLOC_ARRAY_ARGS to flag sizeof as the first
argument of vmalloc_array() and vcalloc().

Link: https://github.com/KSPP/linux/issues/342
Assisted-by: LLM
Signed-off-by: Iurii Trukhin <yuri@trukhin.com>
---
Changes in v2:
- Preserve strings and comments in both factors by using their original
  source positions, instead of the sanitized statement.
- Preserve allocation casts and skip the fix if another check changed
  the line before this rule ran.
- Acknowledge coding assistance.

v1: https://lore.kernel.org/all/CAOx7e9K707oLMN94TC=FBBZYKnwACsN-8mDVjsL+N+BBCmWTOA@mail.gmail.com/

Testing:
- perl -c and checkpatch --strict.
- Allocator regression cases, including factor order, nested expressions,
  strings, escapes, comments, extra factors and multiline statements.
- Compiled and ran 12 generated C expressions to check that the rewritten
  allocations preserve the original size calculation.
- Compared the existing k/kv diagnostics and fixes with the unmodified
  script; checked application to mainline, linux-next and mm-nonmm-unstable.

LLM assistance was used to extend the rule, review the change and develop
and run the regression tests.

 scripts/checkpatch.pl | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 8a7787d228a6..cf2dd0b7c372 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -7355,17 +7355,22 @@ sub process {
 		}


-# check for (kv|k)[mz]alloc with multiplies that could be
kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs
+# check for (kv|k|v)[mz]alloc with multiplies that could be
+# kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs/vmalloc_array/vcalloc
 		if ($perl_version_ok &&
 		    defined $stat &&
-		    $stat =~
/^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/)
{
+		    $stat =~
/^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*(?:,|\))/)
{
 			my $oldfunc = $3;
 			my $a1 = $4;
 			my $a2 = $10;
+			my ($alloc_start, $a1_start, $a1_end, $a2_start, $a2_end) =
+			   ($-[3], $-[4], $+[4], $-[10], $+[10]);
 			my $newfunc = "kmalloc_objs";
 			$newfunc = "kvmalloc_objs" if ($oldfunc eq "kvmalloc");
 			$newfunc = "kvzalloc_objs" if ($oldfunc eq "kvzalloc");
 			$newfunc = "kzalloc_objs" if ($oldfunc eq "kzalloc");
+			$newfunc = "vmalloc_array" if ($oldfunc eq "vmalloc");
+			$newfunc = "vcalloc" if ($oldfunc eq "vzalloc");
 			my $r1 = $a1;
 			my $r2 = $a2;
 			if ($a1 =~ /^sizeof\s*\S/) {
@@ -7381,9 +7386,20 @@ sub process {
 					 "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
 				    $cnt == 1 &&
 				    $fix) {
-					my $sized = trim($r2);
-					$sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;
-					$fixed[$fixlinenr] =~
s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1
. ' = ' . "$newfunc(" . $sized . ', ' . trim($r1)/e;
+					if ($oldfunc =~ /^v/) {
+						# Preserve strings and comments masked in $stat.
+						if ($fixed[$fixlinenr] eq $rawline) {
+							my $raw1 = substr($rawline, $a1_start, $a1_end - $a1_start);
+							my $raw2 = substr($rawline, $a2_start, $a2_end - $a2_start);
+							($raw1, $raw2) = ($raw2, $raw1) if ($a1 =~ /^sizeof\s*\S/);
+							substr($fixed[$fixlinenr], $alloc_start, $a2_end - $alloc_start,
+							       "$newfunc(" . trim($raw1) . ', ' . trim($raw2));
+						}
+					} else {
+						my $sized = trim($r2);
+						$sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;
+						$fixed[$fixlinenr] =~
s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1
. ' = ' . "$newfunc(" . $sized . ', ' . trim($r1)/e;
+					}
 				}
 			}
 		}
@@ -7397,7 +7413,7 @@ sub process {
 		}

 # check for alloc argument mismatch
-		if ($line =~
/\b((?:devm_)?((?:k|kv)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/)
{
+		if ($line =~
/\b((?:devm_)?((?:k|kv|v)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/)
{
 			WARN("ALLOC_ARRAY_ARGS",
 			     "$1 uses number as first arg, sizeof is generally wrong\n" .
$herecurr);
 		}

base-commit: 4056b3c9d3c92ea45955641dbafeb9b960e146ef
-- 
2.56.0



On Wed, 14 Oct 2026 20:20:06 -0400, Iurii Trukhin <yuri@trukhin.com> wrote:
> vmalloc() and vzalloc() have 2-factor multiplication argument forms
> vmalloc_array() and vcalloc() in <linux/vmalloc.h> that protect against
> integer overflow during size calculation.
>
> Commit 070580b0b174 ("checkpatch: Suggest kmalloc_obj family for sizeof
> allocations") updated ALLOC_WITH_MULTIPLY for the (kv|k)[mz]alloc()
> family to suggest kmalloc_objs(type, count, gfp), while vmalloc_array()
> and vcalloc() retain the (count, size) signature.
>
> Extend ALLOC_WITH_MULTIPLY to warn when vmalloc() or vzalloc() is called
> with a 2-factor sizeof() multiplication and suggest vmalloc_array() or
> vcalloc() respectively, including --fix support. Also include the 'v'
> prefix in ALLOC_ARRAY_ARGS so swapped sizeof() first arguments to
> vmalloc_array() and vcalloc() are flagged.
>
> Link: https://github.com/KSPP/linux/issues/342
> Signed-off-by: Iurii Trukhin <yuri@trukhin.com>
> ---
>  scripts/checkpatch.pl | 19 +++++++++++++------
>  1 file changed, 13 insertions(+), 6 deletions(-)
>
> diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
> index 8a7787d228a6..651a46f1fc40 100755
> --- a/scripts/checkpatch.pl
> +++ b/scripts/checkpatch.pl
> @@ -7355,10 +7355,11 @@ sub process {
>  		}
>
>
> -# check for (kv|k)[mz]alloc with multiplies that could be kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs
> +# check for (kv|k|v)[mz]alloc with multiplies that could be
> +# kmalloc_objs/kvmalloc_objs/kzalloc_objs/kvzalloc_objs/vmalloc_array/vcalloc
>  		if ($perl_version_ok &&
>  		    defined $stat &&
> -		    $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
> +		    $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*(?:,|\))/) {
>  			my $oldfunc = $3;
>  			my $a1 = $4;
>  			my $a2 = $10;
> @@ -7366,6 +7367,8 @@ sub process {
>  			$newfunc = "kvmalloc_objs" if ($oldfunc eq "kvmalloc");
>  			$newfunc = "kvzalloc_objs" if ($oldfunc eq "kvzalloc");
>  			$newfunc = "kzalloc_objs" if ($oldfunc eq "kzalloc");
> +			$newfunc = "vmalloc_array" if ($oldfunc eq "vmalloc");
> +			$newfunc = "vcalloc" if ($oldfunc eq "vzalloc");
>  			my $r1 = $a1;
>  			my $r2 = $a2;
>  			if ($a1 =~ /^sizeof\s*\S/) {
> @@ -7381,9 +7384,13 @@ sub process {
>  					 "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
>  				    $cnt == 1 &&
>  				    $fix) {
> -					my $sized = trim($r2);
> -					$sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;
> -					$fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . $sized . ', ' . trim($r1)/e;
> +					if ($oldfunc =~ /^v/) {
> +						$fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(v[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
> +					} else {
> +						my $sized = trim($r2);
> +						$sized =~ s/^sizeof\s*\S\(?([^\)]*)\)?$/$1/;
> +						$fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . $sized . ', ' . trim($r1)/e;
> +					}
>  				}
>  			}
>  		}
> @@ -7397,7 +7404,7 @@ sub process {
>  		}
>
>  # check for alloc argument mismatch
> -		if ($line =~ /\b((?:devm_)?((?:k|kv)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/) {
> +		if ($line =~ /\b((?:devm_)?((?:k|kv|v)?(calloc|malloc_array)(?:_node)?))\s*\(\s*sizeof\b/) {
>  			WARN("ALLOC_ARRAY_ARGS",
>  			     "$1 uses number as first arg, sizeof is generally wrong\n" . $herecurr);
>  		}
> --
> 2.56.0

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-10-19  9:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-15  0:20 [PATCH] checkpatch: add vmalloc() and vzalloc() to alloc with multiplies check Iurii Trukhin
2026-10-19  7:19 ` Alejandro Colomar
2026-10-19  9:30   ` Iurii Trukhin
2026-10-19  9:30 ` [PATCH v2] " Iurii Trukhin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®