From 5b1ba9e30cf0e259450da19189811eb140733f83 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 1 Oct 2012 16:18:46 +0200 Subject: s390/mm,pageattr: add more page table walk sanity checks The current page table walk code in pageattr.c only checks for large pages while walking the kernel page table, but happily assumes that everything else is just fine. Add more checks so we never access invalid memory regions. Reviewed-by: Gerald Schaefer Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/mm/pageattr.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) (limited to 'arch/s390/mm/pageattr.c') diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c index 0f33bab3e984..b56953dd95f8 100644 --- a/arch/s390/mm/pageattr.c +++ b/arch/s390/mm/pageattr.c @@ -8,25 +8,38 @@ #include #include +static pte_t *walk_page_table(unsigned long addr) +{ + pgd_t *pgdp; + pud_t *pudp; + pmd_t *pmdp; + pte_t *ptep; + + pgdp = pgd_offset_k(addr); + if (pgd_none(*pgdp)) + return NULL; + pudp = pud_offset(pgdp, addr); + if (pud_none(*pudp)) + return NULL; + pmdp = pmd_offset(pudp, addr); + if (pmd_none(*pmdp) || pmd_large(*pmdp)) + return NULL; + ptep = pte_offset_kernel(pmdp, addr); + if (pte_none(*ptep)) + return NULL; + return ptep; +} + static void change_page_attr(unsigned long addr, int numpages, pte_t (*set) (pte_t)) { pte_t *ptep, pte; - pmd_t *pmdp; - pud_t *pudp; - pgd_t *pgdp; int i; for (i = 0; i < numpages; i++) { - pgdp = pgd_offset(&init_mm, addr); - pudp = pud_offset(pgdp, addr); - pmdp = pmd_offset(pudp, addr); - if (pmd_large(*pmdp)) { - WARN_ON_ONCE(1); - continue; - } - ptep = pte_offset_kernel(pmdp, addr); - + ptep = walk_page_table(addr); + if (WARN_ON_ONCE(!ptep)) + break; pte = *ptep; pte = set(pte); __ptep_ipte(addr, ptep); -- cgit v1.2.3