Le 08/12/2020 à 14:00, Aneesh Kumar K.V a écrit :
On 12/8/20 2:07 PM, Christophe Leroy wrote:
search_exception_tables() is an heavy operation, we have to avoid it.
When KUAP is selected, we'll know the fault has been blocked by KUAP.
Otherwise, it behaves just as if the address was already in the TLBs
and no fault was generated.
Signed-off-by: Christophe Leroy <christophe.le...@csgroup.eu>
Reviewed-by: Nicholas Piggin <npig...@gmail.com>
---
v3: rebased
v2: Squashed with the preceeding patch which was re-ordering tests that get
removed in this patch.
---
arch/powerpc/mm/fault.c | 23 +++++++----------------
1 file changed, 7 insertions(+), 16 deletions(-)
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 3fcd34c28e10..1770b41e4730 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -210,28 +210,19 @@ static bool bad_kernel_fault(struct pt_regs *regs,
unsigned long error_code,
return true;
}
- if (!is_exec && address < TASK_SIZE && (error_code & (DSISR_PROTFAULT |
DSISR_KEYFAULT)) &&
- !search_exception_tables(regs->nip)) {
- pr_crit_ratelimited("Kernel attempted to access user page (%lx) - exploit attempt? (uid:
%d)\n",
- address,
- from_kuid(&init_user_ns, current_uid()));
- }
-
// Kernel fault on kernel address is bad
if (address >= TASK_SIZE)
return true;
- // Fault on user outside of certain regions (eg. copy_tofrom_user()) is bad
- if (!search_exception_tables(regs->nip))
- return true;
-
- // Read/write fault in a valid region (the exception table search passed
- // above), but blocked by KUAP is bad, it can never succeed.
- if (bad_kuap_fault(regs, address, is_write))
+ // Read/write fault blocked by KUAP is bad, it can never succeed.
+ if (bad_kuap_fault(regs, address, is_write)) {
+ pr_crit_ratelimited("Kernel attempted to %s user page (%lx) - exploit
attempt? (uid: %d)\n",
+ is_write ? "write" : "read", address,
+ from_kuid(&init_user_ns, current_uid()));
return true;
+ }
Should we update bad_kuap_fault to check for !is_kernel_addr() and error_code & (DSISIR_PROT_FAULT |
DSISIR_KEYFAULT). I am wondering whether we can take another fault w.r.t kernel address/user address
and end up reporting that as KUAP fault?
Just before this we do:
if (address >= TASK_SIZE)
return true;
About the error code, I don't know. Can we take a fault that is not a
DSISR_PROT_FAULT |
DSISR_KEYFAULT and that is not a KUAP fault ?
Previously (before this patch), the error code was taken into account for the call to
search_exception_tables(), but has never been for the bad_kuap_fault().
- // What's left? Kernel fault on user in well defined regions (extable
- // matched), and allowed by KUAP in the faulting context.
+ // What's left? Kernel fault on user and allowed by KUAP in the faulting
context.
return false;
}
-aneesh
Christophe