[PATCH RFC v2 bootconfig 2/3] fs/proc: Add /proc/cmdline_load for boot loader arguments

Paul E. McKenney
2023-07-31T23:31:48Z

In kernels built with CONFIG_BOOT_CONFIG_FORCE=y, /proc/cmdline will
show all kernel boot parameters, both those supplied by the boot loader
and those embedded in the kernel image. This works well for those who
just want to see all of the kernel boot parameters, but is not helpful to
those who need to see only those parameters supplied by the boot loader.
This is especially important when these parameters are presented to the
boot loader by automation that might gather them from diverse sources.
It is also useful when booting the next kernel via kexec(), in which
case it is necessary to supply only those kernel command-line arguments
from the boot loader, and most definitely not those that were embedded
into the current kernel.

Therefore, provide a /proc/cmdline_load file that shows only those kernel
boot parameters supplied by the boot loader.

Why put this in /proc? Because it is quite similar to /proc/cmdline, so
it makes sense to put it in the same place that /proc/cmdline is located.

[ sfr: Apply kernel test robot feedback. ]
[ paulmck: Apply Randy Dunlap feedback. ]

Co-developed-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Co-developed-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: <linux-fsdevel@vger.kernel.org>
---
Documentation/filesystems/proc.rst | 1 +
fs/proc/cmdline.c | 13 +++++++++++++
include/linux/init.h | 3 ++-
init/main.c | 2 +-
4 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst
index 75a8c899ebcc..c2aee55248a8 100644
--- a/Documentation/filesystems/proc.rst
+++ b/Documentation/filesystems/proc.rst
@@ -688,6 +688,7 @@ files are there, and which are missing.
bus Directory containing bus specific information
cmdline Kernel command line, both from bootloader and embedded
in the kernel image.
+ cmdline_load Kernel command line obtained from kernel image (6.6)
cpuinfo Info about the CPU
devices Available devices (block and character)
dma Used DMS channels
diff --git a/fs/proc/cmdline.c b/fs/proc/cmdline.c
index a6f76121955f..1d0ef9d2949d 100644
--- a/fs/proc/cmdline.c
+++ b/fs/proc/cmdline.c
@@ -3,6 +3,7 @@
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <asm/setup.h>
#include "internal.h"

static int cmdline_proc_show(struct seq_file *m, void *v)
@@ -12,6 +13,13 @@ static int cmdline_proc_show(struct seq_file *m, void *v)
return 0;
}

+static int cmdline_load_proc_show(struct seq_file *m, void *v)
+{
+ seq_puts(m, boot_command_line);
+ seq_putc(m, '\n');
+ return 0;
+}
+
static int __init proc_cmdline_init(void)
{
struct proc_dir_entry *pde;
@@ -19,6 +27,11 @@ static int __init proc_cmdline_init(void)
pde = proc_create_single("cmdline", 0, NULL, cmdline_proc_show);
pde_make_permanent(pde);
pde->size = saved_command_line_len + 1;
+ if (IS_ENABLED(CONFIG_BOOT_CONFIG_FORCE)) {
+ pde = proc_create_single("cmdline_load", 0, NULL, cmdline_load_proc_show);
+ pde_make_permanent(pde);
+ pde->size = strnlen(boot_command_line, COMMAND_LINE_SIZE) + 1;
+ }
return 0;
}
fs_initcall(proc_cmdline_init);
diff --git a/include/linux/init.h b/include/linux/init.h
index 266c3e1640d4..29e75bbe7984 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -112,6 +112,7 @@
#define __REFCONST .section ".ref.rodata", "a"

#ifndef __ASSEMBLY__
+
/*
* Used for initialization calls..
*/
@@ -143,7 +144,7 @@ struct file_system_type;

/* Defined in init/main.c */
extern int do_one_initcall(initcall_t fn);
-extern char __initdata boot_command_line[];
+extern char boot_command_line[];
extern char *saved_command_line;
extern unsigned int saved_command_line_len;
extern unsigned int reset_devices;
diff --git a/init/main.c b/init/main.c
index ad920fac325c..2121685c479a 100644
--- a/init/main.c
+++ b/init/main.c
@@ -135,7 +135,7 @@ EXPORT_SYMBOL(system_state);
void (*__initdata late_time_init)(void);

/* Untouched command line saved by arch-specific code. */
-char __initdata boot_command_line[COMMAND_LINE_SIZE];
+char boot_command_line[COMMAND_LINE_SIZE] __ro_after_init;
/* Untouched saved command line (eg. for /proc) */
char *saved_command_line __ro_after_init;
unsigned int saved_command_line_len __ro_after_init;
--
2.40.1