diff mbox series

[v6,08/22] bootconfig: init: Allow admin to use bootconfig for init command line

Message ID 157867229521.17873.654222294326542349.stgit@devnote2 (mailing list archive)
State New, archived
Headers show
Series tracing: bootconfig: Boot-time tracing and Extra boot config | expand

Commit Message

Masami Hiramatsu (Google) Jan. 10, 2020, 4:04 p.m. UTC
Since the current kernel command line is too short to describe
long and many options for init (e.g. systemd command line options),
this allows admin to use boot config for init command line.

All init command line under "init." keywords will be passed to
init.

For example,

init.systemd {
	unified_cgroup_hierarchy = 1
	debug_shell
	default_timeout_start_sec = 60
}

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 init/main.c |   31 ++++++++++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

Comments

Kees Cook Feb. 7, 2020, 6:03 p.m. UTC | #1
On Sat, Jan 11, 2020 at 01:04:55AM +0900, Masami Hiramatsu wrote:
> Since the current kernel command line is too short to describe
> long and many options for init (e.g. systemd command line options),
> this allows admin to use boot config for init command line.
> 
> All init command line under "init." keywords will be passed to
> init.
> 
> For example,
> 
> init.systemd {
> 	unified_cgroup_hierarchy = 1
> 	debug_shell
> 	default_timeout_start_sec = 60
> }
> 
> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
> ---
>  init/main.c |   31 ++++++++++++++++++++++++++++---
>  1 file changed, 28 insertions(+), 3 deletions(-)
> 
> diff --git a/init/main.c b/init/main.c
> index c0017d9d16e7..dd7da62d99a5 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -139,6 +139,8 @@ char *saved_command_line;
>  static char *static_command_line;
>  /* Untouched extra command line */
>  static char *extra_command_line;
> +/* Extra init arguments */
> +static char *extra_init_args;
>  
>  static char *execute_command;
>  static char *ramdisk_execute_command;
> @@ -372,6 +374,8 @@ static void __init setup_boot_config(void)
>  		pr_info("Load boot config: %d bytes\n", size);
>  		/* keys starting with "kernel." are passed via cmdline */
>  		extra_command_line = xbc_make_cmdline("kernel");
> +		/* Also, "init." keys are init arguments */
> +		extra_init_args = xbc_make_cmdline("init");
>  	}
>  }
>  #else
> @@ -507,16 +511,18 @@ static inline void smp_prepare_cpus(unsigned int maxcpus) { }
>   */
>  static void __init setup_command_line(char *command_line)
>  {
> -	size_t len, xlen = 0;
> +	size_t len, xlen = 0, ilen = 0;
>  
>  	if (extra_command_line)
>  		xlen = strlen(extra_command_line);
> +	if (extra_init_args)
> +		ilen = strlen(extra_init_args) + 4; /* for " -- " */
>  
>  	len = xlen + strlen(boot_command_line) + 1;
>  
> -	saved_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
> +	saved_command_line = memblock_alloc(len + ilen, SMP_CACHE_BYTES);
>  	if (!saved_command_line)
> -		panic("%s: Failed to allocate %zu bytes\n", __func__, len);
> +		panic("%s: Failed to allocate %zu bytes\n", __func__, len + ilen);
>  
>  	static_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
>  	if (!static_command_line)
> @@ -533,6 +539,22 @@ static void __init setup_command_line(char *command_line)
>  	}
>  	strcpy(saved_command_line + xlen, boot_command_line);
>  	strcpy(static_command_line + xlen, command_line);
> +
> +	if (ilen) {
> +		/*
> +		 * Append supplemental init boot args to saved_command_line
> +		 * so that user can check what command line options passed
> +		 * to init.
> +		 */
> +		len = strlen(saved_command_line);
> +		if (!strstr(boot_command_line, " -- ")) {
> +			strcpy(saved_command_line + len, " -- ");
> +			len += 4;
> +		} else
> +			saved_command_line[len++] = ' ';
> +
> +		strcpy(saved_command_line + len, extra_init_args);
> +	}

This isn't safe because it will destroy any argument with " -- " in
quotes and anything after it. For example, booting with:

thing=on acpi_osi="! -- " other=setting

will wreck acpi_osi's value and potentially overwrite "other=settings",
etc.

(Yes, this seems very unlikely, but you can't treat " -- " as special,
the command line string must be correct parsed for double quotes, as
parse_args() does.)

