• Haorong Lu's avatar
    riscv: signal: handle syscall restart before get_signal · ce4f78f1
    Haorong Lu authored
    In the current riscv implementation, blocking syscalls like read() may
    not correctly restart after being interrupted by ptrace. This problem
    arises when the syscall restart process in arch_do_signal_or_restart()
    is bypassed due to changes to the regs->cause register, such as an
    ebreak instruction.
    
    Steps to reproduce:
    1. Interrupt the tracee process with PTRACE_SEIZE & PTRACE_INTERRUPT.
    2. Backup original registers and instruction at new_pc.
    3. Change pc to new_pc, and inject an instruction (like ebreak) to this
       address.
    4. Resume with PTRACE_CONT and wait for the process to stop again after
       executing ebreak.
    5. Restore original registers and instructions, and detach from the
       tracee process.
    6. Now the read() syscall in tracee will return -1 with errno set to
       ERESTARTSYS.
    
    Specifically, during an interrupt, the regs->cause changes from
    EXC_SYSCALL to EXC_BREAKPOINT due to the injected ebreak, which is
    inaccessible via ptrace so we cannot restore it. This alteration breaks
    the syscall restart condition and ends the read() syscall with an
    ERESTARTSYS error. According to include/linux/errno.h, it should never
    be seen by user programs. X86 can avoid this issue as it checks the
    syscall condition using a register (orig_ax) exposed to user space.
    Arm64 handles syscall restart before calling get_signal, where it could
    be paused and inspected by ptrace/debugger.
    
    This patch adjusts the riscv implementation to arm64 style, which also
    checks syscall using a kernel register (syscallno). It ensures the
    syscall restart process is not bypassed when changes to the cause
    register occur, providing more consistent behavior across various
    architectures.
    
    For a simplified reproduction program, feel free to visit:
    https://github.com/ancientmodern/riscv-ptrace-bug-demo.
    Signed-off-by: default avatarHaorong Lu <ancientmodern4@gmail.com>
    Link: https://lore.kernel.org/r/20230803224458.4156006-1-ancientmodern4@gmail.comSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
    ce4f78f1
signal.c 13.1 KB