From 8e398b6c4020fb2d33a5b3e40271ebf63199b891 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 5 Feb 2015 19:31:13 +0000 Subject: [PATCH] x86, x32, x86_64: do not skip syscall number -1 Syscall number -1 might be a side effect of SECCOMP_RET_ERRNO filtering. * syscall.c (syscall_fixup_on_sysenter) [I386 || X32 || X86_64]: Do not skip syscalls that have number -1. --- syscall.c | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/syscall.c b/syscall.c index 7f52cc8e..78f8f15c 100644 --- a/syscall.c +++ b/syscall.c @@ -1605,24 +1605,43 @@ syscall_fixup_on_sysenter(struct tcb *tcp) { /* A common case of "not a syscall entry" is post-execve SIGTRAP */ #if defined(I386) - if (i386_regs.eax != -ENOSYS) { + /* + * Syscall number -1 requires special treatment. + * On X86, it might be a side effect of SECCOMP_RET_ERRNO filtering + * that sets orig_eax to -1 in some versions of linux kernel. + */ + if (i386_regs.orig_eax != -1 && + i386_regs.eax != -ENOSYS) { if (debug_flag) - fprintf(stderr, "not a syscall entry (eax = %ld)\n", i386_regs.eax); + fprintf(stderr, + "not a syscall entry (eax = %ld, orig_eax = %ld)\n", + i386_regs.eax, i386_regs.orig_eax); return 0; } #elif defined(X86_64) || defined(X32) - { - long rax; - if (x86_io.iov_len == sizeof(i386_regs)) { - /* Sign extend from 32 bits */ - rax = (int32_t)i386_regs.eax; - } else { - /* Note: in X32 build, this truncates 64 to 32 bits */ - rax = x86_64_regs.rax; + /* + * Syscall number -1 requires special treatment. + * On X86_64/X32, it might be a side effect of SECCOMP_RET_ERRNO + * filtering that sets orig_rax to -1 in some versions of linux kernel. + */ + if (x86_io.iov_len == sizeof(i386_regs)) { + if ((int) i386_regs.orig_eax != -1 && + (int) i386_regs.eax != -ENOSYS) { + if (debug_flag) + fprintf(stderr, + "not a syscall entry (eax = %d, orig_eax = %d)\n", + (int) i386_regs.eax, + (int) i386_regs.orig_eax); + return 0; } - if (rax != -ENOSYS) { + } else { + if ((long long) x86_64_regs.orig_rax != -1 && + (long long) x86_64_regs.rax != -ENOSYS) { if (debug_flag) - fprintf(stderr, "not a syscall entry (rax = %ld)\n", rax); + fprintf(stderr, + "not a syscall entry (rax = %lld, orig_rax = %lld)\n", + (long long) x86_64_regs.rax, + (long long) x86_64_regs.orig_rax); return 0; } } -- 2.40.0