xtensa: fix system_call interaction with ptrace
[ Upstream commit 02ce94c229
]
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 <jcmvbkbc@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
f9f47ef869
commit
a1a6f8a14c
|
@ -1897,6 +1897,7 @@ ENTRY(system_call)
|
||||||
|
|
||||||
mov a6, a2
|
mov a6, a2
|
||||||
call4 do_syscall_trace_enter
|
call4 do_syscall_trace_enter
|
||||||
|
beqz a6, .Lsyscall_exit
|
||||||
l32i a7, a2, PT_SYSCALL
|
l32i a7, a2, PT_SYSCALL
|
||||||
|
|
||||||
1:
|
1:
|
||||||
|
@ -1911,8 +1912,6 @@ ENTRY(system_call)
|
||||||
|
|
||||||
addx4 a4, a7, a4
|
addx4 a4, a7, a4
|
||||||
l32i a4, a4, 0
|
l32i a4, a4, 0
|
||||||
movi a5, sys_ni_syscall;
|
|
||||||
beq a4, a5, 1f
|
|
||||||
|
|
||||||
/* Load args: arg0 - arg5 are passed via regs. */
|
/* Load args: arg0 - arg5 are passed via regs. */
|
||||||
|
|
||||||
|
@ -1932,6 +1931,7 @@ ENTRY(system_call)
|
||||||
|
|
||||||
s32i a6, a2, PT_AREG2
|
s32i a6, a2, PT_AREG2
|
||||||
bnez a3, 1f
|
bnez a3, 1f
|
||||||
|
.Lsyscall_exit:
|
||||||
abi_ret(4)
|
abi_ret(4)
|
||||||
|
|
||||||
1:
|
1:
|
||||||
|
|
|
@ -542,14 +542,28 @@ long arch_ptrace(struct task_struct *child, long request,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_syscall_trace_enter(struct pt_regs *regs)
|
void do_syscall_trace_leave(struct pt_regs *regs);
|
||||||
|
int do_syscall_trace_enter(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
if (regs->syscall == NO_SYSCALL)
|
||||||
|
regs->areg[2] = -ENOSYS;
|
||||||
|
|
||||||
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
|
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
|
||||||
tracehook_report_syscall_entry(regs))
|
tracehook_report_syscall_entry(regs)) {
|
||||||
|
regs->areg[2] = -ENOSYS;
|
||||||
regs->syscall = NO_SYSCALL;
|
regs->syscall = NO_SYSCALL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (regs->syscall == NO_SYSCALL) {
|
||||||
|
do_syscall_trace_leave(regs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
|
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
|
||||||
trace_sys_enter(regs, syscall_get_nr(current, regs));
|
trace_sys_enter(regs, syscall_get_nr(current, regs));
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_syscall_trace_leave(struct pt_regs *regs)
|
void do_syscall_trace_leave(struct pt_regs *regs)
|
||||||
|
|
Loading…
Reference in New Issue