[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