diff options
| author | Max Filippov <jcmvbkbc@gmail.com> | 2019-11-29 14:54:06 -0800 | 
|---|---|---|
| committer | Max Filippov <jcmvbkbc@gmail.com> | 2019-11-29 15:47:54 -0800 | 
| commit | 02ce94c229251555ac726ecfebe3458ef5905fa9 (patch) | |
| tree | 19e5ae21b866a950e0b42c5bc8655f5d8d1b0ef5 /arch/xtensa | |
| parent | ba9c1d65991a8be2e160447dd06eb803cbb9ba61 (diff) | |
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 <jcmvbkbc@gmail.com>
Diffstat (limited to 'arch/xtensa')
| -rw-r--r-- | arch/xtensa/kernel/entry.S | 4 | ||||
| -rw-r--r-- | arch/xtensa/kernel/ptrace.c | 18 | 
2 files changed, 18 insertions, 4 deletions
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 59af494d9940..138469e26560 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -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: diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index b964f0b2d886..145742d70a9f 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -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)  | 
