s390/mm,fault: use get_kernel_nofault() to dereference in dump_pagetable()

The page table dumper uses get_kernel_nofault() to test if dereferencing
page table entries is possible. Use the result, which is the required page
table entry, instead of throwing it away and dereferencing a second time
without any safe guard.

Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
Heiko Carstens 2023-10-12 09:40:44 +02:00 committed by Vasily Gorbik
parent 5be05c35e7
commit f67c2da9f1

View file

@ -112,59 +112,52 @@ static __always_inline bool fault_is_write(struct pt_regs *regs)
return false;
}
static int bad_address(void *p)
{
unsigned long dummy;
return get_kernel_nofault(dummy, (unsigned long *)p);
}
static void dump_pagetable(unsigned long asce, unsigned long address)
{
unsigned long *table = __va(asce & _ASCE_ORIGIN);
unsigned long entry, *table = __va(asce & _ASCE_ORIGIN);
pr_alert("AS:%016lx ", asce);
switch (asce & _ASCE_TYPE_MASK) {
case _ASCE_TYPE_REGION1:
table += (address & _REGION1_INDEX) >> _REGION1_SHIFT;
if (bad_address(table))
if (get_kernel_nofault(entry, table))
goto bad;
pr_cont("R1:%016lx ", *table);
if (*table & _REGION_ENTRY_INVALID)
pr_cont("R1:%016lx ", entry);
if (entry & _REGION_ENTRY_INVALID)
goto out;
table = __va(*table & _REGION_ENTRY_ORIGIN);
table = __va(entry & _REGION_ENTRY_ORIGIN);
fallthrough;
case _ASCE_TYPE_REGION2:
table += (address & _REGION2_INDEX) >> _REGION2_SHIFT;
if (bad_address(table))
if (get_kernel_nofault(entry, table))
goto bad;
pr_cont("R2:%016lx ", *table);
if (*table & _REGION_ENTRY_INVALID)
pr_cont("R2:%016lx ", entry);
if (entry & _REGION_ENTRY_INVALID)
goto out;
table = __va(*table & _REGION_ENTRY_ORIGIN);
table = __va(entry & _REGION_ENTRY_ORIGIN);
fallthrough;
case _ASCE_TYPE_REGION3:
table += (address & _REGION3_INDEX) >> _REGION3_SHIFT;
if (bad_address(table))
if (get_kernel_nofault(entry, table))
goto bad;
pr_cont("R3:%016lx ", *table);
if (*table & (_REGION_ENTRY_INVALID | _REGION3_ENTRY_LARGE))
pr_cont("R3:%016lx ", entry);
if (entry & (_REGION_ENTRY_INVALID | _REGION3_ENTRY_LARGE))
goto out;
table = __va(*table & _REGION_ENTRY_ORIGIN);
table = __va(entry & _REGION_ENTRY_ORIGIN);
fallthrough;
case _ASCE_TYPE_SEGMENT:
table += (address & _SEGMENT_INDEX) >> _SEGMENT_SHIFT;
if (bad_address(table))
if (get_kernel_nofault(entry, table))
goto bad;
pr_cont("S:%016lx ", *table);
if (*table & (_SEGMENT_ENTRY_INVALID | _SEGMENT_ENTRY_LARGE))
pr_cont("S:%016lx ", entry);
if (entry & (_SEGMENT_ENTRY_INVALID | _SEGMENT_ENTRY_LARGE))
goto out;
table = __va(*table & _SEGMENT_ENTRY_ORIGIN);
table = __va(entry & _SEGMENT_ENTRY_ORIGIN);
}
table += (address & _PAGE_INDEX) >> _PAGE_SHIFT;
if (bad_address(table))
if (get_kernel_nofault(entry, table))
goto bad;
pr_cont("P:%016lx ", *table);
pr_cont("P:%016lx ", entry);
out:
pr_cont("\n");
return;