[PATCH v13 1/6] nptl: Add rseq auxvals
Mathieu Desnoyers
mathieu.desnoyers@efficios.com
Tue Nov 19 19:49:06 GMT 2024
On 2024-11-19 13:58, Michael Jeanson wrote:
> Get the rseq feature size and alignment requirement from the auxiliary
> vector for use inside the dynamic loader. Use '__rseq_size' directly to
> store the feature size, if the main thread registration fails or is
Use period ("feature size. If ...")
> disabled by tunable, reset the value to 0.
>
> This will be used in the TLS block allocator to compute the size and
> alignment of the rseq area block for the extended ABI support.
>
> Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
> ---
> Changes since v12:
> - Set _rseq_size to 0 on registration failure
> Changes since v11:
> - Removed _dl_rseq_feature_size, use __rseq_size instead
> - Replace GLRO(dl_rseq_align) with a hidden global variable _rseq_align
> ---
> sysdeps/nptl/dl-tls_init_tp.c | 11 +++++++++--
> sysdeps/unix/sysv/linux/dl-parse_auxv.h | 13 +++++++++++++
> sysdeps/unix/sysv/linux/rseq-internal.h | 24 +++++++++++++++++++++---
> sysdeps/unix/sysv/linux/tst-rseq.c | 6 ++++--
> sysdeps/unix/sysv/linux/tst-rseq.h | 1 +
> 5 files changed, 48 insertions(+), 7 deletions(-)
>
> diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
> index 7803e19fd1..2a338bd7df 100644
> --- a/sysdeps/nptl/dl-tls_init_tp.c
> +++ b/sysdeps/nptl/dl-tls_init_tp.c
> @@ -46,6 +46,8 @@ rtld_mutex_dummy (pthread_mutex_t *lock)
>
> const unsigned int __rseq_flags;
>
> +size_t _rseq_align attribute_hidden;
> +
> void
> __tls_pre_init_tp (void)
> {
> @@ -99,10 +101,15 @@ __tls_init_tp (void)
> }
>
> {
> + /* If the registration fails or is disabled by tunable, the public
> + '__rseq_size' will be set '0' regardless of the feature size of the
"set to '0'"
> + allocated rseq area. An rseq area of at least 32 bytes is always
> + allocated since application code is allowed to check the status of the
> + rseq registration by reading the content of the 'cpu_id' field. */
> bool do_rseq = true;
> do_rseq = TUNABLE_GET (rseq, int, NULL);
> - if (rseq_register_current_thread (pd, do_rseq))
> - _rseq_size = RSEQ_AREA_SIZE_INITIAL_USED;
> + if (!rseq_register_current_thread (pd, do_rseq))
> + _rseq_size = 0;
ok
>
> #ifdef RSEQ_SIG
> /* This should be a compile-time constant, but the current
> diff --git a/sysdeps/unix/sysv/linux/dl-parse_auxv.h b/sysdeps/unix/sysv/linux/dl-parse_auxv.h
> index ea2a58ecb1..5a0ef0ae2a 100644
> --- a/sysdeps/unix/sysv/linux/dl-parse_auxv.h
> +++ b/sysdeps/unix/sysv/linux/dl-parse_auxv.h
> @@ -21,6 +21,7 @@
> #include <fpu_control.h>
> #include <ldsodefs.h>
> #include <link.h>
> +#include <rseq-internal.h>
>
> typedef ElfW(Addr) dl_parse_auxv_t[AT_MINSIGSTKSZ + 1];
>
> @@ -59,5 +60,17 @@ void _dl_parse_auxv (ElfW(auxv_t) *av, dl_parse_auxv_t auxv_values)
> GLRO(dl_sysinfo) = auxv_values[AT_SYSINFO];
> #endif
>
> + /* Get the rseq feature size, with a minimum of RSEQ_AREA_SIZE_INITIAL_USED
> + (20) for kernels that don't have AT_RSEQ_FEATURE_SIZE. Limit the feature
> + size to RSEQ_AREA_SIZE_MAX_USED (28) which fits the rseq area in 'struct
> + pthread' and represents the maximum feature size of currently released
> + kernels. Since no kernels currently cross the 32 bytes of the original
> + ABI, the semantics of a feature size of 32 or more are still undetermined.
> + */
> + _rseq_size = MIN (MAX (auxv_values[AT_RSEQ_FEATURE_SIZE],
> + RSEQ_AREA_SIZE_INITIAL_USED),
> + RSEQ_AREA_SIZE_MAX_USED);
> + _rseq_align = MAX (auxv_values[AT_RSEQ_ALIGN], RSEQ_MIN_ALIGN);
ok
> +
> DL_PLATFORM_AUXV
> }
> diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
> index 37a8f630b6..4bcb4370f7 100644
> --- a/sysdeps/unix/sysv/linux/rseq-internal.h
> +++ b/sysdeps/unix/sysv/linux/rseq-internal.h
> @@ -25,13 +25,31 @@
> #include <stdio.h>
> #include <sys/rseq.h>
>
> -/* 32 is the initially required value for the area size. The
> - actually used rseq size may be less (20 bytes initially). */
> +/* Minimum size of the rseq area allocation required by the syscall. The
> + actually used rseq feature size may be less (20 bytes initially). */
> #define RSEQ_AREA_SIZE_INITIAL 32
> +
> +/* Minimum used feature size of the rseq area. */
> #define RSEQ_AREA_SIZE_INITIAL_USED 20
>
> -/* The variables are in .data.relro but are not yet write-protected. */
> +/* Maximum currently used feature size of the rseq area. */
> +#define RSEQ_AREA_SIZE_MAX_USED 28
> +
> +/* Minimum alignment of the rseq area. */
> +#define RSEQ_MIN_ALIGN 32
> +
> +/* Alignment requirement of the rseq area.
> + Populated from the auxiliary vector with a minimum of '32'.
> + In .data.relro but not yet write-protected. */
> +extern size_t _rseq_align attribute_hidden;
> +
> +/* Size of the active features in the rseq area.
> + Populated from the auxiliary vector with a minimum of '20'.
> + In .data.relro but not yet write-protected. */
> extern unsigned int _rseq_size attribute_hidden;
> +
> +/* Offset from the thread pointer to the rseq area.
> + In .data.relro but not yet write-protected. */
> extern ptrdiff_t _rseq_offset attribute_hidden;
ok
>
> #ifdef RSEQ_SIG
> diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c
> index 08a9533130..d1ae16b953 100644
> --- a/sysdeps/unix/sysv/linux/tst-rseq.c
> +++ b/sysdeps/unix/sysv/linux/tst-rseq.c
> @@ -38,13 +38,15 @@ static void
> do_rseq_main_test (void)
> {
> struct pthread *pd = THREAD_SELF;
> + size_t rseq_feature_size = MIN (MAX (getauxval (AT_RSEQ_FEATURE_SIZE),
> + RSEQ_AREA_SIZE_INITIAL_USED),
> + RSEQ_AREA_SIZE_MAX_USED);
>
> TEST_VERIFY_EXIT (rseq_thread_registered ());
> TEST_COMPARE (__rseq_flags, 0);
> TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset
> == (char *) &pd->rseq_area);
> - /* The current implementation only supports the initial size. */
> - TEST_COMPARE (__rseq_size, 20);
> + TEST_COMPARE (__rseq_size, rseq_feature_size);
ok
> }
>
> static void
> diff --git a/sysdeps/unix/sysv/linux/tst-rseq.h b/sysdeps/unix/sysv/linux/tst-rseq.h
> index dc603327d3..7f82554e83 100644
> --- a/sysdeps/unix/sysv/linux/tst-rseq.h
> +++ b/sysdeps/unix/sysv/linux/tst-rseq.h
> @@ -23,6 +23,7 @@
> #include <syscall.h>
> #include <sys/rseq.h>
> #include <tls.h>
> +#include <rseq-internal.h>
I suspect this is mostly used for the RSEQ_AREA_SIZE_INITIAL_USED and
RSEQ_AREA_SIZE_MAX_USED in tst-rseq.c. OK.
After applying the small changes identified above, feel free to add
my:
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thanks!
Mathieu
>
> static inline bool
> rseq_thread_registered (void)
--
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com
More information about the Libc-alpha
mailing list