Skip to content

Commit b7dc5a0

Browse files
ldv-althdeller
authored andcommitted
parisc: Fix ptrace syscall number modification
Commit 910cd32 ("parisc: Fix and enable seccomp filter support") introduced a regression in ptrace-based syscall tampering: when tracer changes syscall number to -1, the kernel fails to initialize %r28 with -ENOSYS and subsequently fails to return the error code of the failed syscall to userspace. This erroneous behaviour could be observed with a simple strace syscall fault injection command which is expected to print something like this: $ strace -a0 -ewrite -einject=write:error=enospc echo hello write(1, "hello\n", 6) = -1 ENOSPC (No space left on device) (INJECTED) write(2, "echo: ", 6) = -1 ENOSPC (No space left on device) (INJECTED) write(2, "write error", 11) = -1 ENOSPC (No space left on device) (INJECTED) write(2, "\n", 1) = -1 ENOSPC (No space left on device) (INJECTED) +++ exited with 1 +++ After commit 910cd32 it loops printing something like this instead: write(1, "hello\n", 6../strace: Failed to tamper with process 12345: unexpectedly got no error (return value 0, error 0) ) = 0 (INJECTED) This bug was found by strace test suite. Fixes: 910cd32 ("parisc: Fix and enable seccomp filter support") Cc: stable@vger.kernel.org # v4.5+ Signed-off-by: Dmitry V. Levin <ldv@altlinux.org> Tested-by: Helge Deller <deller@gmx.de> Signed-off-by: Helge Deller <deller@gmx.de>
1 parent f6163d6 commit b7dc5a0

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

arch/parisc/kernel/ptrace.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -308,15 +308,29 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
308308

309309
long do_syscall_trace_enter(struct pt_regs *regs)
310310
{
311-
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
312-
tracehook_report_syscall_entry(regs)) {
311+
if (test_thread_flag(TIF_SYSCALL_TRACE)) {
312+
int rc = tracehook_report_syscall_entry(regs);
313+
313314
/*
314-
* Tracing decided this syscall should not happen or the
315-
* debugger stored an invalid system call number. Skip
316-
* the system call and the system call restart handling.
315+
* As tracesys_next does not set %r28 to -ENOSYS
316+
* when %r20 is set to -1, initialize it here.
317317
*/
318-
regs->gr[20] = -1UL;
319-
goto out;
318+
regs->gr[28] = -ENOSYS;
319+
320+
if (rc) {
321+
/*
322+
* A nonzero return code from
323+
* tracehook_report_syscall_entry() tells us
324+
* to prevent the syscall execution. Skip
325+
* the syscall call and the syscall restart handling.
326+
*
327+
* Note that the tracer may also just change
328+
* regs->gr[20] to an invalid syscall number,
329+
* that is handled by tracesys_next.
330+
*/
331+
regs->gr[20] = -1UL;
332+
return -1;
333+
}
320334
}
321335

322336
/* Do the secure computing check after ptrace. */
@@ -340,7 +354,6 @@ long do_syscall_trace_enter(struct pt_regs *regs)
340354
regs->gr[24] & 0xffffffff,
341355
regs->gr[23] & 0xffffffff);
342356

343-
out:
344357
/*
345358
* Sign extend the syscall number to 64bit since it may have been
346359
* modified by a compat ptrace call

0 commit comments

Comments
 (0)