2022-10-04 18:27:50

by tip-bot2 for Haifeng Xu

[permalink] [raw]
Subject: [tip: x86/mm] x86/mm: Ease W^X enforcement back to just a warning

The following commit has been merged into the x86/mm branch of tip:

Commit-ID: e9935b87c46236e8d7dd0acb847a31952db25228
Gitweb: https://git.kernel.org/tip/e9935b87c46236e8d7dd0acb847a31952db25228
Author: Dave Hansen <[email protected]>
AuthorDate: Mon, 03 Oct 2022 13:23:46 -07:00
Committer: Dave Hansen <[email protected]>
CommitterDate: Tue, 04 Oct 2022 11:00:24 -07:00

x86/mm: Ease W^X enforcement back to just a warning

Currently, the "change_page_attr" (CPA) code refuses to create
W+X mappings on 64-bit kernels. There have been reports both
from 32-bit[1] and from BPF[2] users where this change kept the
system from booting.

These reports are showing up even after about a month of soak
time in -next.

To avoid breaking anything, never enforce W^X. Always warn
and return the requested permissions even if a problem is
detected.

1. https://lore.kernel.org/all/CAMj1kXHcF_iK_g0OZSkSv56Wmr=eQGQwNstcNjLEfS=mm7a06w@mail.gmail.com/
2. https://lore.kernel.org/bpf/[email protected]/T/#u

Signed-off-by: Dave Hansen <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: [email protected]
Cc: "H. Peter Anvin" <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: Peter Zijlstra <[email protected]>
---
arch/x86/mm/pat/set_memory.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index efe882c..97342c4 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -580,7 +580,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long start,
}

/*
- * Validate and enforce strict W^X semantics.
+ * Validate strict W^X semantics.
*/
static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long start,
unsigned long pfn, unsigned long npg)
@@ -595,7 +595,7 @@ static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long star
if (IS_ENABLED(CONFIG_X86_32))
return new;

- /* Only enforce when NX is supported: */
+ /* Only verify when NX is supported: */
if (!(__supported_pte_mask & _PAGE_NX))
return new;

@@ -606,13 +606,17 @@ static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long star
return new;

end = start + npg * PAGE_SIZE - 1;
- WARN_ONCE(1, "CPA refuse W^X violation: %016llx -> %016llx range: 0x%016lx - 0x%016lx PFN %lx\n",
+ WARN_ONCE(1, "CPA detected W^X violation: %016llx -> %016llx range: 0x%016lx - 0x%016lx PFN %lx\n",
(unsigned long long)pgprot_val(old),
(unsigned long long)pgprot_val(new),
start, end, pfn);

- /* refuse the transition into WX */
- return old;
+ /*
+ * For now, allow all permission change attempts by returning the
+ * attempted permissions. This can 'return old' to actively
+ * refuse the permission change at a later time.
+ */
+ return new;
}

/*