>  }
>  
>  /*
> @@ -759,6 +781,9 @@ asmlinkage __visible void __init start_kernel(void)
>  	if (!IS_ERR_OR_NULL(after_dashes))
>  		parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
>  			   NULL, set_init_arg);
> +	if (extra_init_args)
> +		parse_args("Setting extra init args", extra_init_args,
> +			   NULL, 0, -1, -1, NULL, set_init_arg);

Here is where you can append the extra_init_args, since parse_args()
will have done the work to find after_dashes correctly.

-Kees

>  
>  	/*
>  	 * These use large bootmem allocations and must precede
>
Arvind Sankar Feb. 7, 2020, 7:31 p.m. UTC | #2
On Fri, Feb 07, 2020 at 10:03:16AM -0800, Kees Cook wrote:
> > +
> > +	if (ilen) {
> > +		/*
> > +		 * Append supplemental init boot args to saved_command_line
> > +		 * so that user can check what command line options passed
> > +		 * to init.
> > +		 */
> > +		len = strlen(saved_command_line);
> > +		if (!strstr(boot_command_line, " -- ")) {
> > +			strcpy(saved_command_line + len, " -- ");
> > +			len += 4;
> > +		} else
> > +			saved_command_line[len++] = ' ';
> > +
> > +		strcpy(saved_command_line + len, extra_init_args);
> > +	}
> 
> This isn't safe because it will destroy any argument with " -- " in
> quotes and anything after it. For example, booting with:
> 
> thing=on acpi_osi="! -- " other=setting
> 
> will wreck acpi_osi's value and potentially overwrite "other=settings",
> etc.
> 
> (Yes, this seems very unlikely, but you can't treat " -- " as special,
> the command line string must be correct parsed for double quotes, as
> parse_args() does.)
> 

I think it won't overwrite anything, it will just leave out the " -- "
that should have been added?

I wonder if this is necessary, though -- since commit b88c50ac304a ("log
arguments and environment passed to init") the init arguments will be in
the kernel log anyway.
Steven Rostedt Feb. 7, 2020, 7:46 p.m. UTC | #3
On Fri, 7 Feb 2020 10:03:16 -0800
Kees Cook <keescook@chromium.org> wrote:

> >  static void __init setup_command_line(char *command_line)
> >  {
> > -	size_t len, xlen = 0;
> > +	size_t len, xlen = 0, ilen = 0;
> >  
> >  	if (extra_command_line)
> >  		xlen = strlen(extra_command_line);
> > +	if (extra_init_args)
> > +		ilen = strlen(extra_init_args) + 4; /* for " -- " */
> >  
> >  	len = xlen + strlen(boot_command_line) + 1;
> >  
> > -	saved_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
> > +	saved_command_line = memblock_alloc(len + ilen, SMP_CACHE_BYTES);
> >  	if (!saved_command_line)
> > -		panic("%s: Failed to allocate %zu bytes\n", __func__, len);
> > +		panic("%s: Failed to allocate %zu bytes\n", __func__, len + ilen);
> >  
> >  	static_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
> >  	if (!static_command_line)
> > @@ -533,6 +539,22 @@ static void __init setup_command_line(char *command_line)
> >  	}
> >  	strcpy(saved_command_line + xlen, boot_command_line);
> >  	strcpy(static_command_line + xlen, command_line);
> > +
> > +	if (ilen) {
> > +		/*
> > +		 * Append supplemental init boot args to saved_command_line
> > +		 * so that user can check what command line options passed
> > +		 * to init.
> > +		 */
> > +		len = strlen(saved_command_line);
> > +		if (!strstr(boot_command_line, " -- ")) {
> > +			strcpy(saved_command_line + len, " -- ");
> > +			len += 4;
> > +		} else
> > +			saved_command_line[len++] = ' ';
> > +
> > +		strcpy(saved_command_line + len, extra_init_args);
> > +	}  
> 
> This isn't safe because it will destroy any argument with " -- " in
> quotes and anything after it. For example, booting with:
> 
> thing=on acpi_osi="! -- " other=setting
> 
> will wreck acpi_osi's value and potentially overwrite "other=settings",
> etc.
> 
> (Yes, this seems very unlikely, but you can't treat " -- " as special,
> the command line string must be correct parsed for double quotes, as
> parse_args() does.)
> 

This is not the args you are looking for. ;-)

