From: Tom Rini OK. After looking harder at the console= stuff, here's what I'm proposing (and, FWIW, I hope Rusty is right and all of the parse_arg stuff can be called very early). - Drop early-param-fixes.patch (or replace with this) From: Tom Rini - In parse_early_options, find the end of each argument (' ') and assume if no space, we are the last arg. After a sucessful call, move past the argument as it might have been spliced up with NULs. - In console_setup, ensure that name and options are NUL-terminated. - Document the restrictions on __early_param calls. --- /dev/null | 0 25-akpm/include/linux/init.h | 5 ++++- 25-akpm/init/main.c | 25 +++++++++++++++++++------ 25-akpm/kernel/printk.c | 8 ++++++-- 4 files changed, 29 insertions(+), 9 deletions(-) diff -puN include/linux/init.h~early-param-fixes-2 include/linux/init.h --- 25/include/linux/init.h~early-param-fixes-2 2004-03-31 22:35:18.862124464 -0800 +++ 25-akpm/include/linux/init.h 2004-03-31 22:35:18.868123552 -0800 @@ -68,7 +68,10 @@ extern initcall_t __con_initcall_start, extern initcall_t __security_initcall_start, __security_initcall_end; /* - * Early command line parameters. + * Early command line parameters. We do not allow for spaces in + * our arguments. Functions are allowed to fail (negative return + * value) but must ensure the arg is unchanged, and can only splice + * the arg up, and not rewrite it. */ struct early_params { const char *arg; diff -L include/linux/init.h.orig -puN /dev/null /dev/null diff -puN init/main.c~early-param-fixes-2 init/main.c --- 25/init/main.c~early-param-fixes-2 2004-03-31 22:35:18.863124312 -0800 +++ 25-akpm/init/main.c 2004-03-31 22:35:34.021819840 -0800 @@ -419,18 +419,31 @@ void __init parse_early_options(char **c for (;;) { if (c == ' ') { struct early_params *p; + char *before = from; for (p = &__early_begin; p < &__early_end; p++) { int len = strlen(p->arg); if (memcmp(from, p->arg, len) == 0) { - if (to != *cmdline_p) - to -= 1; - from += len; - p->fn(from); + char *after; - while (*from != ' ' && *from != '\0') - from++; + from += len; + /* Find the end of this arg, and + * no spaces allowed in an arg. */ + after = strchr(from, ' '); + if (p->fn(from) < 0) { + from = before; + break; + } + + /* Advance the string. */ + if (after) { + *after = ' '; + from = after; + } else { + while (*from != '\0') + from++; + } break; } } diff -puN kernel/printk.c~early-param-fixes-2 kernel/printk.c --- 25/kernel/printk.c~early-param-fixes-2 2004-03-31 22:35:18.865124008 -0800 +++ 25-akpm/kernel/printk.c 2004-03-31 22:35:18.870123248 -0800 @@ -123,7 +123,8 @@ static int __init console_setup(char *st int idx; /* - * Decode str into name, index, options. + * Decode str into name, index, options, ensure name and + * options are NUL-terminated. */ if (str[0] >= '0' && str[0] <= '9') { strcpy(name, "ttyS"); @@ -131,8 +132,11 @@ static int __init console_setup(char *st } else strncpy(name, str, sizeof(name) - 1); name[sizeof(name) - 1] = 0; - if ((options = strchr(str, ',')) != NULL) + if ((options = strchr(str, ',')) != NULL) { *(options++) = 0; + if ((s = strchr(options, ' ')) != NULL) + *s = 0; + } #ifdef __sparc__ if (!strcmp(str, "ttya")) strcpy(name, "ttyS0"); diff -L kernel/printk.c.orig -puN /dev/null /dev/null _