]> git.ipfire.org Git - people/ms/linux.git/commitdiff
arm64: fix rodata=full
authorMark Rutland <mark.rutland@arm.com>
Wed, 17 Aug 2022 15:40:22 +0000 (16:40 +0100)
committerWill Deacon <will@kernel.org>
Tue, 23 Aug 2022 10:02:02 +0000 (11:02 +0100)
On arm64, "rodata=full" has been suppored (but not documented) since
commit:

  c55191e96caa9d78 ("arm64: mm: apply r/o permissions of VM areas to its linear alias as well")

As it's necessary to determine the rodata configuration early during
boot, arm64 has an early_param() handler for this, whereas init/main.c
has a __setup() handler which is run later.

Unfortunately, this split meant that since commit:

  f9a40b0890658330 ("init/main.c: return 1 from handled __setup() functions")

... passing "rodata=full" would result in a spurious warning from the
__setup() handler (though RO permissions would be configured
appropriately).

Further, "rodata=full" has been broken since commit:

  0d6ea3ac94ca77c5 ("lib/kstrtox.c: add "false"/"true" support to kstrtobool()")

... which caused strtobool() to parse "full" as false (in addition to
many other values not documented for the "rodata=" kernel parameter.

This patch fixes this breakage by:

* Moving the core parameter parser to an __early_param(), such that it
  is available early.

* Adding an (optional) arch hook which arm64 can use to parse "full".

* Updating the documentation to mention that "full" is valid for arm64.

* Having the core parameter parser handle "on" and "off" explicitly,
  such that any undocumented values (e.g. typos such as "ful") are
  reported as errors rather than being silently accepted.

Note that __setup() and early_param() have opposite conventions for
their return values, where __setup() uses 1 to indicate a parameter was
handled and early_param() uses 0 to indicate a parameter was handled.

Fixes: f9a40b089065 ("init/main.c: return 1 from handled __setup() functions")
Fixes: 0d6ea3ac94ca ("lib/kstrtox.c: add "false"/"true" support to kstrtobool()")
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Jagdish Gediya <jvgediya@linux.ibm.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20220817154022.3974645-1-mark.rutland@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
Documentation/admin-guide/kernel-parameters.txt
arch/arm64/include/asm/setup.h
arch/arm64/mm/mmu.c
init/main.c

index d7f30902fda02fe09ea9eaa6563065b1655b0c2c..426fa892d311a308e38131edf21de630db0654aa 100644 (file)
        rodata=         [KNL]
                on      Mark read-only kernel memory as read-only (default).
                off     Leave read-only kernel memory writable for debugging.
+               full    Mark read-only kernel memory and aliases as read-only
+                       [arm64]
 
        rockchip.usb_uart
                        Enable the uart passthrough on the designated usb port
index 6437df661700920473aa9ccb1f217985436f856c..f4af547ef54caa70a521387d442ffeb6d04a230b 100644 (file)
@@ -3,6 +3,8 @@
 #ifndef __ARM64_ASM_SETUP_H
 #define __ARM64_ASM_SETUP_H
 
+#include <linux/string.h>
+
 #include <uapi/asm/setup.h>
 
 void *get_early_fdt_ptr(void);
@@ -14,4 +16,19 @@ void early_fdt_map(u64 dt_phys);
 extern phys_addr_t __fdt_pointer __initdata;
 extern u64 __cacheline_aligned boot_args[4];
 
+static inline bool arch_parse_debug_rodata(char *arg)
+{
+       extern bool rodata_enabled;
+       extern bool rodata_full;
+
+       if (arg && !strcmp(arg, "full")) {
+               rodata_enabled = true;
+               rodata_full = true;
+               return true;
+       }
+
+       return false;
+}
+#define arch_parse_debug_rodata arch_parse_debug_rodata
+
 #endif
index db7c4e6ae57bbe02774748c9e050d246486b4f9f..e7ad44585f40abab6293dc4ffbfd08775f1e53ac 100644 (file)
@@ -642,24 +642,6 @@ static void __init map_kernel_segment(pgd_t *pgdp, void *va_start, void *va_end,
        vm_area_add_early(vma);
 }
 
-static int __init parse_rodata(char *arg)
-{
-       int ret = strtobool(arg, &rodata_enabled);
-       if (!ret) {
-               rodata_full = false;
-               return 0;
-       }
-
-       /* permit 'full' in addition to boolean options */
-       if (strcmp(arg, "full"))
-               return -EINVAL;
-
-       rodata_enabled = true;
-       rodata_full = true;
-       return 0;
-}
-early_param("rodata", parse_rodata);
-
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 static int __init map_entry_trampoline(void)
 {
index 91642a4e69be62b139fd77b6f7d7791d249b54fe..1fe7942f5d4a8775e0934e9c8b6b6c73ec726ad2 100644 (file)
@@ -1446,13 +1446,25 @@ static noinline void __init kernel_init_freeable(void);
 
 #if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_STRICT_MODULE_RWX)
 bool rodata_enabled __ro_after_init = true;
+
+#ifndef arch_parse_debug_rodata
+static inline bool arch_parse_debug_rodata(char *str) { return false; }
+#endif
+
 static int __init set_debug_rodata(char *str)
 {
-       if (strtobool(str, &rodata_enabled))
+       if (arch_parse_debug_rodata(str))
+               return 0;
+
+       if (str && !strcmp(str, "on"))
+               rodata_enabled = true;
+       else if (str && !strcmp(str, "off"))
+               rodata_enabled = false;
+       else
                pr_warn("Invalid option string for rodata: '%s'\n", str);
-       return 1;
+       return 0;
 }
-__setup("rodata=", set_debug_rodata);
+early_param("rodata", set_debug_rodata);
 #endif
 
 #ifdef CONFIG_STRICT_KERNEL_RWX