There is a slight bug, but not as bad as you may think it is.
bootconfig (when added to the command line) will look for a json like
file appended to the initrd, and it will parse that. That's what all the
xbc_*() functions do (extended boot commandline). If one of the options
in that json like file is "init", then it will create the
extra_init_args, which will make ilen greater than zero.

The above if statement looks for that ' -- ', and if it doesn't find it
(strcmp() returns NULL when not found) it will than append " -- " to
the boot_command_line. If it is found, then the " -- " is not added. In
either case, the init args found in the json like file in the initrd is
appended to the saved_command_line.

I did say there's a slight bug here. If you have your condition, and
you add init arguments to that json file, it wont properly add the " --
", and the init arguments in that file will be ignored.

That should be fixed, and I think I was able to do that below. I also
noticed that we don't properly look for "bootconfig" either.

-- Steve




> >  }
> >  
> >  /*
> > @@ -759,6 +781,9 @@ asmlinkage __visible void __init start_kernel(void)
> >  	if (!IS_ERR_OR_NULL(after_dashes))
> >  		parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
> >  			   NULL, set_init_arg);
> > +	if (extra_init_args)
> > +		parse_args("Setting extra init args", extra_init_args,
> > +			   NULL, 0, -1, -1, NULL, set_init_arg);  

diff --git a/init/main.c b/init/main.c
index 491f1cdb3105..113c8244e5f0 100644
--- a/init/main.c
+++ b/init/main.c
@@ -142,6 +142,15 @@ static char *extra_command_line;
 /* Extra init arguments */
 static char *extra_init_args;
 
+#ifdef CONFIG_BOOT_CONFIG
+/* Is bootconfig on command line? */
+static bool bootconfig_found;
+static bool initargs_found;
+#else
+# define bootconfig_found false
+# define initargs_found false
+#endif
+
 static char *execute_command;
 static char *ramdisk_execute_command;
 
@@ -336,17 +345,32 @@ u32 boot_config_checksum(unsigned char *p, u32 size)
 	return ret;
 }
 
+static int __init bootconfig_params(char *param, char *val,
+				    const char *unused, void *arg)
+{
+	if (strcmp(param, "bootconfig") == 0) {
+		bootconfig_found = true;
+	} else if (strcmp(param, "--") == 0) {
+		initargs_found = true;
+	}
+	return 0;
+}
+
 static void __init setup_boot_config(const char *cmdline)
 {
+	static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata;
 	u32 size, csum;
 	char *data, *copy;
 	const char *p;
 	u32 *hdr;
 	int ret;
 
-	p = strstr(cmdline, "bootconfig");
-	if (!p || (p != cmdline && !isspace(*(p-1))) ||
-	    (p[10] && !isspace(p[10])))
+	/* All fall through to do_early_param. */
+	strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+	parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
+		   bootconfig_params);
+
+	if (!bootconfig_found)
 		return;
 
 	if (!initrd_end)
@@ -563,11 +587,12 @@ static void __init setup_command_line(char *command_line)
 		 * to init.
 		 */
 		len = strlen(saved_command_line);
-		if (!strstr(boot_command_line, " -- ")) {
+		if (initargs_found) {
+			saved_command_line[len++] = ' ';
+		} else {
 			strcpy(saved_command_line + len, " -- ");
 			len += 4;
-		} else
-			saved_command_line[len++] = ' ';
+		}
 
 		strcpy(saved_command_line + len, extra_init_args);
 	}
Kees Cook Feb. 8, 2020, 12:44 a.m. UTC | #4
On Fri, Feb 07, 2020 at 02:46:03PM -0500, Steven Rostedt wrote:
> On Fri, 7 Feb 2020 10:03:16 -0800
> Kees Cook <keescook@chromium.org> wrote:
> > > +		len = strlen(saved_command_line);
> > > +		if (!strstr(boot_command_line, " -- ")) {
> > > +			strcpy(saved_command_line + len, " -- ");
> > > +			len += 4;
> > > +		} else
> > > +			saved_command_line[len++] = ' ';
> > > +
> > > +		strcpy(saved_command_line + len, extra_init_args);
> > > +	}  
> > 
> > This isn't safe because it will destroy any argument with " -- " in
> > quotes and anything after it. For example, booting with:
> > 
> > thing=on acpi_osi="! -- " other=setting
> > 
> > will wreck acpi_osi's value and potentially overwrite "other=settings",
> > etc.
> > 
> > (Yes, this seems very unlikely, but you can't treat " -- " as special,
> > the command line string must be correct parsed for double quotes, as
> > parse_args() does.)
> > 
> 
> This is not the args you are looking for. ;-)
> 
> There is a slight bug, but not as bad as you may think it is.
> bootconfig (when added to the command line) will look for a json like
> file appended to the initrd, and it will parse that. That's what all the
> xbc_*() functions do (extended boot commandline). If one of the options
> in that json like file is "init", then it will create the
> extra_init_args, which will make ilen greater than zero.
> 
> The above if statement looks for that ' -- ', and if it doesn't find it
> (strcmp() returns NULL when not found) it will than append " -- " to
> the boot_command_line. If it is found, then the " -- " is not added. In
> either case, the init args found in the json like file in the initrd is
> appended to the saved_command_line.
> 
> I did say there's a slight bug here. If you have your condition, and
> you add init arguments to that json file, it wont properly add the " --
> ", and the init arguments in that file will be ignored.

