diff options
author | Dave Hansen <dave.hansen@intel.com> | 2017-11-06 17:29:51 -0800 |
---|---|---|
committer | Dave Hansen <dave.hansen@intel.com> | 2017-11-06 17:29:51 -0800 |
commit | ef4f9e8cd08df643cedbccf043489edfdf88bf71 (patch) | |
tree | eb9f79aaf07b06955856c131e11ad231424f4537 | |
parent | cd3420e4b5c472df96be1d4822f7c39a851f0968 (diff) | |
download | x86-kaiser-ef4f9e8cd08df643cedbccf043489edfdf88bf71.tar.gz |
x86, kaiser: allow NX to be set in p4d/pgd
From: Dave Hansen <dave.hansen@linux.intel.com>
We protect user portion of the kernel page tables with the NX
bit to cripple it. But, that trips the p4d/pgd_bad() checks.
Make sure it does not do that.
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Moritz Lipp <moritz.lipp@iaik.tugraz.at>
Cc: Daniel Gruss <daniel.gruss@iaik.tugraz.at>
Cc: Michael Schwarz <michael.schwarz@iaik.tugraz.at>
Cc: Richard Fellner <richard.fellner@student.tugraz.at>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Kees Cook <keescook@google.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: x86@kernel.org
-rw-r--r-- | arch/x86/include/asm/pgtable.h | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 5ce5a19f6cf7a9..c149fdfcd1ed7a 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -845,7 +845,12 @@ static inline pud_t *pud_offset(p4d_t *p4d, unsigned long address) static inline int p4d_bad(p4d_t p4d) { - return (p4d_flags(p4d) & ~(_KERNPG_TABLE | _PAGE_USER)) != 0; + unsigned long ignore_flags = _KERNPG_TABLE | _PAGE_USER; + + if (IS_ENABLED(CONFIG_KAISER)) + ignore_flags |= _PAGE_NX; + + return (p4d_flags(p4d) & ~ignore_flags) != 0; } #endif /* CONFIG_PGTABLE_LEVELS > 3 */ @@ -879,7 +884,12 @@ static inline p4d_t *p4d_offset(pgd_t *pgd, unsigned long address) static inline int pgd_bad(pgd_t pgd) { - return (pgd_flags(pgd) & ~_PAGE_USER) != _KERNPG_TABLE; + unsigned long ignore_flags = _PAGE_USER; + + if (IS_ENABLED(CONFIG_KAISER)) + ignore_flags |= _PAGE_NX; + + return (pgd_flags(pgd) & ~ignore_flags) != _KERNPG_TABLE; } static inline int pgd_none(pgd_t pgd) |