Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5b1ba9e3 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky
Browse files

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: default avatarGerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 378b1e7a
Loading
Loading
Loading
Loading
+25 −12
Original line number Diff line number Diff line
@@ -8,25 +8,38 @@
#include <asm/cacheflush.h>
#include <asm/pgtable.h>

static void change_page_attr(unsigned long addr, int numpages,
			     pte_t (*set) (pte_t))
static pte_t *walk_page_table(unsigned long addr)
{
	pte_t *ptep, pte;
	pmd_t *pmdp;
	pud_t *pudp;
	pgd_t *pgdp;
	int i;
	pud_t *pudp;
	pmd_t *pmdp;
	pte_t *ptep;

	for (i = 0; i < numpages; i++) {
		pgdp = pgd_offset(&init_mm, addr);
	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_large(*pmdp)) {
			WARN_ON_ONCE(1);
			continue;
		}
	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;
	int i;

	for (i = 0; i < numpages; i++) {
		ptep = walk_page_table(addr);
		if (WARN_ON_ONCE(!ptep))
			break;
		pte = *ptep;
		pte = set(pte);
		__ptep_ipte(addr, ptep);