Ah, right, it's even more slight, sorry, I had the strstr() in my head
still. So, yes, with an "init" section and a very goofy " -- " present
in a kernel bootparam string value, the appended init args will be
parsed as kernel options.
Arvind Sankar Aug. 2, 2020, 2:33 a.m. UTC | #5
On Fri, Feb 07, 2020 at 02:46:03PM -0500, Steven Rostedt wrote:
> 
> diff --git a/init/main.c b/init/main.c
> index 491f1cdb3105..113c8244e5f0 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -142,6 +142,15 @@ static char *extra_command_line;
>  /* Extra init arguments */
>  static char *extra_init_args;
>  
> +#ifdef CONFIG_BOOT_CONFIG
> +/* Is bootconfig on command line? */
> +static bool bootconfig_found;
> +static bool initargs_found;
> +#else
> +# define bootconfig_found false
> +# define initargs_found false
> +#endif
> +
>  static char *execute_command;
>  static char *ramdisk_execute_command;
>  
> @@ -336,17 +345,32 @@ u32 boot_config_checksum(unsigned char *p, u32 size)
>  	return ret;
>  }
>  
> +static int __init bootconfig_params(char *param, char *val,
> +				    const char *unused, void *arg)
> +{
> +	if (strcmp(param, "bootconfig") == 0) {
> +		bootconfig_found = true;
> +	} else if (strcmp(param, "--") == 0) {
> +		initargs_found = true;
> +	}
> +	return 0;
> +}
> +

I came across this as I was poking around some of the command line
parsing. AFAICT, initargs_found will never be set to true here, because
parse_args handles "--" itself by immediately returning: it doesn't
invoke the callback for it. So you'd instead have to check the return of
parse_args("bootconfig"...) to detect the initargs_found case.

>  static void __init setup_boot_config(const char *cmdline)
>  {
> +	static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata;
>  	u32 size, csum;
>  	char *data, *copy;
>  	const char *p;
>  	u32 *hdr;
>  	int ret;
>  
> -	p = strstr(cmdline, "bootconfig");
> -	if (!p || (p != cmdline && !isspace(*(p-1))) ||
> -	    (p[10] && !isspace(p[10])))
> +	/* All fall through to do_early_param. */
> +	strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
> +	parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
> +		   bootconfig_params);
> +
> +	if (!bootconfig_found)
>  		return;
Masami Hiramatsu (Google) Aug. 3, 2020, 3:03 p.m. UTC | #6
On Sat, 1 Aug 2020 22:33:18 -0400
Arvind Sankar <nivedita@alum.mit.edu> wrote:

> On Fri, Feb 07, 2020 at 02:46:03PM -0500, Steven Rostedt wrote:
> > 
> > diff --git a/init/main.c b/init/main.c
> > index 491f1cdb3105..113c8244e5f0 100644
> > --- a/init/main.c
> > +++ b/init/main.c
> > @@ -142,6 +142,15 @@ static char *extra_command_line;
> >  /* Extra init arguments */
> >  static char *extra_init_args;
> >  
> > +#ifdef CONFIG_BOOT_CONFIG
> > +/* Is bootconfig on command line? */
> > +static bool bootconfig_found;
> > +static bool initargs_found;
> > +#else
> > +# define bootconfig_found false
> > +# define initargs_found false
> > +#endif
> > +
> >  static char *execute_command;
> >  static char *ramdisk_execute_command;
> >  
> > @@ -336,17 +345,32 @@ u32 boot_config_checksum(unsigned char *p, u32 size)
> >  	return ret;
> >  }
> >  
> > +static int __init bootconfig_params(char *param, char *val,
> > +				    const char *unused, void *arg)
> > +{
> > +	if (strcmp(param, "bootconfig") == 0) {
> > +		bootconfig_found = true;
> > +	} else if (strcmp(param, "--") == 0) {
> > +		initargs_found = true;
> > +	}
> > +	return 0;
> > +}
> > +
> 
> I came across this as I was poking around some of the command line
> parsing. AFAICT, initargs_found will never be set to true here, because
> parse_args handles "--" itself by immediately returning: it doesn't
> invoke the callback for it. So you'd instead have to check the return of
> parse_args("bootconfig"...) to detect the initargs_found case.

