From 9be763fb64891faae235f69861934032b5b55a05 Mon Sep 17 00:00:00 2001 From: Chris Goldsworthy Date: Mon, 5 Feb 2024 20:55:12 -0800 Subject: [PATCH] ANDROID: arm64: Call fixup_exception() within do_sea() path_lookupat() is capable of safely reading unampped VAs. If an unmapped VA is read whilst the function is being called, the resulting page fault will get re-directed to __do_page_fault(), which will call fixup_exception() to handle the aforementioned unmapped VA read. Now, for an OS running in a VM, let's say that memory was still mapped at S1 but lent to another VM (i.e. unmapped at S2 for the given VM). The reading of an unmapped VA in path_lookupat() still needs to be handled. For hypervisors that inject an abort leading to a do_sea() call, call fixup_exception() from do_sea() if trace_android_vh_try_fixup_sea() indicates that we can do so. Bug: 320358381 Change-Id: I0aedcd954f08e3011b27524f9a7b038debbb246d Signed-off-by: Chris Goldsworthy --- arch/arm64/mm/fault.c | 5 +++++ drivers/android/vendor_hooks.c | 1 + include/trace/hooks/fault.h | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 7d522b037d9a..2f63b2a86c63 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -746,6 +746,11 @@ static int do_sea(unsigned long far, unsigned long esr, struct pt_regs *regs) { const struct fault_info *inf; unsigned long siaddr; + bool can_fixup = false; + + trace_android_vh_try_fixup_sea(far, esr, regs, &can_fixup); + if (can_fixup && fixup_exception(regs)) + return 0; inf = esr_to_fault_info(esr); diff --git a/drivers/android/vendor_hooks.c b/drivers/android/vendor_hooks.c index 20b3b02b7db4..19f96411720a 100644 --- a/drivers/android/vendor_hooks.c +++ b/drivers/android/vendor_hooks.c @@ -244,6 +244,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_try_to_freeze_todo_unfrozen); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_die_kernel_fault); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_do_sea); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_do_sp_pc_abort); +EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_try_fixup_sea); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_do_undefinstr); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_do_el1_bti); EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_do_el1_fpac); diff --git a/include/trace/hooks/fault.h b/include/trace/hooks/fault.h index d3e26ea66160..121a3404806e 100644 --- a/include/trace/hooks/fault.h +++ b/include/trace/hooks/fault.h @@ -21,6 +21,11 @@ DECLARE_RESTRICTED_HOOK(android_rvh_do_sp_pc_abort, TP_ARGS(addr, esr, regs), TP_CONDITION(!user_mode(regs))); +DECLARE_HOOK(android_vh_try_fixup_sea, + TP_PROTO(unsigned long addr, unsigned long esr, struct pt_regs *regs, + bool *can_fixup), + TP_ARGS(addr, esr, regs, can_fixup)); + #endif /* _TRACE_HOOK_FAULT_H */ /* This part must be outside protection */ #include