[PATCH] Linux: Inhibit tail calls in cancellable system calls
Florian Weimer
fweimer@redhat.com
Fri Mar 21 13:01:35 GMT 2025
Without this change, the system call wrapper function is not visible
on the stack at the time of the system call, which causes problems
for interception tools such as valgrind.
Enhances commit 89b53077d2a58f00e7debdfe58afabe953dac60d ("nptl: Fix
Race conditions in pthread cancellation [BZ#12683]").
Tested on i686-linux-gnu, powerpc64le-linux-gnu, x86_64-linux-gnu.
(We're still discussing if valgrind needs this, but if it does, here's a
patch.)
---
sysdeps/unix/sysdep.h | 57 ++++++++++++++++++++++++++++++++-------------------
1 file changed, 36 insertions(+), 21 deletions(-)
diff --git a/sysdeps/unix/sysdep.h b/sysdeps/unix/sysdep.h
index 2cc98725c3..8f1e4fc4f9 100644
--- a/sysdeps/unix/sysdep.h
+++ b/sysdeps/unix/sysdep.h
@@ -166,30 +166,45 @@ long int __syscall_cancel (__syscall_arg_t arg1, __syscall_arg_t arg2,
__SYSCALL_CANCEL7_ARG_DEF
__syscall_arg_t nr) attribute_hidden;
+/* Inhibit tail call optimization, so that the stack frame of the
+ system-call-implementing function is visible at the time of the
+ system call. */
+#define __syscall_cancel_barrier(...) \
+ ({ \
+ long int __syscall_cancel_result = __syscall_cancel (__VA_ARGS__); \
+ asm volatile ("" ::: "memory"); \
+ __syscall_cancel_result; \
+ })
+
#define __SYSCALL_CANCEL0(name) \
- __syscall_cancel (0, 0, 0, 0, 0, 0, __SYSCALL_CANCEL7_ARG __NR_##name)
+ __syscall_cancel_barrier (0, 0, 0, 0, 0, 0, \
+ __SYSCALL_CANCEL7_ARG __NR_##name)
#define __SYSCALL_CANCEL1(name, a1) \
- __syscall_cancel (__SSC (a1), 0, 0, 0, 0, 0, \
- __SYSCALL_CANCEL7_ARG __NR_##name)
-#define __SYSCALL_CANCEL2(name, a1, a2) \
- __syscall_cancel (__SSC (a1), __SSC (a2), 0, 0, 0, 0, \
- __SYSCALL_CANCEL7_ARG __NR_##name)
-#define __SYSCALL_CANCEL3(name, a1, a2, a3) \
- __syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), 0, 0, 0, \
- __SYSCALL_CANCEL7_ARG __NR_##name)
-#define __SYSCALL_CANCEL4(name, a1, a2, a3, a4) \
- __syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), \
- __SSC(a4), 0, 0, __SYSCALL_CANCEL7_ARG __NR_##name)
-#define __SYSCALL_CANCEL5(name, a1, a2, a3, a4, a5) \
- __syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), __SSC(a4), \
- __SSC (a5), 0, __SYSCALL_CANCEL7_ARG __NR_##name)
-#define __SYSCALL_CANCEL6(name, a1, a2, a3, a4, a5, a6) \
- __syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), __SSC (a4), \
- __SSC (a5), __SSC (a6), __SYSCALL_CANCEL7_ARG \
- __NR_##name)
+ __syscall_cancel_barrier (__SSC (a1), 0, 0, 0, 0, 0, \
+ __SYSCALL_CANCEL7_ARG __NR_##name)
+#define __SYSCALL_CANCEL2(name, a1, a2) \
+ __syscall_cancel_barrier (__SSC (a1), __SSC (a2), 0, 0, 0, 0, \
+ __SYSCALL_CANCEL7_ARG __NR_##name)
+#define __SYSCALL_CANCEL3(name, a1, a2, a3) \
+ __syscall_cancel_barrier (__SSC (a1), __SSC (a2), __SSC (a3), \
+ 0, 0, 0, __SYSCALL_CANCEL7_ARG __NR_##name)
+#define __SYSCALL_CANCEL4(name, a1, a2, a3, a4) \
+ __syscall_cancel_barrier (__SSC (a1), __SSC (a2), __SSC (a3), \
+ __SSC(a4), 0, 0, \
+ __SYSCALL_CANCEL7_ARG __NR_##name)
+#define __SYSCALL_CANCEL5(name, a1, a2, a3, a4, a5) \
+ __syscall_cancel_barrier (__SSC (a1), __SSC (a2), __SSC (a3), \
+ __SSC(a4), __SSC (a5), 0, \
+ __SYSCALL_CANCEL7_ARG __NR_##name)
+#define __SYSCALL_CANCEL6(name, a1, a2, a3, a4, a5, a6) \
+ __syscall_cancel_barrier (__SSC (a1), __SSC (a2), __SSC (a3), \
+ __SSC (a4), __SSC (a5), __SSC (a6), \
+ __SYSCALL_CANCEL7_ARG \
+ __NR_##name)
#define __SYSCALL_CANCEL7(name, a1, a2, a3, a4, a5, a6, a7) \
- __syscall_cancel (__SSC (a1), __SSC (a2), __SSC (a3), __SSC (a4), \
- __SSC (a5), __SSC (a6), __SSC (a7), __NR_##name)
+ __syscall_cancel_barrier (__SSC (a1), __SSC (a2), __SSC (a3), \
+ __SSC (a4), __SSC (a5), __SSC (a6), \
+ __SSC (a7), __NR_##name)
#define __SYSCALL_CANCEL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n
#define __SYSCALL_CANCEL_NARGS(...) \
base-commit: 3e2be87832781a29ed67f38f87c1ce3dd4c1b866
More information about the Libc-alpha
mailing list