Oops, good catch!
Does this fixes the problem?

From b078e8b02ad54aea74f8c3645fc11dd3a1cdc1e7 Mon Sep 17 00:00:00 2001
From: Masami Hiramatsu <mhiramat@kernel.org>
Date: Mon, 3 Aug 2020 23:57:29 +0900
Subject: [PATCH] bootconfig: Fix to find the initargs correctly

Since the parse_args() stops parsing at '--', bootconfig_params()
will never get the '--' as param and initargs_found never be true.
In the result, if we pass some init arguments via the bootconfig,
those are always appended to the kernel command line with '--'
and user will see double '--'.

To fix this correctly, check the return value of parse_args()
and set initargs_found true if the return value is not an error
but a valid address.

Fixes: f61872bb58a1 ("bootconfig: Use parse_args() to find bootconfig and '--'")
Cc: stable@vger.kernel.org
Reported-by: Arvind Sankar <nivedita@alum.mit.edu>
Suggested-by: Arvind Sankar <nivedita@alum.mit.edu>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 init/main.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/init/main.c b/init/main.c
index 0ead83e86b5a..627f9230dbe8 100644
--- a/init/main.c
+++ b/init/main.c
@@ -387,8 +387,6 @@ static int __init bootconfig_params(char *param, char *val,
 {
 	if (strcmp(param, "bootconfig") == 0) {
 		bootconfig_found = true;
-	} else if (strcmp(param, "--") == 0) {
-		initargs_found = true;
 	}
 	return 0;
 }
@@ -399,19 +397,23 @@ static void __init setup_boot_config(const char *cmdline)
 	const char *msg;
 	int pos;
 	u32 size, csum;
-	char *data, *copy;
+	char *data, *copy, *err;
 	int ret;
 
 	/* Cut out the bootconfig data even if we have no bootconfig option */
 	data = get_boot_config_from_initrd(&size, &csum);
 
 	strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
-	parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
-		   bootconfig_params);
+	err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
+			 bootconfig_params);
 
-	if (!bootconfig_found)
+	if (IS_ERR(err) || !bootconfig_found)
 		return;
 
+	/* parse_args() stops at '--' and returns an address */
+	if (!IS_ERR(err) && err)
+		initargs_found = true;
+
 	if (!data) {
 		pr_err("'bootconfig' found on command line, but no bootconfig found\n");
 		return;
Arvind Sankar Aug. 3, 2020, 3:29 p.m. UTC | #7
On Tue, Aug 04, 2020 at 12:03:45AM +0900, Masami Hiramatsu wrote:
> On Sat, 1 Aug 2020 22:33:18 -0400
> Arvind Sankar <nivedita@alum.mit.edu> wrote:
> > 
> > I came across this as I was poking around some of the command line
> > parsing. AFAICT, initargs_found will never be set to true here, because
> > parse_args handles "--" itself by immediately returning: it doesn't
> > invoke the callback for it. So you'd instead have to check the return of
> > parse_args("bootconfig"...) to detect the initargs_found case.
> 
> Oops, good catch!
> Does this fixes the problem?

Note I found the issue by code inspection, I don't have an actual test
case. But the change looks good to me, with one comment below.

> 
>  	strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
> -	parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
> -		   bootconfig_params);
> +	err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
> +			 bootconfig_params);
>  
> -	if (!bootconfig_found)
> +	if (IS_ERR(err) || !bootconfig_found)
>  		return;
>  
> +	/* parse_args() stops at '--' and returns an address */
> +	if (!IS_ERR(err) && err)
> +		initargs_found = true;
> +

I think you can drop the second IS_ERR, since we already checked that.

