From e04c989eb785af61d2895d76d38c09166296f9c5 Mon Sep 17 00:00:00 2001 From: Mickaël Salaün Date: Tue, 29 Dec 2015 21:35:44 +0100 Subject: um: Fix ptrace GETREGS/SETREGS bugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fix two related bugs: * PTRACE_GETREGS doesn't get the right orig_ax (syscall) value * PTRACE_SETREGS can't set the orig_ax value (erased by initial value) Get rid of the now useless and error-prone get_syscall(). Fix inconsistent behavior in the ptrace implementation for i386 when updating orig_eax automatically update the syscall number as well. This is now updated in handle_syscall(). Signed-off-by: Mickaël Salaün Cc: Jeff Dike Cc: Richard Weinberger Cc: Thomas Gleixner Cc: Kees Cook Cc: Andy Lutomirski Cc: Will Drewry Cc: Thomas Meyer Cc: Nicolas Iooss Cc: Anton Ivanov Cc: Meredydd Luff Cc: David Drysdale Signed-off-by: Richard Weinberger Acked-by: Kees Cook --- arch/um/include/shared/os.h | 1 - arch/um/kernel/skas/syscall.c | 26 ++++++++++++++------------ arch/um/os-Linux/skas/process.c | 7 ------- 3 files changed, 14 insertions(+), 20 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index 7a04ddd85334..de5d572225f3 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -284,7 +284,6 @@ extern void initial_thread_cb_skas(void (*proc)(void *), void *arg); extern void halt_skas(void); extern void reboot_skas(void); -extern int get_syscall(struct uml_pt_regs *regs); /* irq.c */ extern int os_waiting_for_events(struct irq_fd *active_fds); diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index 1683b8efdfda..6cadce761bcf 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c @@ -7,29 +7,31 @@ #include #include #include +#include #include -#include void handle_syscall(struct uml_pt_regs *r) { struct pt_regs *regs = container_of(r, struct pt_regs, regs); - long result; int syscall; - if (syscall_trace_enter(regs)) { - result = -ENOSYS; + /* Initialize the syscall number and default return value. */ + UPT_SYSCALL_NR(r) = PT_SYSCALL_NR(r->gp); + PT_REGS_SET_SYSCALL_RETURN(regs, -ENOSYS); + + if (syscall_trace_enter(regs)) goto out; - } - syscall = get_syscall(r); + /* Update the syscall number after orig_ax has potentially been updated + * with ptrace. + */ + UPT_SYSCALL_NR(r) = PT_SYSCALL_NR(r->gp); + syscall = UPT_SYSCALL_NR(r); - if ((syscall > __NR_syscall_max) || syscall < 0) - result = -ENOSYS; - else - result = EXECUTE_SYSCALL(syscall, regs); + if (syscall >= 0 && syscall <= __NR_syscall_max) + PT_REGS_SET_SYSCALL_RETURN(regs, + EXECUTE_SYSCALL(syscall, regs)); out: - PT_REGS_SET_SYSCALL_RETURN(regs, result); - syscall_trace_leave(regs); } diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index b856c66ebd3a..23025d645160 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -172,13 +172,6 @@ static void handle_trap(int pid, struct uml_pt_regs *regs, handle_syscall(regs); } -int get_syscall(struct uml_pt_regs *regs) -{ - UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp); - - return UPT_SYSCALL_NR(regs); -} - extern char __syscall_stub_start[]; static int userspace_tramp(void *stack) -- cgit v1.2.3-59-g8ed1b