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.
diff --git a/syscall.c b/syscall.c
index c5681e2..0d1c97e 100644
--- a/syscall.c
+++ b/syscall.c
@@ -1593,6 +1593,52 @@
return 1;
}
+/*
+ * Cannot rely on __kernel_[u]long_t being defined,
+ * it is quite a recent feature of <asm/posix_types.h>.
+ */
+#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 @@
* 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 @@
*/
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 @@
}
} 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 @@
#endif
}
-/*
- * Cannot rely on __kernel_[u]long_t being defined,
- * it is quite a recent feature of <asm/posix_types.h>.
- */
-#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