Revert "arm64: mm: add support for WXN memory translation attribute"
authorCatalin Marinas <catalin.marinas@arm.com>
Tue, 12 Mar 2024 20:00:20 +0000 (20:00 +0000)
committerCatalin Marinas <catalin.marinas@arm.com>
Wed, 13 Mar 2024 10:53:20 +0000 (10:53 +0000)
This reverts commit 50e3ed0f93f4f62ed2aa83de5db6cb84ecdd5707.

The SCTLR_EL1.WXN control forces execute-never when a page has write
permissions. While the idea of hardening such write/exec combinations is
good, with permissions indirection enabled (FEAT_PIE) this control
becomes RES0. FEAT_PIE introduces a slightly different form of WXN which
only has an effect when the base permission is RWX and the write is
toggled by the permission overlay (FEAT_POE, not yet supported by the
arm64 kernel). Revert the patch for now.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/r/ZfGESD3a91lxH367@arm.com
arch/arm64/Kconfig
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/mman.h
arch/arm64/include/asm/mmu_context.h
arch/arm64/kernel/pi/idreg-override.c
arch/arm64/kernel/pi/map_kernel.c
arch/arm64/mm/proc.S

index 24dfd87fab9332237cb9f2262676a3e2cdd54c27..4869265ace2dddc24281865fb89afdb539b8509c 100644 (file)
@@ -1606,17 +1606,6 @@ config RODATA_FULL_DEFAULT_ENABLED
          This requires the linear region to be mapped down to pages,
          which may adversely affect performance in some cases.
 
-config ARM64_WXN
-       bool "Enable WXN attribute so all writable mappings are non-exec"
-       help
-         Set the WXN bit in the SCTLR system register so that all writable
-         mappings are treated as if the PXN/UXN bit is set as well.
-         If this is set to Y, it can still be disabled at runtime by
-         passing 'arm64.nowxn' on the kernel command line.
-
-         This should only be set if no software needs to be supported that
-         relies on being able to execute from writable mappings.
-
 config ARM64_SW_TTBR0_PAN
        bool "Emulate Privileged Access Never using TTBR0_EL1 switching"
        help
index 66ba0801f7b7129a4ed44e4b43a29f581e32da74..6d86ad37c6159760b233e0741d24e04dce32984c 100644 (file)
@@ -18,7 +18,6 @@
 #define ARM64_SW_FEATURE_OVERRIDE_NOKASLR      0
 #define ARM64_SW_FEATURE_OVERRIDE_HVHE         4
 #define ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF   8
-#define ARM64_SW_FEATURE_OVERRIDE_NOWXN                12
 
 #ifndef __ASSEMBLY__
 
@@ -968,13 +967,6 @@ static inline bool kaslr_disabled_cmdline(void)
        return arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOKASLR);
 }
 
-static inline bool arm64_wxn_enabled(void)
-{
-       if (!IS_ENABLED(CONFIG_ARM64_WXN))
-               return false;
-       return !arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOWXN);
-}
-
 u32 get_kvm_ipa_limit(void);
 void dump_cpu_features(void);
 
index 6d4940342ba73060309c355eec8c09fd5c96d7ef..5966ee4a61542edfa6ec513619adde639cead9b8 100644 (file)
@@ -35,40 +35,11 @@ static inline unsigned long arch_calc_vm_flag_bits(unsigned long flags)
 }
 #define arch_calc_vm_flag_bits(flags) arch_calc_vm_flag_bits(flags)
 
