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.
#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
*/
#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
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)