Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: fix rodata=full

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>

authored by

Mark Rutland and committed by
Will Deacon
2e8cff0a 729a9165

+34 -21
+2
Documentation/admin-guide/kernel-parameters.txt
··· 5331 5331 rodata= [KNL] 5332 5332 on Mark read-only kernel memory as read-only (default). 5333 5333 off Leave read-only kernel memory writable for debugging. 5334 + full Mark read-only kernel memory and aliases as read-only 5335 + [arm64] 5334 5336 5335 5337 rockchip.usb_uart 5336 5338 Enable the uart passthrough on the designated usb port
+17
arch/arm64/include/asm/setup.h
··· 3 3 #ifndef __ARM64_ASM_SETUP_H 4 4 #define __ARM64_ASM_SETUP_H 5 5 6 + #include <linux/string.h> 7 + 6 8 #include <uapi/asm/setup.h> 7 9 8 10 void *get_early_fdt_ptr(void); ··· 15 13 */ 16 14 extern phys_addr_t __fdt_pointer __initdata; 17 15 extern u64 __cacheline_aligned boot_args[4]; 16 + 17 + static inline bool arch_parse_debug_rodata(char *arg) 18 + { 19 + extern bool rodata_enabled; 20 + extern bool rodata_full; 21 + 22 + if (arg && !strcmp(arg, "full")) { 23 + rodata_enabled = true; 24 + rodata_full = true; 25 + return true; 26 + } 27 + 28 + return false; 29 + } 30 + #define arch_parse_debug_rodata arch_parse_debug_rodata 18 31 19 32 #endif
-18
arch/arm64/mm/mmu.c
··· 642 642 vm_area_add_early(vma); 643 643 } 644 644 645 - static int __init parse_rodata(char *arg) 646 - { 647 - int ret = strtobool(arg, &rodata_enabled); 648 - if (!ret) { 649 - rodata_full = false; 650 - return 0; 651 - } 652 - 653 - /* permit 'full' in addition to boolean options */ 654 - if (strcmp(arg, "full")) 655 - return -EINVAL; 656 - 657 - rodata_enabled = true; 658 - rodata_full = true; 659 - return 0; 660 - } 661 - early_param("rodata", parse_rodata); 662 - 663 645 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 664 646 static int __init map_entry_trampoline(void) 665 647 {
+15 -3
init/main.c
··· 1446 1446 1447 1447 #if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_STRICT_MODULE_RWX) 1448 1448 bool rodata_enabled __ro_after_init = true; 1449 + 1450 + #ifndef arch_parse_debug_rodata 1451 + static inline bool arch_parse_debug_rodata(char *str) { return false; } 1452 + #endif 1453 + 1449 1454 static int __init set_debug_rodata(char *str) 1450 1455 { 1451 - if (strtobool(str, &rodata_enabled)) 1456 + if (arch_parse_debug_rodata(str)) 1457 + return 0; 1458 + 1459 + if (str && !strcmp(str, "on")) 1460 + rodata_enabled = true; 1461 + else if (str && !strcmp(str, "off")) 1462 + rodata_enabled = false; 1463 + else 1452 1464 pr_warn("Invalid option string for rodata: '%s'\n", str); 1453 - return 1; 1465 + return 0; 1454 1466 } 1455 - __setup("rodata=", set_debug_rodata); 1467 + early_param("rodata", set_debug_rodata); 1456 1468 #endif 1457 1469 1458 1470 #ifdef CONFIG_STRICT_KERNEL_RWX