Re: [PATCH v3] sysctl: fix check against uninitialized variable in proc_do_large_bitmap

From: buermarc

Date: Tue Mar 24 2026 - 18:36:52 EST


From: Marc Buerg <buermarc@xxxxxxxxxxxxxx>

Hi,

On Tue, 24 Mar 2026 08:44:13 +0100 Joel Granados, wrote:

> 1. len is calculated by doing len = p - tmp
> 2. tmp is the beginning of the buffer
> 3. p is the first character that is not a digit.
>
> There will always be at least one ('\0') character that is not a digit.

Yes.

> So len will be less than size at least by one (could be more if the
> string contains non digit chars). When it is parsed to the end,
> len will be less than size by one.

I don't think this is the case. See below.

> TL;DR

I'll try to make it shorter. size is the length of the user buffer, even
after the copy to the kernel buffer. The added '\0' does not increment
size in proc_sys_call_handler(). Following the example for
write(fd,"123",3). In the beginning of proc_get_long():

size = 3

@:012 3
-------
"123\0"
|
tmp=@0
|
p=@0

After strtoul_lenient():

@:012 3
-------
"123\0"
| |
tmp=@0
|
p=@3

@3 - @0 = 3
len = 3

(len < size) => (3 < 3) => false

And size must be 3, proc_sys_call_handler() does not increment it. If we
provide something like write(fd,"123\0",4) size will be 4, but now we will
return -EINVAL.

If len < size is true, we call memchk(). memchk will not find a trailing
character as p points to '\0'. This means in this case we would return
-EINVAL for the first proc_get_long() call in the while loop. Reason is
'\0' is not in tr_a and therefore not a valid delimiter for the first
proc_get_long() call.

I hope this get's my point across.

> All this holds unless the trailing '\0' is modified in some way in that
> BPF call.

To my knowledge there was no bpf tracing enabled on the affected host at
the time that the behavior was observed.

Finally: the fix which adds a check for left introduces a regression.
"123-" is wrongly accepted. Not sure if you saw my other message. It
should not be used.

Best Regards,
Marc