From: Dave Hansen <dave.han...@linux.intel.com> With PAGE_TABLE_ISOLATION the user portion of the kernel page tables is poisoned with the NX bit so if the entry code exits with the kernel page tables selected in CR3, userspace crashes.
But doing so trips the p4d/pgd_bad() checks. Make sure it does not do that. Signed-off-by: Dave Hansen <dave.han...@linux.intel.com> Signed-off-by: Ingo Molnar <mi...@kernel.org> Signed-off-by: Thomas Gleixner <t...@linutronix.de> Reviewed-by: Borislav Petkov <b...@suse.de> Cc: Andy Lutomirski <l...@kernel.org> Cc: Boris Ostrovsky <boris.ostrov...@oracle.com> Cc: Brian Gerst <brge...@gmail.com> Cc: David Laight <david.lai...@aculab.com> Cc: Denys Vlasenko <dvlas...@redhat.com> Cc: Eduardo Valentin <edu...@amazon.com> Cc: Greg KH <gre...@linuxfoundation.org> Cc: H. Peter Anvin <h...@zytor.com> Cc: Josh Poimboeuf <jpoim...@redhat.com> Cc: Juergen Gross <jgr...@suse.com> Cc: Linus Torvalds <torva...@linux-foundation.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Will Deacon <will.dea...@arm.com> Cc: aligu...@amazon.com Cc: daniel.gr...@iaik.tugraz.at Cc: hu...@google.com Cc: keesc...@google.com --- arch/x86/include/asm/pgtable.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -846,7 +846,12 @@ static inline pud_t *pud_offset(p4d_t *p 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_PAGE_TABLE_ISOLATION)) + ignore_flags |= _PAGE_NX; + + return (p4d_flags(p4d) & ~ignore_flags) != 0; } #endif /* CONFIG_PGTABLE_LEVELS > 3 */ @@ -880,7 +885,12 @@ static inline p4d_t *p4d_offset(pgd_t *p 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_PAGE_TABLE_ISOLATION)) + ignore_flags |= _PAGE_NX; + + return (pgd_flags(pgd) & ~ignore_flags) != _KERNPG_TABLE; } static inline int pgd_none(pgd_t pgd)