Skip to content

Commit 7d44b9f

Browse files
BenjaminGrayNp1adi-g15-ibm
authored andcommitted
powerpc/dexcr: Move HASHCHK trap handler
Syzkaller reported a sleep in atomic context bug relating to the HASHCHK handler logic: BUG: sleeping function called from invalid context at arch/powerpc/kernel/traps.c:1518 in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 25040, name: syz-executor preempt_count: 0, expected: 0 RCU nest depth: 0, expected: 0 no locks held by syz-executor/25040. irq event stamp: 34 hardirqs last enabled at (33): [<c000000000048b38>] prep_irq_for_enabled_exit arch/powerpc/kernel/interrupt.c:56 [inline] hardirqs last enabled at (33): [<c000000000048b38>] interrupt_exit_user_prepare_main+0x148/0x600 arch/powerpc/kernel/interrupt.c:230 hardirqs last disabled at (34): [<c00000000003e6a4>] interrupt_enter_prepare+0x144/0x4f0 arch/powerpc/include/asm/interrupt.h:176 softirqs last enabled at (0): [<c000000000281954>] copy_process+0x16e4/0x4750 kernel/fork.c:2436 softirqs last disabled at (0): [<0000000000000000>] 0x0 CPU: 15 PID: 25040 Comm: syz-executor Not tainted 6.5.0-rc5-00001-g3ccdff6bb06d SamirMulani#3 Hardware name: IBM,9105-22A POWER10 (raw) 0x800200 0xf000006 of:IBM,FW1040.00 (NL1040_021) hv:phyp pSeries Call Trace: [c0000000a8247ce0] [c00000000032b0e4] __might_resched+0x3b4/0x400 kernel/sched/core.c:10189 [c0000000a8247d80] [c0000000008c7dc8] __might_fault+0xa8/0x170 mm/memory.c:5853 [c0000000a8247dc0] [c00000000004160c] do_program_check+0x32c/0xb20 arch/powerpc/kernel/traps.c:1518 [c0000000a8247e50] [c000000000009b2c] program_check_common_virt+0x3bc/0x3c0 To determine if a trap was caused by a HASHCHK instruction, we inspect the user instruction that triggered the trap. However this may sleep if the page needs to be faulted in (get_user_instr() reaches __get_user(), which calls might_fault() and triggers the bug message). Move the HASHCHK handler logic to after we allow IRQs, which is fine because we are only interested in HASHCHK if it's a user space trap. Fixes: 5bcba4e ("powerpc/dexcr: Handle hashchk exception") Signed-off-by: Benjamin Gray <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://msgid.link/[email protected]
1 parent b337bf2 commit 7d44b9f

File tree

1 file changed

+36
-20
lines changed

1 file changed

+36
-20
lines changed

arch/powerpc/kernel/traps.c

+36-20
Original file line numberDiff line numberDiff line change
@@ -1514,23 +1514,11 @@ static void do_program_check(struct pt_regs *regs)
15141514
return;
15151515
}
15161516

1517-
if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE) && user_mode(regs)) {
1518-
ppc_inst_t insn;
1519-
1520-
if (get_user_instr(insn, (void __user *)regs->nip)) {
1521-
_exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
1522-
return;
1523-
}
1524-
1525-
if (ppc_inst_primary_opcode(insn) == 31 &&
1526-
get_xop(ppc_inst_val(insn)) == OP_31_XOP_HASHCHK) {
1527-
_exception(SIGILL, regs, ILL_ILLOPN, regs->nip);
1528-
return;
1529-
}
1517+
/* User mode considers other cases after enabling IRQs */
1518+
if (!user_mode(regs)) {
1519+
_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
1520+
return;
15301521
}
1531-
1532-
_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
1533-
return;
15341522
}
15351523
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
15361524
if (reason & REASON_TM) {
@@ -1563,16 +1551,44 @@ static void do_program_check(struct pt_regs *regs)
15631551

15641552
/*
15651553
* If we took the program check in the kernel skip down to sending a
1566-
* SIGILL. The subsequent cases all relate to emulating instructions
1567-
* which we should only do for userspace. We also do not want to enable
1568-
* interrupts for kernel faults because that might lead to further
1569-
* faults, and loose the context of the original exception.
1554+
* SIGILL. The subsequent cases all relate to user space, such as
1555+
* emulating instructions which we should only do for user space. We
1556+
* also do not want to enable interrupts for kernel faults because that
1557+
* might lead to further faults, and loose the context of the original
1558+
* exception.
15701559
*/
15711560
if (!user_mode(regs))
15721561
goto sigill;
15731562

15741563
interrupt_cond_local_irq_enable(regs);
15751564

1565+
/*
1566+
* (reason & REASON_TRAP) is mostly handled before enabling IRQs,
1567+
* except get_user_instr() can sleep so we cannot reliably inspect the
1568+
* current instruction in that context. Now that we know we are
1569+
* handling a user space trap and can sleep, we can check if the trap
1570+
* was a hashchk failure.
1571+
*/
1572+
if (reason & REASON_TRAP) {
1573+
if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE)) {
1574+
ppc_inst_t insn;
1575+
1576+
if (get_user_instr(insn, (void __user *)regs->nip)) {
1577+
_exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
1578+
return;
1579+
}
1580+
1581+
if (ppc_inst_primary_opcode(insn) == 31 &&
1582+
get_xop(ppc_inst_val(insn)) == OP_31_XOP_HASHCHK) {
1583+
_exception(SIGILL, regs, ILL_ILLOPN, regs->nip);
1584+
return;
1585+
}
1586+
}
1587+
1588+
_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
1589+
return;
1590+
}
1591+
15761592
/* (reason & REASON_ILLEGAL) would be the obvious thing here,
15771593
* but there seems to be a hardware bug on the 405GP (RevD)
15781594
* that means ESR is sometimes set incorrectly - either to

0 commit comments

Comments
 (0)