-static inline bool arm64_check_wx_prot(unsigned long prot,
-                                      struct task_struct *tsk)
-{
-       /*
-        * When we are running with SCTLR_ELx.WXN==1, writable mappings are
-        * implicitly non-executable. This means we should reject such mappings
-        * when user space attempts to create them using mmap() or mprotect().
-        */
-       if (arm64_wxn_enabled() &&
-           ((prot & (PROT_WRITE | PROT_EXEC)) == (PROT_WRITE | PROT_EXEC))) {
-               /*
-                * User space libraries such as libffi carry elaborate
-                * heuristics to decide whether it is worth it to even attempt
-                * to create writable executable mappings, as PaX or selinux
-                * enabled systems will outright reject it. They will usually
-                * fall back to something else (e.g., two separate shared
-                * mmap()s of a temporary file) on failure.
-                */
-               pr_info_ratelimited(
-                       "process %s (%d) attempted to create PROT_WRITE+PROT_EXEC mapping\n",
-                       tsk->comm, tsk->pid);
-               return false;
-       }
-       return true;
-}
-
 static inline bool arch_validate_prot(unsigned long prot,
        unsigned long addr __always_unused)
 {
        unsigned long supported = PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM;
 
-       if (!arm64_check_wx_prot(prot, current))
-               return false;
-
        if (system_supports_bti())
                supported |= PROT_BTI;
 
@@ -79,13 +50,6 @@ static inline bool arch_validate_prot(unsigned long prot,
 }
 #define arch_validate_prot(prot, addr) arch_validate_prot(prot, addr)
 
-static inline bool arch_validate_mmap_prot(unsigned long prot,
-                                          unsigned long addr)
-{
-       return arm64_check_wx_prot(prot, current);
-}
-#define arch_validate_mmap_prot arch_validate_mmap_prot
-
 static inline bool arch_validate_flags(unsigned long vm_flags)
 {
        if (!system_supports_mte())
index f0fe2d09d139cc0514041981951cacf0b92e99a6..c768d16b81a49e5a4718fb9fd7d3075028d92def 100644 (file)
 #include <asm/cpufeature.h>
 #include <asm/daifflags.h>
 #include <asm/proc-fns.h>
+#include <asm-generic/mm_hooks.h>
 #include <asm/cputype.h>
 #include <asm/sysreg.h>
 #include <asm/tlbflush.h>
 
 extern bool rodata_full;
 
-static inline int arch_dup_mmap(struct mm_struct *oldmm,
-                               struct mm_struct *mm)
-{
-       return 0;
-}
-
-static inline void arch_exit_mmap(struct mm_struct *mm)
-{
-}
-
-static inline void arch_unmap(struct mm_struct *mm,
-                       unsigned long start, unsigned long end)
-{
-}
-
-static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
-               bool write, bool execute, bool foreign)
-{
-       if (IS_ENABLED(CONFIG_ARM64_WXN) && execute &&
-           (vma->vm_flags & (VM_WRITE | VM_EXEC)) == (VM_WRITE | VM_EXEC)) {
-               pr_warn_ratelimited(
-                       "process %s (%d) attempted to execute from writable memory\n",
-                       current->comm, current->pid);
-               /* disallow unless the nowxn override is set */
-               return !arm64_wxn_enabled();
-       }
-       return true;
-}
-
 static inline void contextidr_thread_switch(struct task_struct *next)
 {
        if (!IS_ENABLED(CONFIG_PID_IN_CONTEXTIDR))
index bccfee34f62f9450f3a100754d84b82f63d83cfa..aad399796e812180aa4e8e244d30a97fb29950d9 100644 (file)
@@ -189,7 +189,6 @@ static const struct ftr_set_desc sw_features __prel64_initconst = {
                FIELD("nokaslr", ARM64_SW_FEATURE_OVERRIDE_NOKASLR, NULL),
                FIELD("hvhe", ARM64_SW_FEATURE_OVERRIDE_HVHE, hvhe_filter),
                FIELD("rodataoff", ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF, NULL),
-               FIELD("nowxn", ARM64_SW_FEATURE_OVERRIDE_NOWXN, NULL),
                {}
        },
 };
@@ -222,9 +221,8 @@ static const struct {
        { "arm64.nomops",               "id_aa64isar2.mops=0" },
        { "arm64.nomte",                "id_aa64pfr1.mte=0" },
        { "nokaslr",                    "arm64_sw.nokaslr=1" },
-       { "rodata=off",                 "arm64_sw.rodataoff=1 arm64_sw.nowxn=1" },
+       { "rodata=off",                 "arm64_sw.rodataoff=1" },
        { "arm64.nolva",                "id_aa64mmfr2.varange=0" },
-       { "arm64.nowxn",                "arm64_sw.nowxn=1" },
 };
 
 static int __init parse_hexdigit(const char *p, u64 *v)
index cac1e1f63c4400ba0c7cff8f43509f475effa795..5fa08e13e17e524aba5ee92061c1ad3ebc3bedcb 100644 (file)
@@ -132,25 +132,6 @@ static void __init map_kernel(u64 kaslr_offset, u64 va_offset, int root_level)
        idmap_cpu_replace_ttbr1(swapper_pg_dir);
 }
 
-static void noinline __section(".idmap.text") disable_wxn(void)
-{
-       u64 sctlr = read_sysreg(sctlr_el1) & ~SCTLR_ELx_WXN;
-
-       /*
-        * We cannot safely clear the WXN bit while the MMU and caches are on,
-        * so turn the MMU off, flush the TLBs and turn it on again but with
-        * the WXN bit cleared this time.
-        */
-       asm("   msr     sctlr_el1, %0           ;"
-           "   isb                             ;"
-           "   tlbi    vmalle1                 ;"
-           "   dsb     nsh                     ;"
-           "   isb                             ;"
-           "   msr     sctlr_el1, %1           ;"
-           "   isb                             ;"
-           ::  "r"(sctlr & ~SCTLR_ELx_M), "r"(sctlr));
-}
-
 static void noinline __section(".idmap.text") set_ttbr0_for_lpa2(u64 ttbr)
 {
        u64 sctlr = read_sysreg(sctlr_el1);
@@ -248,10 +229,6 @@ asmlinkage void __init early_map_kernel(u64 boot_status, void *fdt)
        if (va_bits > VA_BITS_MIN)
                sysreg_clear_set(tcr_el1, TCR_T1SZ_MASK, TCR_T1SZ(va_bits));
 
-       if (IS_ENABLED(CONFIG_ARM64_WXN) &&
-           arm64_test_sw_feature_override(ARM64_SW_FEATURE_OVERRIDE_NOWXN))
-               disable_wxn();
-
        /*
         * The virtual KASLR displacement modulo 2MiB is decided by the
         * physical placement of the image, as otherwise, we might not be able
index bfd2ad896108d1649a80b7e452a4b8dcf069634b..9d40f3ffd8d233ba6fec0044fca5e71d9d586cb1 100644 (file)
@@ -546,12 +546,6 @@ alternative_else_nop_endif
         * Prepare SCTLR
         */
        mov_q   x0, INIT_SCTLR_EL1_MMU_ON
-#ifdef CONFIG_ARM64_WXN
-       ldr_l   x1, arm64_sw_feature_override + FTR_OVR_VAL_OFFSET
-       tst     x1, #0xf << ARM64_SW_FEATURE_OVERRIDE_NOWXN
-       orr     x1, x0, #SCTLR_ELx_WXN
-       csel    x0, x0, x1, ne
-#endif
        ret                                     // return to head.S
 
        .unreq  mair