aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2018-04-17 09:27:16 -0400
committerThomas Gleixner <tglx@linutronix.de>2018-04-17 09:43:01 -0400
commitd6ef1f194b7569af8b8397876dc9ab07649d63cb (patch)
tree9d7bd7b181f1d7f32abb559812163b8eba076d8b
parent1340ccfa9a9afefdbab90d7935d4ed19817e37c2 (diff)
x86/mm: Prevent kernel Oops in PTDUMP code with HIGHPTE=y
The walk_pte_level() function just uses __va to get the virtual address of the PTE page, but that breaks when the PTE page is not in the direct mapping with HIGHPTE=y. The result is an unhandled kernel paging request at some random address when accessing the current_kernel or current_user file. Use the correct API to access PTE pages. Fixes: fe770bf0310d ('x86: clean up the page table dumper and add 32-bit support') Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: stable@vger.kernel.org Cc: jgross@suse.com Cc: JBeulich@suse.com Cc: hpa@zytor.com Cc: aryabinin@virtuozzo.com Cc: kirill.shutemov@linux.intel.com Link: https://lkml.kernel.org/r/1523971636-4137-1-git-send-email-joro@8bytes.org
-rw-r--r--arch/x86/mm/dump_pagetables.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
index 62a7e9f65dec..cc7ff5957194 100644
--- a/arch/x86/mm/dump_pagetables.c
+++ b/arch/x86/mm/dump_pagetables.c
@@ -18,6 +18,7 @@
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/sched.h> 19#include <linux/sched.h>
20#include <linux/seq_file.h> 20#include <linux/seq_file.h>
21#include <linux/highmem.h>
21 22
22#include <asm/pgtable.h> 23#include <asm/pgtable.h>
23 24
@@ -334,16 +335,16 @@ static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr,
334 pgprotval_t eff_in, unsigned long P) 335 pgprotval_t eff_in, unsigned long P)
335{ 336{
336 int i; 337 int i;
337 pte_t *start; 338 pte_t *pte;
338 pgprotval_t prot, eff; 339 pgprotval_t prot, eff;
339 340
340 start = (pte_t *)pmd_page_vaddr(addr);
341 for (i = 0; i < PTRS_PER_PTE; i++) { 341 for (i = 0; i < PTRS_PER_PTE; i++) {
342 prot = pte_flags(*start);
343 eff = effective_prot(eff_in, prot);
344 st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT); 342 st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT);
343 pte = pte_offset_map(&addr, st->current_address);
344 prot = pte_flags(*pte);
345 eff = effective_prot(eff_in, prot);
345 note_page(m, st, __pgprot(prot), eff, 5); 346 note_page(m, st, __pgprot(prot), eff, 5);
346 start++; 347 pte_unmap(pte);
347 } 348 }
348} 349}
349#ifdef CONFIG_KASAN 350#ifdef CONFIG_KASAN