[PATCH] Linux: Inhibit tail calls in cancellable system calls
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Fri Mar 21 14:18:45 GMT 2025
On 21/03/25 10:01, Florian Weimer wrote:
> 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.)
>
Another option would to inline __internal_syscall_cancel and __syscall_cancel [1],
it increases the code size a bit but it mimics how the cancellation entrypoint
were implemented before 89b53077d2a58f00e.
[1] https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/azanella/cancel-wrappers-inline
> ---
> 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