Do not watch for post-execve SIGTRAP if PTRACE_O_TRACEEXEC is enabled

If PTRACE_O_TRACEEXEC option is enabled, then post-execve SIGTRAPs are
suppressed and we can safely skip -ENOSYS heuristics.  This partially
reverts commits v4.9-258-g8e398b6 and v4.9-261-gd70c41d.

* syscall.c (syscall_fixup_on_sysenter): Skip if PTRACE_O_TRACEEXEC
flag is set in ptrace_setoptions.  Remove all SECCOMP_RET_ERRNO
workarounds as they are not needed when PTRACE_O_TRACEEXEC is not
supported by the kernel.
This commit is contained in:
Дмитрий Левин 2015-02-07 23:26:44 +00:00
parent 2cd488b259
commit 85dc4a11c7

View File

@ -1654,45 +1654,38 @@ is_negated_errno(kernel_ulong_t val)
static int
syscall_fixup_on_sysenter(struct tcb *tcp)
{
/* A common case of "not a syscall entry" is post-execve SIGTRAP */
#if defined(I386)
/* Do we have post-execve SIGTRAP suppressed? */
if (ptrace_setoptions & PTRACE_O_TRACEEXEC)
return 1;
/*
* 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.
* No, unfortunately. Apply -ENOSYS heuristics.
* We don't have to workaround SECCOMP_RET_ERRNO side effects
* because any kernel with SECCOMP_RET_ERRNO support surely
* implements PTRACE_O_TRACEEXEC.
*/
if (i386_regs.orig_eax != -1 &&
!is_negated_errno(i386_regs.eax)) {
#if defined(I386)
if (i386_regs.eax != -ENOSYS) {
if (debug_flag)
fprintf(stderr,
"not a syscall entry (eax = %ld, orig_eax = %ld)\n",
i386_regs.eax, i386_regs.orig_eax);
fprintf(stderr, "not a syscall entry (eax = %ld)\n",
i386_regs.eax);
return 0;
}
#elif defined(X86_64) || defined(X32)
/*
* 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 &&
!is_negated_errno(i386_regs.eax)) {
if ((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);
"not a syscall entry (eax = %d)\n",
(int) i386_regs.eax);
return 0;
}
} else {
if ((long long) x86_64_regs.orig_rax != -1 &&
!is_negated_errno(x86_64_regs.rax)) {
if ((long long) x86_64_regs.rax != -ENOSYS) {
if (debug_flag)
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);
"not a syscall entry (rax = %lld)\n",
(long long) x86_64_regs.rax);
return 0;
}
}