]> granicus.if.org Git - strace/commitdiff
hppa: workaround kernel bug in syscall number tampering
authorDmitry V. Levin <ldv@altlinux.org>
Sun, 17 Feb 2019 00:10:26 +0000 (00:10 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Sun, 17 Feb 2019 00:10:26 +0000 (00:10 +0000)
Linux kernel commit v4.6-rc2~20^2 introduced a regression:
when tracer changes syscall number to -1, the kernel fails
to initialize %r28 with -ENOSYS and subsequently fails
to return the error code of the failed syscall to userspace.
Workaround this by initializing %r28 ourselves.

* linux/arch_defs_.h (ARCH_NEEDS_SET_ERROR_FOR_SCNO_TAMPERING): Define
to 0.
* linux/hppa/arch_defs_.h (ARCH_NEEDS_SET_ERROR_FOR_SCNO_TAMPERING):
Define to 1.
* syscall.c (tamper_with_syscall_entering)
[ARCH_NEEDS_SET_ERROR_FOR_SCNO_TAMPERING]: When changing syscall number
to -1, set the return value as well.

linux/arch_defs_.h
linux/hppa/arch_defs_.h
syscall.c

index f4b3a7f7be04508d7ee89337ba6a8e61159da4e2..5a7bb4d9c4cd811230398fba7d22dfb526523dc3 100644 (file)
@@ -42,3 +42,7 @@
 #ifndef CAN_ARCH_BE_COMPAT_ON_64BIT_KERNEL
 # define CAN_ARCH_BE_COMPAT_ON_64BIT_KERNEL 0
 #endif
+
+#ifndef ARCH_NEEDS_SET_ERROR_FOR_SCNO_TAMPERING
+# define ARCH_NEEDS_SET_ERROR_FOR_SCNO_TAMPERING 0
+#endif
index a237049e8ab2d8c6679d5e0c1cca985301206c2a..db674682b441a6ef492b1a364f375d24d6d11159 100644 (file)
@@ -6,3 +6,11 @@
  */
 
 #define HAVE_ARCH_SA_RESTORER 0
+/*
+ * Linux kernel commit v4.6-rc2~20^2 introduced a regression:
+ * when tracer changes syscall number to -1, the kernel fails
+ * to initialize %r28 with -ENOSYS and subsequently fails
+ * to return the error code of the failed syscall to userspace.
+ * Workaround this by initializing %r28 ourselves.
+ */
+#define ARCH_NEEDS_SET_ERROR_FOR_SCNO_TAMPERING 1
index d36b8433a91741e48cfa69627024dbfc3b7c5432..552f0826b5fca7cb7cc946989dec9202d7485369 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -496,6 +496,20 @@ tamper_with_syscall_entering(struct tcb *tcp, unsigned int *signo)
                                tcp->flags |= TCB_TAMPERED;
                                if (scno != -1)
                                        tcp->flags |= TCB_TAMPERED_NO_FAIL;
+#if ARCH_NEEDS_SET_ERROR_FOR_SCNO_TAMPERING
+                               /*
+                                * So far it's just a workaround for hppa,
+                                * but let's pretend it could be used elsewhere.
+                                */
+                               else {
+                                       kernel_long_t rval =
+                                               (opts->data.flags & INJECT_F_RETVAL) ?
+                                               ENOSYS : retval_get(opts->data.rval_idx);
+
+                                       tcp->u_error = 0; /* force reset */
+                                       set_error(tcp, rval);
+                               }
+#endif
                        }
                }
                if (opts->data.flags & INJECT_F_DELAY_ENTER)