* [PATCH 0/2] init: fix array boundary bugs in boot parameter parsing
@ 2026-08-18 4:53 Wilson Felipe Pereira
2026-08-18 4:53 ` [PATCH 1/2] init/main: fix off-by-one in argv_init cleanup Wilson Felipe Pereira
2026-08-18 4:53 ` [PATCH 2/2] init/main: fix false-positive kernel panic on environment variable overwrite Wilson Felipe Pereira
0 siblings, 2 replies; 3+ messages in thread
From: Wilson Felipe Pereira @ 2026-08-18 4:53 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, Wilson Felipe Pereira
This series fixes two distinct boundary logic edge-case bugs in
`init/main.c` related to parsing boot command-line arguments and
environment variables. Both bugs have been present since the early
git history (Linux-2.6.12-rc2).
1. The first patch fixes an off-by-one error in `init_setup()` where
the final slot of the `argv_init` array was left uncleared. This
allowed a stale kernel parameter to leak into the `init` process's
user-space command line if exactly `MAX_INIT_ARGS` unknown
parameters were passed.
2. The second patch fixes a false-positive kernel panic in
`unknown_bootoption()`. If a user filled the environment variable
array up to its exact limit (32) and then attempted to overwrite
the final variable, the kernel would panic before evaluating
whether it was a harmless duplicate.
Exact QEMU reproduction steps for both edge cases are documented
inside their respective commit descriptions.
Wilson Felipe Pereira (2):
init/main: fix off-by-one in argv_init cleanup
init/main: fix false-positive kernel panic on environment variable
overwrite
init/main.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--
2.55.0.699.gb54405d56f-goog
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] init/main: fix off-by-one in argv_init cleanup
2026-08-18 4:53 [PATCH 0/2] init: fix array boundary bugs in boot parameter parsing Wilson Felipe Pereira
@ 2026-08-18 4:53 ` Wilson Felipe Pereira
2026-08-18 4:53 ` [PATCH 2/2] init/main: fix false-positive kernel panic on environment variable overwrite Wilson Felipe Pereira
1 sibling, 0 replies; 3+ messages in thread
From: Wilson Felipe Pereira @ 2026-08-18 4:53 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, Wilson Felipe Pereira
When cleaning up argv_init in init_setup() and rdinit_setup(), the loop
terminates one element early due to using '<' instead of '<='. Since
argv_init is sized MAX_INIT_ARGS+2, index MAX_INIT_ARGS is a valid element
that should be cleared to NULL.
If exactly MAX_INIT_ARGS unknown arguments are passed before 'init=', the
uncleared argv_init[MAX_INIT_ARGS] can act as a ghost argument to
/sbin/init or cause a spurious kernel panic when later appended to.
To verify the argument leak, boot a VM into a shell with 32 unknown kernel
arguments, the init parameter, and 31 user arguments:
STALE_ARGS=$(for i in {1..32}; do echo -n "stale$i "; done)
USER_ARGS=$(for i in {1..31}; do echo -n "user$i "; done)
qemu-system-x86_64 -kernel bzImage \
-append "$STALE_ARGS init=/bin/sh $USER_ARGS"
Running `cat /proc/1/cmdline` inside the shell reveals that the 32nd kernel
argument ('stale32') incorrectly leaked into the init process's command
line. This patch zeroes the final slot, cleanly terminating the array.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Fixes: ffdfc40976dd ("[PATCH] Add rdinit parameter to pick early userspace init")
Signed-off-by: Wilson Felipe Pereira <wfelipe@google.com>
---
init/main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/init/main.c b/init/main.c
index 92d34e496a33..f02041a42111 100644
--- a/init/main.c
+++ b/init/main.c
@@ -572,7 +572,7 @@ static int __init init_setup(char *str)
* the shell think it should execute a script with such name.
* So we ignore all arguments entered _before_ init=... [MJ]
*/
- for (i = 1; i < MAX_INIT_ARGS; i++)
+ for (i = 1; i <= MAX_INIT_ARGS; i++)
argv_init[i] = NULL;
return 1;
}
@@ -585,7 +585,7 @@ static int __init rdinit_setup(char *str)
ramdisk_execute_command = str;
ramdisk_execute_command_set = true;
/* See "auto" comment in init_setup */
- for (i = 1; i < MAX_INIT_ARGS; i++)
+ for (i = 1; i <= MAX_INIT_ARGS; i++)
argv_init[i] = NULL;
return 1;
}
--
2.55.0.699.gb54405d56f-goog
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] init/main: fix false-positive kernel panic on environment variable overwrite
2026-08-18 4:53 [PATCH 0/2] init: fix array boundary bugs in boot parameter parsing Wilson Felipe Pereira
2026-08-18 4:53 ` [PATCH 1/2] init/main: fix off-by-one in argv_init cleanup Wilson Felipe Pereira
@ 2026-08-18 4:53 ` Wilson Felipe Pereira
1 sibling, 0 replies; 3+ messages in thread
From: Wilson Felipe Pereira @ 2026-08-18 4:53 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, Wilson Felipe Pereira
In unknown_bootoption(), the limit checking for environment variables
sets panic_later *before* checking if the variable already exists in
envp_init.
If a user passes exactly MAX_INIT_ENVS custom variables and then
overwrites the final variable by matching its key, it causes a
false-positive hard panic on boot despite not actually exceeding the
array bounds or increasing the total variable count.
Swapping the order of these checks allows the duplicate check to
break out of the loop before the panic flag is erroneously latched.
To verify, boot a VM with 31 custom variables (filling the array up to its
limit of 32) and then overwrite the very last variable:
ENV_VARS=$(for i in {1..31}; do echo -n "var$i=$i "; done)
qemu-system-x86_64 -kernel bzImage -append "$ENV_VARS var31=overwrite"
Without this patch, the kernel crashes instantly with:
Kernel panic - not syncing: Too many boot env vars at 'var31=overwrite'
With this patch, the kernel safely overwrites the variable and boots.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Wilson Felipe Pereira <wfelipe@google.com>
---
init/main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/init/main.c b/init/main.c
index f02041a42111..577ae30570e0 100644
--- a/init/main.c
+++ b/init/main.c
@@ -539,12 +539,12 @@ static int __init unknown_bootoption(char *param, char *val,
/* Environment option */
unsigned int i;
for (i = 0; envp_init[i]; i++) {
+ if (!strncmp(param, envp_init[i], len+1))
+ break;
if (i == MAX_INIT_ENVS) {
panic_later = "env";
panic_param = param;
}
- if (!strncmp(param, envp_init[i], len+1))
- break;
}
envp_init[i] = param;
} else {
--
2.55.0.699.gb54405d56f-goog
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-18 4:54 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-18 4:53 [PATCH 0/2] init: fix array boundary bugs in boot parameter parsing Wilson Felipe Pereira
2026-08-18 4:53 ` [PATCH 1/2] init/main: fix off-by-one in argv_init cleanup Wilson Felipe Pereira
2026-08-18 4:53 ` [PATCH 2/2] init/main: fix false-positive kernel panic on environment variable overwrite Wilson Felipe Pereira
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.