>  	if (!data) {
>  		pr_err("'bootconfig' found on command line, but no bootconfig found\n");
>  		return;
> -- 
> 2.25.1
Steven Rostedt Aug. 3, 2020, 5:22 p.m. UTC | #8
On Mon, 3 Aug 2020 11:29:59 -0400
Arvind Sankar <nivedita@alum.mit.edu> wrote:

> > +	/* parse_args() stops at '--' and returns an address */
> > +	if (!IS_ERR(err) && err)
> > +		initargs_found = true;
> > +  
> 
> I think you can drop the second IS_ERR, since we already checked that.

Masami,

Can you send this with the update as a normal patch (not a Cc to this
thread). That way it gets caught by my patchwork scanning of my inbox.

Thanks!

(/me is currently going through all his patchwork patches to pull in
for the merge window.)

-- Steve
Masami Hiramatsu (Google) Aug. 4, 2020, 12:29 a.m. UTC | #9
On Mon, 3 Aug 2020 13:22:38 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:

> On Mon, 3 Aug 2020 11:29:59 -0400
> Arvind Sankar <nivedita@alum.mit.edu> wrote:
> 
> > > +	/* parse_args() stops at '--' and returns an address */
> > > +	if (!IS_ERR(err) && err)
> > > +		initargs_found = true;
> > > +  
> > 
> > I think you can drop the second IS_ERR, since we already checked that.
> 
> Masami,
> 
> Can you send this with the update as a normal patch (not a Cc to this
> thread). That way it gets caught by my patchwork scanning of my inbox.

OK, I'll update it.

> 
> Thanks!
> 
> (/me is currently going through all his patchwork patches to pull in
> for the merge window.)

Thank you!

> 
> -- Steve
diff mbox series

Patch

diff --git a/init/main.c b/init/main.c
index c0017d9d16e7..dd7da62d99a5 100644
--- a/init/main.c
+++ b/init/main.c
@@ -139,6 +139,8 @@  char *saved_command_line;
 static char *static_command_line;
 /* Untouched extra command line */
 static char *extra_command_line;
+/* Extra init arguments */
+static char *extra_init_args;
 
 static char *execute_command;
 static char *ramdisk_execute_command;
@@ -372,6 +374,8 @@  static void __init setup_boot_config(void)
 		pr_info("Load boot config: %d bytes\n", size);
 		/* keys starting with "kernel." are passed via cmdline */
 		extra_command_line = xbc_make_cmdline("kernel");
+		/* Also, "init." keys are init arguments */
+		extra_init_args = xbc_make_cmdline("init");
 	}
 }
 #else
@@ -507,16 +511,18 @@  static inline void smp_prepare_cpus(unsigned int maxcpus) { }
  */
 static void __init setup_command_line(char *command_line)
 {
-	size_t len, xlen = 0;
+	size_t len, xlen = 0, ilen = 0;
 
 	if (extra_command_line)
 		xlen = strlen(extra_command_line);
+	if (extra_init_args)
+		ilen = strlen(extra_init_args) + 4; /* for " -- " */
 
 	len = xlen + strlen(boot_command_line) + 1;
 
-	saved_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
+	saved_command_line = memblock_alloc(len + ilen, SMP_CACHE_BYTES);
 	if (!saved_command_line)
-		panic("%s: Failed to allocate %zu bytes\n", __func__, len);
+		panic("%s: Failed to allocate %zu bytes\n", __func__, len + ilen);
 
 	static_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
 	if (!static_command_line)
@@ -533,6 +539,22 @@  static void __init setup_command_line(char *command_line)
 	}
 	strcpy(saved_command_line + xlen, boot_command_line);
 	strcpy(static_command_line + xlen, command_line);
+
+	if (ilen) {
+		/*
+		 * Append supplemental init boot args to saved_command_line
+		 * so that user can check what command line options passed
+		 * to init.
+		 */
+		len = strlen(saved_command_line);
+		if (!strstr(boot_command_line, " -- ")) {
+			strcpy(saved_command_line + len, " -- ");
+			len += 4;
+		} else
+			saved_command_line[len++] = ' ';
+
+		strcpy(saved_command_line + len, extra_init_args);
+	}
 }
 
 /*
@@ -759,6 +781,9 @@  asmlinkage __visible void __init start_kernel(void)
 	if (!IS_ERR_OR_NULL(after_dashes))
 		parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
 			   NULL, set_init_arg);
+	if (extra_init_args)
+		parse_args("Setting extra init args", extra_init_args,
+			   NULL, 0, -1, -1, NULL, set_init_arg);
 
 	/*
 	 * These use large bootmem allocations and must precede