x86/mm/dump_pagetables: Check user space page table for WX pages

ptdump_walk_pgd_level_checkwx() checks the kernel page table for WX pages,
but does not check the PAGE_TABLE_ISOLATION user space page table.

Restructure the code so that dmesg output is selected by an explicit
argument and not implicit via checking the pgd argument for !NULL.

Add the check for the user space page table.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: David Laight <David.Laight@aculab.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Eduardo Valentin <eduval@amazon.com>
Cc: Greg KH <gregkh@linuxfoundation.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: aliguori@amazon.com
Cc: daniel.gruss@iaik.tugraz.at
Cc: hughd@google.com
Cc: keescook@google.com
Cc: linux-mm@kvack.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by Thomas Gleixner and committed by Ingo Molnar b4bf4f92 75298aa1

+27 -6
+1
arch/x86/include/asm/pgtable.h
··· 28 28 int __init __early_make_pgtable(unsigned long address, pmdval_t pmd); 29 29 30 30 void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd); 31 + void ptdump_walk_pgd_level_debugfs(struct seq_file *m, pgd_t *pgd); 31 32 void ptdump_walk_pgd_level_checkwx(void); 32 33 33 34 #ifdef CONFIG_DEBUG_WX
+1 -1
arch/x86/mm/debug_pagetables.c
··· 5 5 6 6 static int ptdump_show(struct seq_file *m, void *v) 7 7 { 8 - ptdump_walk_pgd_level(m, NULL); 8 + ptdump_walk_pgd_level_debugfs(m, NULL); 9 9 return 0; 10 10 } 11 11
+25 -5
arch/x86/mm/dump_pagetables.c
··· 476 476 } 477 477 478 478 static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd, 479 - bool checkwx) 479 + bool checkwx, bool dmesg) 480 480 { 481 481 #ifdef CONFIG_X86_64 482 482 pgd_t *start = (pgd_t *) &init_top_pgt; ··· 489 489 490 490 if (pgd) { 491 491 start = pgd; 492 - st.to_dmesg = true; 492 + st.to_dmesg = dmesg; 493 493 } 494 494 495 495 st.check_wx = checkwx; ··· 527 527 528 528 void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd) 529 529 { 530 - ptdump_walk_pgd_level_core(m, pgd, false); 530 + ptdump_walk_pgd_level_core(m, pgd, false, true); 531 531 } 532 - EXPORT_SYMBOL_GPL(ptdump_walk_pgd_level); 532 + 533 + void ptdump_walk_pgd_level_debugfs(struct seq_file *m, pgd_t *pgd) 534 + { 535 + ptdump_walk_pgd_level_core(m, pgd, false, false); 536 + } 537 + EXPORT_SYMBOL_GPL(ptdump_walk_pgd_level_debugfs); 538 + 539 + static void ptdump_walk_user_pgd_level_checkwx(void) 540 + { 541 + #ifdef CONFIG_PAGE_TABLE_ISOLATION 542 + pgd_t *pgd = (pgd_t *) &init_top_pgt; 543 + 544 + if (!static_cpu_has(X86_FEATURE_PTI)) 545 + return; 546 + 547 + pr_info("x86/mm: Checking user space page tables\n"); 548 + pgd = kernel_to_user_pgdp(pgd); 549 + ptdump_walk_pgd_level_core(NULL, pgd, true, false); 550 + #endif 551 + } 533 552 534 553 void ptdump_walk_pgd_level_checkwx(void) 535 554 { 536 - ptdump_walk_pgd_level_core(NULL, NULL, true); 555 + ptdump_walk_pgd_level_core(NULL, NULL, true, false); 556 + ptdump_walk_user_pgd_level_checkwx(); 537 557 } 538 558 539 559 static int __init pt_dump_init(void)