Skip to content

Commit cbd7e6c

Browse files
chleroympe
authored andcommitted
powerpc/fault: Avoid heavy search_exception_tables() verification
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. When it is blocked by KUAP, check whether we are in an expected userspace access place. If so, emit a warning to spot something is going work. Otherwise, just remain silent, it will likely Oops soon. When KUAP is not selected, it behaves just as if the address was already in the TLBs and no fault was generated. Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Reviewed-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/9870f01e293a5a76c4f4e4ddd4a6b0f63038c591.1607491748.git.christophe.leroy@csgroup.eu
1 parent 3dc12df commit cbd7e6c

File tree

1 file changed

+13
-15
lines changed

1 file changed

+13
-15
lines changed

arch/powerpc/mm/fault.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -210,28 +210,26 @@ static bool bad_kernel_fault(struct pt_regs *regs, unsigned long error_code,
210210
return true;
211211
}
212212

213-
if (!is_exec && address < TASK_SIZE && (error_code & (DSISR_PROTFAULT | DSISR_KEYFAULT)) &&
214-
!search_exception_tables(regs->nip)) {
215-
pr_crit_ratelimited("Kernel attempted to access user page (%lx) - exploit attempt? (uid: %d)\n",
216-
address,
217-
from_kuid(&init_user_ns, current_uid()));
218-
}
219-
220213
// Kernel fault on kernel address is bad
221214
if (address >= TASK_SIZE)
222215
return true;
223216

224-
// Fault on user outside of certain regions (eg. copy_tofrom_user()) is bad
225-
if (!search_exception_tables(regs->nip))
226-
return true;
217+
// Read/write fault blocked by KUAP is bad, it can never succeed.
218+
if (bad_kuap_fault(regs, address, is_write)) {
219+
pr_crit_ratelimited("Kernel attempted to %s user page (%lx) - exploit attempt? (uid: %d)\n",
220+
is_write ? "write" : "read", address,
221+
from_kuid(&init_user_ns, current_uid()));
222+
223+
// Fault on user outside of certain regions (eg. copy_tofrom_user()) is bad
224+
if (!search_exception_tables(regs->nip))
225+
return true;
227226

228-
// Read/write fault in a valid region (the exception table search passed
229-
// above), but blocked by KUAP is bad, it can never succeed.
230-
if (bad_kuap_fault(regs, address, is_write))
227+
// Read/write fault in a valid region (the exception table search passed
228+
// above), but blocked by KUAP is bad, it can never succeed.
231229
return WARN(true, "Bug: %s fault blocked by KUAP!", is_write ? "Write" : "Read");
230+
}
232231

233-
// What's left? Kernel fault on user in well defined regions (extable
234-
// matched), and allowed by KUAP in the faulting context.
232+
// What's left? Kernel fault on user and allowed by KUAP in the faulting context.
235233
return false;
236234
}
237235

0 commit comments

Comments
 (0)