From d70c41ddad5a1cde7c978a65370809abc2eba508 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 5 Feb 2015 23:43:06 +0000 Subject: [PATCH] x86, x32, x86_64: print SECCOMP_RET_ERRNO filtered syscalls This is required to process SECCOMP_RET_ERRNO filtered syscalls on systems where linux kernel does not change the syscall number to -1. * syscall.c (is_negated_errno): Move before syscall_fixup_on_sysenter. (syscall_fixup_on_sysenter) [I386 || X32 || X86_64] : Use it to check AX register. --- syscall.c | 98 +++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/syscall.c b/syscall.c index c5681e27..0d1c97ec 100644 --- a/syscall.c +++ b/syscall.c @@ -1593,6 +1593,52 @@ get_scno(struct tcb *tcp) return 1; } +/* + * Cannot rely on __kernel_[u]long_t being defined, + * it is quite a recent feature of . + */ +#ifdef __kernel_long_t +typedef __kernel_long_t kernel_long_t; +typedef __kernel_ulong_t kernel_ulong_t; +#else +# ifdef X32 +typedef long long kernel_long_t; +typedef unsigned long long kernel_ulong_t; +# else +typedef long kernel_long_t; +typedef unsigned long kernel_ulong_t; +# endif +#endif + +/* + * Check the syscall return value register value for whether it is + * a negated errno code indicating an error, or a success return value. + */ +static inline bool +is_negated_errno(kernel_ulong_t val) +{ + kernel_ulong_t max = -(kernel_long_t) nerrnos; + +#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 + if (current_wordsize < sizeof(val)) { + val = (uint32_t) val; + max = (uint32_t) max; + } +#elif defined X32 + /* + * current_wordsize is 4 even in personality 0 (native X32) + * but truncation _must not_ be done in it. + * can't check current_wordsize here! + */ + if (current_personality != 0) { + val = (uint32_t) val; + max = (uint32_t) max; + } +#endif + + return val > max; +} + /* Called at each syscall entry. * Returns: * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently. @@ -1611,7 +1657,7 @@ syscall_fixup_on_sysenter(struct tcb *tcp) * that sets orig_eax to -1 in some versions of linux kernel. */ if (i386_regs.orig_eax != -1 && - i386_regs.eax != -ENOSYS) { + !is_negated_errno(i386_regs.eax)) { if (debug_flag) fprintf(stderr, "not a syscall entry (eax = %ld, orig_eax = %ld)\n", @@ -1626,7 +1672,7 @@ syscall_fixup_on_sysenter(struct tcb *tcp) */ if (x86_io.iov_len == sizeof(i386_regs)) { if ((int) i386_regs.orig_eax != -1 && - (int) i386_regs.eax != -ENOSYS) { + !is_negated_errno(i386_regs.eax)) { if (debug_flag) fprintf(stderr, "not a syscall entry (eax = %d, orig_eax = %d)\n", @@ -1636,7 +1682,7 @@ syscall_fixup_on_sysenter(struct tcb *tcp) } } else { if ((long long) x86_64_regs.orig_rax != -1 && - (long long) x86_64_regs.rax != -ENOSYS) { + !is_negated_errno(x86_64_regs.rax)) { if (debug_flag) fprintf(stderr, "not a syscall entry (rax = %lld, orig_rax = %lld)\n", @@ -2215,52 +2261,6 @@ syscall_fixup_on_sysexit(struct tcb *tcp) #endif } -/* - * Cannot rely on __kernel_[u]long_t being defined, - * it is quite a recent feature of . - */ -#ifdef __kernel_long_t -typedef __kernel_long_t kernel_long_t; -typedef __kernel_ulong_t kernel_ulong_t; -#else -# ifdef X32 -typedef long long kernel_long_t; -typedef unsigned long long kernel_ulong_t; -# else -typedef long kernel_long_t; -typedef unsigned long kernel_ulong_t; -# endif -#endif - -/* - * Check the syscall return value register value for whether it is - * a negated errno code indicating an error, or a success return value. - */ -static inline bool -is_negated_errno(kernel_ulong_t val) -{ - kernel_ulong_t max = -(kernel_long_t) nerrnos; - -#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 - if (current_wordsize < sizeof(val)) { - val = (uint32_t) val; - max = (uint32_t) max; - } -#elif defined X32 - /* - * current_wordsize is 4 even in personality 0 (native X32) - * but truncation _must not_ be done in it. - * can't check current_wordsize here! - */ - if (current_personality != 0) { - val = (uint32_t) val; - max = (uint32_t) max; - } -#endif - - return val > max; -} - /* Returns: * 1: ok, continue in trace_syscall_exiting(). * -1: error, trace_syscall_exiting() should print error indicator -- 2.40.0