Commit f67c2da9 authored by Heiko Carstens's avatar Heiko Carstens Committed by Vasily Gorbik
Browse files

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: default avatarClaudio Imbrenda <imbrenda@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 5be05c35
Loading
Loading
Loading
Loading
+19 −26
Original line number Diff line number Diff line
@@ -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;