]> git.baikalelectronics.ru Git - kernel.git/commitdiff
sh: fix syscall tracing
authorRich Felker <dalias@libc.org>
Sat, 29 Aug 2020 01:01:41 +0000 (21:01 -0400)
committerRich Felker <dalias@libc.org>
Mon, 14 Sep 2020 01:22:55 +0000 (21:22 -0400)
Addition of SECCOMP_FILTER exposed a longstanding bug in
do_syscall_trace_enter, whereby r0 (the 5th argument register) was
mistakenly used where r3 (syscall_nr) was intended. By overwriting r0
rather than r3 with -1 when attempting to block a syscall, the
existing code would instead have caused the syscall to execute with an
argument clobbered.

Commit a39806ac4bf27ab1 then introduced skipping of the syscall when
do_syscall_trace_enter returns -1, so that the return value set by
seccomp filters would not be clobbered by -ENOSYS. This eliminated the
clobbering of the 5th argument register, but instead caused syscalls
made with a 5th argument of -1 to be misinterpreted as a request by
do_syscall_trace_enter to suppress the syscall.

Fixes: a39806ac4bf27ab1 ("sh: Add SECCOMP_FILTER")
Fixes: 814098d4ce4f8c2a ("sh: Make syscall tracer use tracehook notifiers, add TIF_NOTIFY_RESUME.")
Tested-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Signed-off-by: Rich Felker <dalias@libc.org>
arch/sh/kernel/entry-common.S
arch/sh/kernel/ptrace_32.c

index ad963104d22d47fd2afdfb21bf135d4ded22921d..91ab2607a1ff9f24ba615481a9761f946d69e871 100644 (file)
@@ -370,7 +370,6 @@ syscall_trace_entry:
         nop
        cmp/eq  #-1, r0
        bt      syscall_exit
-       mov.l   r0, @(OFF_R0,r15)       ! Save return value
        !                       Reload R0-R4 from kernel stack, where the
        !                       parent may have modified them using
        !                       ptrace(POKEUSR).  (Note that R0-R2 are
index b05bf92f9c3254469d31be2f898b183dbe2305dc..5281685f6ad1f728b3ac8c577aaa54a1c7f99fc2 100644 (file)
@@ -455,16 +455,11 @@ long arch_ptrace(struct task_struct *child, long request,
 
 asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
 {
-       long ret = 0;
-
        if (test_thread_flag(TIF_SYSCALL_TRACE) &&
-           tracehook_report_syscall_entry(regs))
-               /*
-                * Tracing decided this syscall should not happen.
-                * We'll return a bogus call number to get an ENOSYS
-                * error, but leave the original number in regs->regs[0].
-                */
-               ret = -1L;
+           tracehook_report_syscall_entry(regs)) {
+               regs->regs[0] = -ENOSYS;
+               return -1;
+       }
 
        if (secure_computing() == -1)
                return -1;
@@ -475,7 +470,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
        audit_syscall_entry(regs->regs[3], regs->regs[4], regs->regs[5],
                            regs->regs[6], regs->regs[7]);
 
-       return ret ?: regs->regs[0];
+       return 0;
 }
 
 asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)