proc_do_large_bitmap() does not initialize variable c, which is expected to be set to a trailing character by proc_get_long(). However, proc_get_long() only sets c when the input buffer contains a trailing character after the parsed value. If c is not initialized it may happen to contain a '-'. If this is the case proc_do_large_bitmap() expects to be able to parse a second part of the input buffer. If there is no second part an unjustified -EINVAL will be returned. Initialize c to 0 to prevent returning -EINVAL on valid input. Fixes: 9f977fb7ae9d ("sysctl: add proc_do_large_bitmap") Signed-off-by: Marc Buerg --- When writing to /proc/sys/net/ipv4/ip_local_reserved_ports it is possible to receive an -EINVAL for a valid value. This happens due to an uninitialized variable in the proc_do_large_bitmap() function, namely char c. To trigger this behavior the variable has to contain the later explicitly checked '-' char by chance. In proc_do_large_bitmap() it is expected that the variable might be filled by the proc_get_long() function with the trailing character of the given input. But only if a trailing character exists within the passed size of the buffer. The proc_get_long() function can set c if the length of the parsed long is smaller than the given size of the buffer containing the user input. This is not the case if the buffer only contains the port value (e.g. "123") and sets the size exactly to that (3). Meaning if there is no trailing character, c will not be set. If no trailing character is present we still do a c == '-' check. If the uninitialized variable contains this char the function continues parsing. It will now set err to -EINVAL in the next proc_get_long() call, as there is nothing more to parse. Initializing c to 0 will solve the problem. The problem will only arise sporadically, as the variable must contain '-' by chance. On the affected system CONFIG_INIT_STACK_NONE=y was enabled. Further, when enabling eBPF tracing to dump contents of the stack the issue disappears, which would fit the current explanation as a root cause for the observed behavior. --- Changes in v4: - Re-include set c to 0 - Drop check against left - Move trailers - Removed Reviewed-by: Peter Seiderer - Link to v3: https://lore.kernel.org/r/20260319-fix-uninitialized-variable-in-proc_do_large_bitmap-v3-1-9cfc3ff60c09@googlemail.com Changes in v3: - Add Reviewed-by: Peter Seiderer - Re-include bug context into cover letter - Link to v2: https://lore.kernel.org/r/20260317-fix-uninitialized-variable-in-proc_do_large_bitmap-v2-1-6dfb1aefa287@googlemail.com Changes in v2: - Drop initialization of c to 0 - Include checking that left is non-zero before checking against c - Link to v1: https://lore.kernel.org/r/20260312-fix-uninitialized-variable-in-proc_do_large_bitmap-v1-1-35ad2dddaf21@googlemail.com --- kernel/sysctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 9d3a666ffde1..c9efb17cc255 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1118,7 +1118,7 @@ int proc_do_large_bitmap(const struct ctl_table *table, int dir, unsigned long bitmap_len = table->maxlen; unsigned long *bitmap = *(unsigned long **) table->data; unsigned long *tmp_bitmap = NULL; - char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c; + char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c = 0; if (!bitmap || !bitmap_len || !left || (*ppos && SYSCTL_KERN_TO_USER(dir))) { *lenp = 0; --- base-commit: 80234b5ab240f52fa45d201e899e207b9265ef91 change-id: 20260312-fix-uninitialized-variable-in-proc_do_large_bitmap-30c6ef4ac1c5 Best regards, -- Marc Buerg