1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2019 SiFive 4 */ 5 6 #include <linux/efi.h> 7 #include <linux/init.h> 8 #include <linux/debugfs.h> 9 #include <linux/seq_file.h> 10 #include <linux/ptdump.h> 11 12 #include <asm/ptdump.h> 13 #include <linux/pgtable.h> 14 #include <asm/kasan.h> 15 16 #define pt_dump_seq_printf(m, fmt, args...) \ 17 ({ \ 18 if (m) \ 19 seq_printf(m, fmt, ##args); \ 20 }) 21 22 #define pt_dump_seq_puts(m, fmt) \ 23 ({ \ 24 if (m) \ 25 seq_printf(m, fmt); \ 26 }) 27 28 /* 29 * The page dumper groups page table entries of the same type into a single 30 * description. It uses pg_state to track the range information while 31 * iterating over the pte entries. When the continuity is broken it then 32 * dumps out a description of the range. 33 */ 34 struct pg_state { 35 struct ptdump_state ptdump; 36 struct seq_file *seq; 37 const struct addr_marker *marker; 38 unsigned long start_address; 39 unsigned long start_pa; 40 unsigned long last_pa; 41 int level; 42 u64 current_prot; 43 bool check_wx; 44 unsigned long wx_pages; 45 }; 46 47 /* Address marker */ 48 struct addr_marker { 49 unsigned long start_address; 50 const char *name; 51 }; 52 53 /* Private information for debugfs */ 54 struct ptd_mm_info { 55 struct mm_struct *mm; 56 const struct addr_marker *markers; 57 unsigned long base_addr; 58 unsigned long end; 59 }; 60 61 enum address_markers_idx { 62 FIXMAP_START_NR, 63 FIXMAP_END_NR, 64 PCI_IO_START_NR, 65 PCI_IO_END_NR, 66 #ifdef CONFIG_SPARSEMEM_VMEMMAP 67 VMEMMAP_START_NR, 68 VMEMMAP_END_NR, 69 #endif 70 VMALLOC_START_NR, 71 VMALLOC_END_NR, 72 PAGE_OFFSET_NR, 73 #ifdef CONFIG_KASAN 74 KASAN_SHADOW_START_NR, 75 KASAN_SHADOW_END_NR, 76 #endif 77 #ifdef CONFIG_64BIT 78 MODULES_MAPPING_NR, 79 KERNEL_MAPPING_NR, 80 #endif 81 END_OF_SPACE_NR 82 }; 83 84 static struct addr_marker address_markers[] = { 85 {0, "Fixmap start"}, 86 {0, "Fixmap end"}, 87 {0, "PCI I/O start"}, 88 {0, "PCI I/O end"}, 89 #ifdef CONFIG_SPARSEMEM_VMEMMAP 90 {0, "vmemmap start"}, 91 {0, "vmemmap end"}, 92 #endif 93 {0, "vmalloc() area"}, 94 {0, "vmalloc() end"}, 95 {0, "Linear mapping"}, 96 #ifdef CONFIG_KASAN 97 {0, "Kasan shadow start"}, 98 {0, "Kasan shadow end"}, 99 #endif 100 #ifdef CONFIG_64BIT 101 {0, "Modules/BPF mapping"}, 102 {0, "Kernel mapping"}, 103 #endif 104 {-1, NULL}, 105 }; 106 107 static struct ptd_mm_info kernel_ptd_info = { 108 .mm = &init_mm, 109 .markers = address_markers, 110 .base_addr = 0, 111 .end = ULONG_MAX, 112 }; 113 114 #ifdef CONFIG_EFI 115 static struct addr_marker efi_addr_markers[] = { 116 { 0, "UEFI runtime start" }, 117 { SZ_1G, "UEFI runtime end" }, 118 { -1, NULL } 119 }; 120 121 static struct ptd_mm_info efi_ptd_info = { 122 .mm = &efi_mm, 123 .markers = efi_addr_markers, 124 .base_addr = 0, 125 .end = SZ_2G, 126 }; 127 #endif 128 129 /* Page Table Entry */ 130 struct prot_bits { 131 u64 mask; 132 u64 val; 133 const char *set; 134 const char *clear; 135 }; 136 137 static const struct prot_bits pte_bits[] = { 138 { 139 .mask = _PAGE_SOFT, 140 .val = _PAGE_SOFT, 141 .set = "RSW", 142 .clear = " ", 143 }, { 144 .mask = _PAGE_DIRTY, 145 .val = _PAGE_DIRTY, 146 .set = "D", 147 .clear = ".", 148 }, { 149 .mask = _PAGE_ACCESSED, 150 .val = _PAGE_ACCESSED, 151 .set = "A", 152 .clear = ".", 153 }, { 154 .mask = _PAGE_GLOBAL, 155 .val = _PAGE_GLOBAL, 156 .set = "G", 157 .clear = ".", 158 }, { 159 .mask = _PAGE_USER, 160 .val = _PAGE_USER, 161 .set = "U", 162 .clear = ".", 163 }, { 164 .mask = _PAGE_EXEC, 165 .val = _PAGE_EXEC, 166 .set = "X", 167 .clear = ".", 168 }, { 169 .mask = _PAGE_WRITE, 170 .val = _PAGE_WRITE, 171 .set = "W", 172 .clear = ".", 173 }, { 174 .mask = _PAGE_READ, 175 .val = _PAGE_READ, 176 .set = "R", 177 .clear = ".", 178 }, { 179 .mask = _PAGE_PRESENT, 180 .val = _PAGE_PRESENT, 181 .set = "V", 182 .clear = ".", 183 } 184 }; 185 186 /* Page Level */ 187 struct pg_level { 188 const char *name; 189 u64 mask; 190 }; 191 192 static struct pg_level pg_level[] = { 193 { /* pgd */ 194 .name = "PGD", 195 }, { /* p4d */ 196 .name = (CONFIG_PGTABLE_LEVELS > 4) ? "P4D" : "PGD", 197 }, { /* pud */ 198 .name = (CONFIG_PGTABLE_LEVELS > 3) ? "PUD" : "PGD", 199 }, { /* pmd */ 200 .name = (CONFIG_PGTABLE_LEVELS > 2) ? "PMD" : "PGD", 201 }, { /* pte */ 202 .name = "PTE", 203 }, 204 }; 205 206 static void dump_prot(struct pg_state *st) 207 { 208 unsigned int i; 209 210 for (i = 0; i < ARRAY_SIZE(pte_bits); i++) { 211 const char *s; 212 213 if ((st->current_prot & pte_bits[i].mask) == pte_bits[i].val) 214 s = pte_bits[i].set; 215 else 216 s = pte_bits[i].clear; 217 218 if (s) 219 pt_dump_seq_printf(st->seq, " %s", s); 220 } 221 } 222 223 #ifdef CONFIG_64BIT 224 #define ADDR_FORMAT "0x%016lx" 225 #else 226 #define ADDR_FORMAT "0x%08lx" 227 #endif 228 static void dump_addr(struct pg_state *st, unsigned long addr) 229 { 230 static const char units[] = "KMGTPE"; 231 const char *unit = units; 232 unsigned long delta; 233 234 pt_dump_seq_printf(st->seq, ADDR_FORMAT "-" ADDR_FORMAT " ", 235 st->start_address, addr); 236 237 pt_dump_seq_printf(st->seq, " " ADDR_FORMAT " ", st->start_pa); 238 delta = (addr - st->start_address) >> 10; 239 240 while (!(delta & 1023) && unit[1]) { 241 delta >>= 10; 242 unit++; 243 } 244 245 pt_dump_seq_printf(st->seq, "%9lu%c %s", delta, *unit, 246 pg_level[st->level].name); 247 } 248 249 static void note_prot_wx(struct pg_state *st, unsigned long addr) 250 { 251 if (!st->check_wx) 252 return; 253 254 if ((st->current_prot & (_PAGE_WRITE | _PAGE_EXEC)) != 255 (_PAGE_WRITE | _PAGE_EXEC)) 256 return; 257 258 WARN_ONCE(1, "riscv/mm: Found insecure W+X mapping at address %p/%pS\n", 259 (void *)st->start_address, (void *)st->start_address); 260 261 st->wx_pages += (addr - st->start_address) / PAGE_SIZE; 262 } 263 264 static void note_page(struct ptdump_state *pt_st, unsigned long addr, 265 int level, u64 val) 266 { 267 struct pg_state *st = container_of(pt_st, struct pg_state, ptdump); 268 u64 pa = PFN_PHYS(pte_pfn(__pte(val))); 269 u64 prot = 0; 270 271 if (level >= 0) 272 prot = val & pg_level[level].mask; 273 274 if (st->level == -1) { 275 st->level = level; 276 st->current_prot = prot; 277 st->start_address = addr; 278 st->start_pa = pa; 279 st->last_pa = pa; 280 pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); 281 } else if (prot != st->current_prot || 282 level != st->level || addr >= st->marker[1].start_address) { 283 if (st->current_prot) { 284 note_prot_wx(st, addr); 285 dump_addr(st, addr); 286 dump_prot(st); 287 pt_dump_seq_puts(st->seq, "\n"); 288 } 289 290 while (addr >= st->marker[1].start_address) { 291 st->marker++; 292 pt_dump_seq_printf(st->seq, "---[ %s ]---\n", 293 st->marker->name); 294 } 295 296 st->start_address = addr; 297 st->start_pa = pa; 298 st->last_pa = pa; 299 st->current_prot = prot; 300 st->level = level; 301 } else { 302 st->last_pa = pa; 303 } 304 } 305 306 static void ptdump_walk(struct seq_file *s, struct ptd_mm_info *pinfo) 307 { 308 struct pg_state st = { 309 .seq = s, 310 .marker = pinfo->markers, 311 .level = -1, 312 .ptdump = { 313 .note_page = note_page, 314 .range = (struct ptdump_range[]) { 315 {pinfo->base_addr, pinfo->end}, 316 {0, 0} 317 } 318 } 319 }; 320 321 ptdump_walk_pgd(&st.ptdump, pinfo->mm, NULL); 322 } 323 324 void ptdump_check_wx(void) 325 { 326 struct pg_state st = { 327 .seq = NULL, 328 .marker = (struct addr_marker[]) { 329 {0, NULL}, 330 {-1, NULL}, 331 }, 332 .level = -1, 333 .check_wx = true, 334 .ptdump = { 335 .note_page = note_page, 336 .range = (struct ptdump_range[]) { 337 {KERN_VIRT_START, ULONG_MAX}, 338 {0, 0} 339 } 340 } 341 }; 342 343 ptdump_walk_pgd(&st.ptdump, &init_mm, NULL); 344 345 if (st.wx_pages) 346 pr_warn("Checked W+X mappings: failed, %lu W+X pages found\n", 347 st.wx_pages); 348 else 349 pr_info("Checked W+X mappings: passed, no W+X pages found\n"); 350 } 351 352 static int ptdump_show(struct seq_file *m, void *v) 353 { 354 ptdump_walk(m, m->private); 355 356 return 0; 357 } 358 359 DEFINE_SHOW_ATTRIBUTE(ptdump); 360 361 static int __init ptdump_init(void) 362 { 363 unsigned int i, j; 364 365 address_markers[FIXMAP_START_NR].start_address = FIXADDR_START; 366 address_markers[FIXMAP_END_NR].start_address = FIXADDR_TOP; 367 address_markers[PCI_IO_START_NR].start_address = PCI_IO_START; 368 address_markers[PCI_IO_END_NR].start_address = PCI_IO_END; 369 #ifdef CONFIG_SPARSEMEM_VMEMMAP 370 address_markers[VMEMMAP_START_NR].start_address = VMEMMAP_START; 371 address_markers[VMEMMAP_END_NR].start_address = VMEMMAP_END; 372 #endif 373 address_markers[VMALLOC_START_NR].start_address = VMALLOC_START; 374 address_markers[VMALLOC_END_NR].start_address = VMALLOC_END; 375 address_markers[PAGE_OFFSET_NR].start_address = PAGE_OFFSET; 376 #ifdef CONFIG_KASAN 377 address_markers[KASAN_SHADOW_START_NR].start_address = KASAN_SHADOW_START; 378 address_markers[KASAN_SHADOW_END_NR].start_address = KASAN_SHADOW_END; 379 #endif 380 #ifdef CONFIG_64BIT 381 address_markers[MODULES_MAPPING_NR].start_address = MODULES_VADDR; 382 address_markers[KERNEL_MAPPING_NR].start_address = kernel_map.virt_addr; 383 #endif 384 385 kernel_ptd_info.base_addr = KERN_VIRT_START; 386 387 for (i = 0; i < ARRAY_SIZE(pg_level); i++) 388 for (j = 0; j < ARRAY_SIZE(pte_bits); j++) 389 pg_level[i].mask |= pte_bits[j].mask; 390 391 debugfs_create_file("kernel_page_tables", 0400, NULL, &kernel_ptd_info, 392 &ptdump_fops); 393 #ifdef CONFIG_EFI 394 if (efi_enabled(EFI_RUNTIME_SERVICES)) 395 debugfs_create_file("efi_page_tables", 0400, NULL, &efi_ptd_info, 396 &ptdump_fops); 397 #endif 398 399 return 0; 400 } 401 402 device_initcall(ptdump_init); 403