Commit 02ce94c2 authored by Max Filippov's avatar Max Filippov
Browse files

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: default avatarMax Filippov <jcmvbkbc@gmail.com>
parent ba9c1d65
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1892,6 +1892,7 @@ ENTRY(system_call)

	mov	a6, a2
	call4	do_syscall_trace_enter
	beqz	a6, .Lsyscall_exit
	l32i	a7, a2, PT_SYSCALL

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

	addx4	a4, a7, a4
	l32i	a4, a4, 0
	movi	a5, sys_ni_syscall;
	beq	a4, a5, 1f

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

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

	s32i	a6, a2, PT_AREG2
	bnez	a3, 1f
.Lsyscall_exit:
	abi_ret(4)

1:
+16 −2
Original line number Diff line number Diff line
@@ -542,14 +542,28 @@ long arch_ptrace(struct task_struct *child, long request,
	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) &&
	    tracehook_report_syscall_entry(regs))
	    tracehook_report_syscall_entry(regs)) {
		regs->areg[2] = -ENOSYS;
		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))
		trace_sys_enter(regs, syscall_get_nr(current, regs));

	return 1;
}

void do_syscall_trace_leave(struct pt_regs *regs)