Commit 8dced77d authored by Mark Rutland's avatar Mark Rutland Committed by Nanyong Sun
Browse files

arm64: mm: kfence: only handle translation faults

mainline inclusion
from mainline-v6.2-rc1
commit 0bb1fbff
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8YLWW

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0bb1fbffc631064db567ccaeb9ed6b6df6342b66

------------------------------------------------------

Alexander noted that KFENCE only expects to handle faults from invalid page
table entries (i.e. translation faults), but arm64's fault handling logic will
call kfence_handle_page_fault() for other types of faults, including alignment
faults caused by unaligned atomics. This has the unfortunate property of
causing those other faults to be reported as "KFENCE: use-after-free",
which is misleading and hinders debugging.

Fix this by only forwarding unhandled translation faults to the KFENCE
code, similar to what x86 does already.

Alexander has verified that this passes all the tests in the KFENCE test
suite and avoids bogus reports on misaligned atomics.

Link: https://lore.kernel.org/all/20221102081620.1465154-1-zhongbaisong@huawei.com/


Fixes: 840b2398 ("arm64, kfence: enable KFENCE for ARM64")
Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
Reviewed-by: default avatarAlexander Potapenko <glider@google.com>
Tested-by: default avatarAlexander Potapenko <glider@google.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marco Elver <elver@google.com>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20221114104411.2853040-1-mark.rutland@arm.com


Signed-off-by: default avatarWill Deacon <will@kernel.org>
Signed-off-by: default avatarNanyong Sun <sunnanyong@huawei.com>
parent 8afc6e23
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -299,6 +299,11 @@ static void die_kernel_fault(const char *msg, unsigned long addr,
	do_exit(SIGKILL);
}

static bool is_translation_fault(unsigned long esr)
{
	return (esr & ESR_ELx_FSC_TYPE) == ESR_ELx_FSC_FAULT;
}

static void __do_kernel_fault(unsigned long addr, unsigned int esr,
			      struct pt_regs *regs)
{
@@ -325,7 +330,8 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr,
	} else if (addr < PAGE_SIZE) {
		msg = "NULL pointer dereference";
	} else {
		if (kfence_handle_page_fault(addr, esr & ESR_ELx_WNR, regs))
		if (is_translation_fault(esr) &&
		    kfence_handle_page_fault(addr, esr & ESR_ELx_WNR, regs))
			return;

		msg = "paging request";