diff options
-rw-r--r-- | arch/x86/include/asm/pgtable.h | 2 | ||||
-rw-r--r-- | arch/x86/mm/debug_pagetables.c | 71 | ||||
-rw-r--r-- | arch/x86/mm/dump_pagetables.c | 6 |
3 files changed, 73 insertions, 6 deletions
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 03780d5c41c5..6b43d677f8ca 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h | |||
@@ -28,7 +28,7 @@ extern pgd_t early_top_pgt[PTRS_PER_PGD]; | |||
28 | int __init __early_make_pgtable(unsigned long address, pmdval_t pmd); | 28 | int __init __early_make_pgtable(unsigned long address, pmdval_t pmd); |
29 | 29 | ||
30 | void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd); | 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 | void ptdump_walk_pgd_level_debugfs(struct seq_file *m, pgd_t *pgd, bool user); |
32 | void ptdump_walk_pgd_level_checkwx(void); | 32 | void ptdump_walk_pgd_level_checkwx(void); |
33 | 33 | ||
34 | #ifdef CONFIG_DEBUG_WX | 34 | #ifdef CONFIG_DEBUG_WX |
diff --git a/arch/x86/mm/debug_pagetables.c b/arch/x86/mm/debug_pagetables.c index 8e70c1599e51..421f2664ffa0 100644 --- a/arch/x86/mm/debug_pagetables.c +++ b/arch/x86/mm/debug_pagetables.c | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | static int ptdump_show(struct seq_file *m, void *v) | 6 | static int ptdump_show(struct seq_file *m, void *v) |
7 | { | 7 | { |
8 | ptdump_walk_pgd_level_debugfs(m, NULL); | 8 | ptdump_walk_pgd_level_debugfs(m, NULL, false); |
9 | return 0; | 9 | return 0; |
10 | } | 10 | } |
11 | 11 | ||
@@ -22,7 +22,57 @@ static const struct file_operations ptdump_fops = { | |||
22 | .release = single_release, | 22 | .release = single_release, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | static struct dentry *dir, *pe; | 25 | static int ptdump_show_curknl(struct seq_file *m, void *v) |
26 | { | ||
27 | if (current->mm->pgd) { | ||
28 | down_read(¤t->mm->mmap_sem); | ||
29 | ptdump_walk_pgd_level_debugfs(m, current->mm->pgd, false); | ||
30 | up_read(¤t->mm->mmap_sem); | ||
31 | } | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static int ptdump_open_curknl(struct inode *inode, struct file *filp) | ||
36 | { | ||
37 | return single_open(filp, ptdump_show_curknl, NULL); | ||
38 | } | ||
39 | |||
40 | static const struct file_operations ptdump_curknl_fops = { | ||
41 | .owner = THIS_MODULE, | ||
42 | .open = ptdump_open_curknl, | ||
43 | .read = seq_read, | ||
44 | .llseek = seq_lseek, | ||
45 | .release = single_release, | ||
46 | }; | ||
47 | |||
48 | #ifdef CONFIG_PAGE_TABLE_ISOLATION | ||
49 | static struct dentry *pe_curusr; | ||
50 | |||
51 | static int ptdump_show_curusr(struct seq_file *m, void *v) | ||
52 | { | ||
53 | if (current->mm->pgd) { | ||
54 | down_read(¤t->mm->mmap_sem); | ||
55 | ptdump_walk_pgd_level_debugfs(m, current->mm->pgd, true); | ||
56 | up_read(¤t->mm->mmap_sem); | ||
57 | } | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static int ptdump_open_curusr(struct inode *inode, struct file *filp) | ||
62 | { | ||
63 | return single_open(filp, ptdump_show_curusr, NULL); | ||
64 | } | ||
65 | |||
66 | static const struct file_operations ptdump_curusr_fops = { | ||
67 | .owner = THIS_MODULE, | ||
68 | .open = ptdump_open_curusr, | ||
69 | .read = seq_read, | ||
70 | .llseek = seq_lseek, | ||
71 | .release = single_release, | ||
72 | }; | ||
73 | #endif | ||
74 | |||
75 | static struct dentry *dir, *pe_knl, *pe_curknl; | ||
26 | 76 | ||
27 | static int __init pt_dump_debug_init(void) | 77 | static int __init pt_dump_debug_init(void) |
28 | { | 78 | { |
@@ -30,9 +80,22 @@ static int __init pt_dump_debug_init(void) | |||
30 | if (!dir) | 80 | if (!dir) |
31 | return -ENOMEM; | 81 | return -ENOMEM; |
32 | 82 | ||
33 | pe = debugfs_create_file("kernel", 0400, dir, NULL, &ptdump_fops); | 83 | pe_knl = debugfs_create_file("kernel", 0400, dir, NULL, |
34 | if (!pe) | 84 | &ptdump_fops); |
85 | if (!pe_knl) | ||
86 | goto err; | ||
87 | |||
88 | pe_curknl = debugfs_create_file("current_kernel", 0400, | ||
89 | dir, NULL, &ptdump_curknl_fops); | ||
90 | if (!pe_curknl) | ||
91 | goto err; | ||
92 | |||
93 | #ifdef CONFIG_PAGE_TABLE_ISOLATION | ||
94 | pe_curusr = debugfs_create_file("current_user", 0400, | ||
95 | dir, NULL, &ptdump_curusr_fops); | ||
96 | if (!pe_curusr) | ||
35 | goto err; | 97 | goto err; |
98 | #endif | ||
36 | return 0; | 99 | return 0; |
37 | err: | 100 | err: |
38 | debugfs_remove_recursive(dir); | 101 | debugfs_remove_recursive(dir); |
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c index 17f5b417f95e..f56902c1f04b 100644 --- a/arch/x86/mm/dump_pagetables.c +++ b/arch/x86/mm/dump_pagetables.c | |||
@@ -530,8 +530,12 @@ void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd) | |||
530 | ptdump_walk_pgd_level_core(m, pgd, false, true); | 530 | ptdump_walk_pgd_level_core(m, pgd, false, true); |
531 | } | 531 | } |
532 | 532 | ||
533 | void ptdump_walk_pgd_level_debugfs(struct seq_file *m, pgd_t *pgd) | 533 | void ptdump_walk_pgd_level_debugfs(struct seq_file *m, pgd_t *pgd, bool user) |
534 | { | 534 | { |
535 | #ifdef CONFIG_PAGE_TABLE_ISOLATION | ||
536 | if (user && static_cpu_has(X86_FEATURE_PTI)) | ||
537 | pgd = kernel_to_user_pgdp(pgd); | ||
538 | #endif | ||
535 | ptdump_walk_pgd_level_core(m, pgd, false, false); | 539 | ptdump_walk_pgd_level_core(m, pgd, false, false); |
536 | } | 540 | } |
537 | EXPORT_SYMBOL_GPL(ptdump_walk_pgd_level_debugfs); | 541 | EXPORT_SYMBOL_GPL(ptdump_walk_pgd_level_debugfs); |