From b88c50ac304a14f14e70c4ad22577b6b84632d5e Mon Sep 17 00:00:00 2001 From: Arvind Sankar Date: Thu, 30 Jan 2020 22:17:13 -0800 Subject: init/main.c: log arguments and environment passed to init Extend logging in `run_init_process` to also show the arguments and environment that we are passing to init. Link: http://lkml.kernel.org/r/20191212180023.24339-2-nivedita@alum.mit.edu Signed-off-by: Arvind Sankar Cc: Chris Metcalf Cc: Krzysztof Mazur Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/main.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'init/main.c') diff --git a/init/main.c b/init/main.c index db13a76c036e..424d88fef08e 100644 --- a/init/main.c +++ b/init/main.c @@ -1043,8 +1043,16 @@ static void __init do_pre_smp_initcalls(void) static int run_init_process(const char *init_filename) { + const char *const *p; + argv_init[0] = init_filename; pr_info("Run %s as init process\n", init_filename); + pr_debug(" with arguments:\n"); + for (p = argv_init; *p; p++) + pr_debug(" %s\n", *p); + pr_debug(" with environment:\n"); + for (p = envp_init; *p; p++) + pr_debug(" %s\n", *p); return do_execve(getname_kernel(init_filename), (const char __user *const __user *)argv_init, (const char __user *const __user *)envp_init); -- cgit v1.2.3 From 7e2762e1d9f4b9cb67ed6c3b7aff2020c367d4ac Mon Sep 17 00:00:00 2001 From: Arvind Sankar Date: Thu, 30 Jan 2020 22:17:16 -0800 Subject: init/main.c: remove unnecessary repair_env_string in do_initcall_level Since commit 08746a65c296 ("init: fix in-place parameter modification regression"), parse_args in do_initcall_level is called on a copy of saved_command_line. It is unnecessary to call repair_env_string during this parsing, as this copy is not used for anything later. Remove the now unnecessary arguments from repair_env_string as well. Link: http://lkml.kernel.org/r/20191212180023.24339-3-nivedita@alum.mit.edu Signed-off-by: Arvind Sankar Cc: Krzysztof Mazur Cc: Chris Metcalf Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/main.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'init/main.c') diff --git a/init/main.c b/init/main.c index 424d88fef08e..51fced4ca87a 100644 --- a/init/main.c +++ b/init/main.c @@ -246,8 +246,7 @@ static int __init loglevel(char *str) early_param("loglevel", loglevel); /* Change NUL term back to "=", to make "param" the whole string. */ -static int __init repair_env_string(char *param, char *val, - const char *unused, void *arg) +static void __init repair_env_string(char *param, char *val) { if (val) { /* param=val or param="val"? */ @@ -260,7 +259,6 @@ static int __init repair_env_string(char *param, char *val, } else BUG(); } - return 0; } /* Anything after -- gets handed straight to init. */ @@ -272,7 +270,7 @@ static int __init set_init_arg(char *param, char *val, if (panic_later) return 0; - repair_env_string(param, val, unused, NULL); + repair_env_string(param, val); for (i = 0; argv_init[i]; i++) { if (i == MAX_INIT_ARGS) { @@ -292,7 +290,7 @@ static int __init set_init_arg(char *param, char *val, static int __init unknown_bootoption(char *param, char *val, const char *unused, void *arg) { - repair_env_string(param, val, unused, NULL); + repair_env_string(param, val); /* Handle obsolete-style parameters */ if (obsolete_checksetup(param)) @@ -991,6 +989,12 @@ static const char *initcall_level_names[] __initdata = { "late", }; +static int __init ignore_unknown_bootoption(char *param, char *val, + const char *unused, void *arg) +{ + return 0; +} + static void __init do_initcall_level(int level) { initcall_entry_t *fn; @@ -1000,7 +1004,7 @@ static void __init do_initcall_level(int level) initcall_command_line, __start___param, __stop___param - __start___param, level, level, - NULL, &repair_env_string); + NULL, ignore_unknown_bootoption); trace_initcall_level(initcall_level_names[level]); for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) -- cgit v1.2.3 From 283900e82847e10898650c66a249c10b213934fb Mon Sep 17 00:00:00 2001 From: Arvind Sankar Date: Thu, 30 Jan 2020 22:17:19 -0800 Subject: init/main.c: fix quoted value handling in unknown_bootoption Patch series "init/main.c: minor cleanup/bugfix of envvar handling", v2. unknown_bootoption passes unrecognized command line arguments to init as either environment variables or arguments. Some of the logic in the function is broken for quoted command line arguments. When an argument of the form param="value" is processed by parse_args and passed to unknown_bootoption, the command line has param\0"value\0 with val pointing to the beginning of value. The helper function repair_env_string is then used to restore the '=' character that was removed by parse_args, and strip the quotes off fully. This results in param=value\0\0 and val ends up pointing to the 'a' instead of the 'v' in value. This bug was introduced when repair_env_string was refactored into a separate function, and the decrement of val in repair_env_string became dead code. This causes two problems in unknown_bootoption in the two places where the val pointer is used as a substitute for the length of param: 1. An argument of the form param=".value" is misinterpreted as a potential module parameter, with the result that it will not be placed in init's environment. 2. An argument of the form param="value" is checked to see if param is an existing environment variable that should be overwritten, but the comparison is off-by-one and compares 'param=v' instead of 'param=' against the existing environment. So passing, for example, TERM="vt100" on the command line results in init being passed both TERM=linux and TERM=vt100 in its environment. Patch 1 adds logging for the arguments and environment passed to init and is independent of the rest: it can be dropped if this is unnecessarily verbose. Patch 2 removes repair_env_string from initcall parameter parsing in do_initcall_level, as that uses a separate copy of the command line now and the repairing is no longer necessary. Patch 3 fixes the bug in unknown_bootoption by recording the length of param explicitly instead of implying it from val-param. This patch (of 3): Commit a99cd1125189 ("init: fix bug where environment vars can't be passed via boot args") introduced two minor bugs in unknown_bootoption by factoring out the quoted value handling into a separate function. When value is quoted, repair_env_string will move the value up 1 byte to strip the quotes, so val in unknown_bootoption no longer points to the actual location of the value. The result is that an argument of the form param=".value" is mistakenly treated as a potential module parameter and is not placed in init's environment, and an argument of the form param="value" can result in a duplicate environment variable: eg TERM="vt100" on the command line will result in both TERM=linux and TERM=vt100 being placed into init's environment. Fix this by recording the length of the param before calling repair_env_string instead of relying on val. Link: http://lkml.kernel.org/r/20191212180023.24339-4-nivedita@alum.mit.edu Signed-off-by: Arvind Sankar Cc: Chris Metcalf Cc: Krzysztof Mazur Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'init/main.c') diff --git a/init/main.c b/init/main.c index 51fced4ca87a..75eded9aafb0 100644 --- a/init/main.c +++ b/init/main.c @@ -255,7 +255,6 @@ static void __init repair_env_string(char *param, char *val) else if (val == param+strlen(param)+2) { val[-2] = '='; memmove(val-1, val, strlen(val)+1); - val--; } else BUG(); } @@ -290,6 +289,8 @@ static int __init set_init_arg(char *param, char *val, static int __init unknown_bootoption(char *param, char *val, const char *unused, void *arg) { + size_t len = strlen(param); + repair_env_string(param, val); /* Handle obsolete-style parameters */ @@ -297,7 +298,7 @@ static int __init unknown_bootoption(char *param, char *val, return 0; /* Unused module parameter. */ - if (strchr(param, '.') && (!val || strchr(param, '.') < val)) + if (strnchr(param, len, '.')) return 0; if (panic_later) @@ -311,7 +312,7 @@ static int __init unknown_bootoption(char *param, char *val, panic_later = "env"; panic_param = param; } - if (!strncmp(param, envp_init[i], val - param)) + if (!strncmp(param, envp_init[i], len+1)) break; } envp_init[i] = param; -- cgit v1.2.3 From f596ded1a044517afc4e9325f0dea449858450ac Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Thu, 30 Jan 2020 22:17:23 -0800 Subject: init/main.c: fix misleading "This architecture does not have kernel memory protection" message This message leads to thinking that memory protection is not implemented for the said architecture, whereas absence of CONFIG_STRICT_KERNEL_RWX only means that memory protection has not been selected at compile time. Don't print this message when CONFIG_ARCH_HAS_STRICT_KERNEL_RWX is selected by the architecture. Instead, print "Kernel memory protection not selected by kernel config." Link: http://lkml.kernel.org/r/62477e446d9685459d4f27d193af6ff1bd69d55f.1578557581.git.christophe.leroy@c-s.fr Signed-off-by: Christophe Leroy Acked-by: Kees Cook Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/main.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'init/main.c') diff --git a/init/main.c b/init/main.c index 75eded9aafb0..d8c7e86c2d28 100644 --- a/init/main.c +++ b/init/main.c @@ -1104,6 +1104,11 @@ static void mark_readonly(void) } else pr_info("Kernel memory protection disabled.\n"); } +#elif defined(CONFIG_ARCH_HAS_STRICT_KERNEL_RWX) +static inline void mark_readonly(void) +{ + pr_warn("Kernel memory protection not selected by kernel config.\n"); +} #else static inline void mark_readonly(void) { -- cgit v1.2.3