um/ptrace: Fix the syscall number update after a ptrace

Update the syscall number after each PTRACE_SETREGS on ORIG_*AX.

This is needed to get the potentially altered syscall number in the
seccomp filters after RET_TRACE.

This fix four seccomp_bpf tests:
> [ RUN      ] TRACE_syscall.skip_after_RET_TRACE
> seccomp_bpf.c:1560:TRACE_syscall.skip_after_RET_TRACE:Expected -1 (18446744073709551615) == syscall(39) (26)
> seccomp_bpf.c:1561:TRACE_syscall.skip_after_RET_TRACE:Expected 1 (1) == (*__errno_location ()) (22)
> [     FAIL ] TRACE_syscall.skip_after_RET_TRACE
> [ RUN      ] TRACE_syscall.kill_after_RET_TRACE
> TRACE_syscall.kill_after_RET_TRACE: Test exited normally instead of by signal (code: 1)
> [     FAIL ] TRACE_syscall.kill_after_RET_TRACE
> [ RUN      ] TRACE_syscall.skip_after_ptrace
> seccomp_bpf.c:1622:TRACE_syscall.skip_after_ptrace:Expected -1 (18446744073709551615) == syscall(39) (26)
> seccomp_bpf.c:1623:TRACE_syscall.skip_after_ptrace:Expected 1 (1) == (*__errno_location ()) (22)
> [     FAIL ] TRACE_syscall.skip_after_ptrace
> [ RUN      ] TRACE_syscall.kill_after_ptrace
> TRACE_syscall.kill_after_ptrace: Test exited normally instead of by signal (code: 1)
> [     FAIL ] TRACE_syscall.kill_after_ptrace

Fixes: 26703c636c ("um/ptrace: run seccomp after ptrace")

Signed-off-by: Mickaël Salaün <mic@digikod.net>
Acked-by: Kees Cook <keescook@chromium.org>
Cc: Jeff Dike <jdike@addtoit.com>
Cc: Richard Weinberger <richard@nod.at>
Cc: James Morris <jmorris@namei.org>
Cc: user-mode-linux-devel@lists.sourceforge.net
Signed-off-by: James Morris <james.l.morris@oracle.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
Mickaël Salaün 2016-08-01 23:01:56 +02:00 committed by Kees Cook
parent 972939e285
commit ce29856a5e
3 changed files with 7 additions and 5 deletions

View File

@ -27,12 +27,7 @@ void handle_syscall(struct uml_pt_regs *r)
if (secure_computing(NULL) == -1) if (secure_computing(NULL) == -1)
goto out; goto out;
/* 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); syscall = UPT_SYSCALL_NR(r);
if (syscall >= 0 && syscall <= __NR_syscall_max) if (syscall >= 0 && syscall <= __NR_syscall_max)
PT_REGS_SET_SYSCALL_RETURN(regs, PT_REGS_SET_SYSCALL_RETURN(regs,
EXECUTE_SYSCALL(syscall, regs)); EXECUTE_SYSCALL(syscall, regs));

View File

@ -84,7 +84,10 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
case EAX: case EAX:
case EIP: case EIP:
case UESP: case UESP:
break;
case ORIG_EAX: case ORIG_EAX:
/* Update the syscall number. */
UPT_SYSCALL_NR(&child->thread.regs.regs) = value;
break; break;
case FS: case FS:
if (value && (value & 3) != 3) if (value && (value & 3) != 3)

View File

@ -78,7 +78,11 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
case RSI: case RSI:
case RDI: case RDI:
case RBP: case RBP:
break;
case ORIG_RAX: case ORIG_RAX:
/* Update the syscall number. */
UPT_SYSCALL_NR(&child->thread.regs.regs) = value;
break; break;
case FS: case FS: