Commit acfa60db authored by Will Deacon's avatar Will Deacon Committed by Catalin Marinas
Browse files

arm64: mm: Fix "rodata=on" when CONFIG_RODATA_FULL_DEFAULT_ENABLED=y



When CONFIG_RODATA_FULL_DEFAULT_ENABLED=y, passing "rodata=on" on the
kernel command-line (rather than "rodata=full") should turn off the
"full" behaviour, leaving writable linear aliases of read-only kernel
memory. Unfortunately, the option has no effect in this situation and
the only way to disable the "rodata=full" behaviour is to disable rodata
protection entirely by passing "rodata=off".

Fix this by parsing the "on" and "off" options in the arch code,
additionally enforcing that 'rodata_full' cannot be set without also
setting 'rodata_enabled', allowing us to simplify a couple of checks
in the process.

Fixes: 2e8cff0a ("arm64: fix rodata=full")
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: default avatarWill Deacon <will@kernel.org>
Reviewed-by: default avatar"Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Reviewed-by: default avatarArd Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20231117131422.29663-1-will@kernel.org


Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent b85ea95d
Loading
Loading
Loading
Loading
+15 −2
Original line number Diff line number Diff line
@@ -21,9 +21,22 @@ static inline bool arch_parse_debug_rodata(char *arg)
	extern bool rodata_enabled;
	extern bool rodata_full;

	if (arg && !strcmp(arg, "full")) {
	if (!arg)
		return false;

	if (!strcmp(arg, "full")) {
		rodata_enabled = rodata_full = true;
		return true;
	}

	if (!strcmp(arg, "off")) {
		rodata_enabled = rodata_full = false;
		return true;
	}

	if (!strcmp(arg, "on")) {
		rodata_enabled = true;
		rodata_full = true;
		rodata_full = false;
		return true;
	}

+3 −4
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ bool can_set_direct_map(void)
	 *
	 * KFENCE pool requires page-granular mapping if initialized late.
	 */
	return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() ||
	return rodata_full || debug_pagealloc_enabled() ||
	       arm64_kfence_can_set_direct_map();
}

@@ -105,8 +105,7 @@ static int change_memory_common(unsigned long addr, int numpages,
	 * If we are manipulating read-only permissions, apply the same
	 * change to the linear mapping of the pages that back this VM area.
	 */
	if (rodata_enabled &&
	    rodata_full && (pgprot_val(set_mask) == PTE_RDONLY ||
	if (rodata_full && (pgprot_val(set_mask) == PTE_RDONLY ||
			    pgprot_val(clear_mask) == PTE_RDONLY)) {
		for (i = 0; i < area->nr_pages; i++) {
			__change_memory_common((u64)page_address(area->pages[i]),