Commit 6e2edd63 authored by Catalin Marinas's avatar Catalin Marinas
Browse files

arm64: Ensure execute-only permissions are not allowed without EPAN



Commit 18107f8a ("arm64: Support execute-only permissions with
Enhanced PAN") re-introduced execute-only permissions when EPAN is
available. When EPAN is not available, arch_filter_pgprot() is supposed
to change a PAGE_EXECONLY permission into PAGE_READONLY_EXEC. However,
if BTI or MTE are present, such check does not detect the execute-only
pgprot in the presence of PTE_GP (BTI) or MT_NORMAL_TAGGED (MTE),
allowing the user to request PROT_EXEC with PROT_BTI or PROT_MTE.

Remove the arch_filter_pgprot() function, change the default VM_EXEC
permissions to PAGE_READONLY_EXEC and update the protection_map[] array
at core_initcall() if EPAN is detected.

Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Fixes: 18107f8a ("arm64: Support execute-only permissions with Enhanced PAN")
Cc: <stable@vger.kernel.org> # 5.13.x
Acked-by: default avatarWill Deacon <will@kernel.org>
Reviewed-by: default avatarVladimir Murzin <vladimir.murzin@arm.com>
Tested-by: default avatarVladimir Murzin <vladimir.murzin@arm.com>
parent 4f6de676
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -1236,9 +1236,6 @@ config HW_PERF_EVENTS
	def_bool y
	depends on ARM_PMU

config ARCH_HAS_FILTER_PGPROT
	def_bool y

# Supported by clang >= 7.0
config CC_HAVE_SHADOW_CALL_STACK
	def_bool $(cc-option, -fsanitize=shadow-call-stack -ffixed-x18)
+2 −2
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ extern bool arm64_use_ng_mappings;
#define __P001  PAGE_READONLY
#define __P010  PAGE_READONLY
#define __P011  PAGE_READONLY
#define __P100  PAGE_EXECONLY
#define __P100  PAGE_READONLY_EXEC	/* PAGE_EXECONLY if Enhanced PAN */
#define __P101  PAGE_READONLY_EXEC
#define __P110  PAGE_READONLY_EXEC
#define __P111  PAGE_READONLY_EXEC
@@ -101,7 +101,7 @@ extern bool arm64_use_ng_mappings;
#define __S001  PAGE_READONLY
#define __S010  PAGE_SHARED
#define __S011  PAGE_SHARED
#define __S100  PAGE_EXECONLY
#define __S100  PAGE_READONLY_EXEC	/* PAGE_EXECONLY if Enhanced PAN */
#define __S101  PAGE_READONLY_EXEC
#define __S110  PAGE_SHARED_EXEC
#define __S111  PAGE_SHARED_EXEC
+0 −11
Original line number Diff line number Diff line
@@ -1017,17 +1017,6 @@ static inline bool arch_wants_old_prefaulted_pte(void)
}
#define arch_wants_old_prefaulted_pte	arch_wants_old_prefaulted_pte

static inline pgprot_t arch_filter_pgprot(pgprot_t prot)
{
	if (cpus_have_const_cap(ARM64_HAS_EPAN))
		return prot;

	if (pgprot_val(prot) != pgprot_val(PAGE_EXECONLY))
		return prot;

	return PAGE_READONLY_EXEC;
}

static inline bool pud_sect_supported(void)
{
	return PAGE_SIZE == SZ_4K;
+17 −0
Original line number Diff line number Diff line
@@ -7,8 +7,10 @@

#include <linux/io.h>
#include <linux/memblock.h>
#include <linux/mm.h>
#include <linux/types.h>

#include <asm/cpufeature.h>
#include <asm/page.h>

/*
@@ -38,3 +40,18 @@ int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
{
	return !(((pfn << PAGE_SHIFT) + size) & ~PHYS_MASK);
}

static int __init adjust_protection_map(void)
{
	/*
	 * With Enhanced PAN we can honour the execute-only permissions as
	 * there is no PAN override with such mappings.
	 */
	if (cpus_have_const_cap(ARM64_HAS_EPAN)) {
		protection_map[VM_EXEC] = PAGE_EXECONLY;
		protection_map[VM_EXEC | VM_SHARED] = PAGE_EXECONLY;
	}

	return 0;
}
arch_initcall(adjust_protection_map);