Skip to content

Commit 02ce94c

Browse files
committed
xtensa: fix system_call interaction with ptrace
Don't overwrite return value if system call was cancelled at entry by ptrace. Return status code from do_syscall_trace_enter so that pt_regs::syscall doesn't need to be changed to skip syscall. Signed-off-by: Max Filippov <[email protected]>
1 parent ba9c1d6 commit 02ce94c

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

arch/xtensa/kernel/entry.S

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,6 +1892,7 @@ ENTRY(system_call)
18921892

18931893
mov a6, a2
18941894
call4 do_syscall_trace_enter
1895+
beqz a6, .Lsyscall_exit
18951896
l32i a7, a2, PT_SYSCALL
18961897

18971898
1:
@@ -1904,8 +1905,6 @@ ENTRY(system_call)
19041905

19051906
addx4 a4, a7, a4
19061907
l32i a4, a4, 0
1907-
movi a5, sys_ni_syscall;
1908-
beq a4, a5, 1f
19091908

19101909
/* Load args: arg0 - arg5 are passed via regs. */
19111910

@@ -1925,6 +1924,7 @@ ENTRY(system_call)
19251924

19261925
s32i a6, a2, PT_AREG2
19271926
bnez a3, 1f
1927+
.Lsyscall_exit:
19281928
abi_ret(4)
19291929

19301930
1:

arch/xtensa/kernel/ptrace.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,14 +542,28 @@ long arch_ptrace(struct task_struct *child, long request,
542542
return ret;
543543
}
544544

545-
void do_syscall_trace_enter(struct pt_regs *regs)
545+
void do_syscall_trace_leave(struct pt_regs *regs);
546+
int do_syscall_trace_enter(struct pt_regs *regs)
546547
{
548+
if (regs->syscall == NO_SYSCALL)
549+
regs->areg[2] = -ENOSYS;
550+
547551
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
548-
tracehook_report_syscall_entry(regs))
552+
tracehook_report_syscall_entry(regs)) {
553+
regs->areg[2] = -ENOSYS;
549554
regs->syscall = NO_SYSCALL;
555+
return 0;
556+
}
557+
558+
if (regs->syscall == NO_SYSCALL) {
559+
do_syscall_trace_leave(regs);
560+
return 0;
561+
}
550562

551563
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
552564
trace_sys_enter(regs, syscall_get_nr(current, regs));
565+
566+
return 1;
553567
}
554568

555569
void do_syscall_trace_leave(struct pt_regs *regs)

0 commit comments

Comments
 (0)