diff mbox series

Linux: Change meaning of __rseq_size slightly

Message ID 87wmlx9sjh.fsf@oldenburg.str.redhat.com
State New
Headers show
Series Linux: Change meaning of __rseq_size slightly | expand

Commit Message

Florian Weimer July 7, 2024, 2:37 p.m. UTC
It is now the active area of struct rseq (so 20 initially), not
the full struct size including padding at the end (32 initially).
Introduce a new symbol version for __rseq_area, so that
applications can rely on the new semantics.

Update misc/tst-rseq to print some additional diagnostics.

This replaces Michael's __rseq_feature_size patch.  I prefer this
approach because it avoids confusion with having three different sizes
(__rseq_size, __rseq_feature_size, getauxval (AT_RSEQ_FEATURE_SIZE)).
I looked at the __rseq_size usage in CRIU, and it seems to be compatible
as long as the system has full ptrace support.  I do not think we
need a compat symbol that is artificially increased to 32.  We
can do this retroactively if necessary because there is a new symbol
version (so that newly linked applications can depend on the new
semantics).

I hope we can still put this into 2.40.

Tested on aarch64-linux-gnu, i386-linux-gnu, x86_64-linux-gnu.
Built with build-many-glibcs.py.

Thanks,
Florian
---
 NEWS                                               |  3 +++
 manual/threads.texi                                |  8 ++++++--
 sysdeps/nptl/dl-tls_init_tp.c                      |  8 +-------
 sysdeps/unix/sysv/linux/Versions                   |  3 +++
 sysdeps/unix/sysv/linux/aarch64/ld.abilist         |  1 +
 sysdeps/unix/sysv/linux/alpha/ld.abilist           |  1 +
 sysdeps/unix/sysv/linux/arc/ld.abilist             |  1 +
 sysdeps/unix/sysv/linux/arm/be/ld.abilist          |  1 +
 sysdeps/unix/sysv/linux/arm/le/ld.abilist          |  1 +
 sysdeps/unix/sysv/linux/csky/ld.abilist            |  1 +
 sysdeps/unix/sysv/linux/dl-rseq-symbols.S          | 23 +++++++++++++++++++---
 sysdeps/unix/sysv/linux/hppa/ld.abilist            |  1 +
 sysdeps/unix/sysv/linux/i386/ld.abilist            |  1 +
 sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist  |  1 +
 sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist   |  1 +
 sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist     |  1 +
 sysdeps/unix/sysv/linux/microblaze/ld.abilist      |  1 +
 sysdeps/unix/sysv/linux/mips/mips32/ld.abilist     |  1 +
 sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist |  1 +
 sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist |  1 +
 sysdeps/unix/sysv/linux/nios2/ld.abilist           |  1 +
 sysdeps/unix/sysv/linux/or1k/ld.abilist            |  1 +
 .../unix/sysv/linux/powerpc/powerpc32/ld.abilist   |  1 +
 .../sysv/linux/powerpc/powerpc64/be/ld.abilist     |  1 +
 .../sysv/linux/powerpc/powerpc64/le/ld.abilist     |  1 +
 sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist      |  1 +
 sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist      |  1 +
 sysdeps/unix/sysv/linux/rseq-internal.h            | 23 ++++++++++++++++++++--
 sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist    |  1 +
 sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist    |  1 +
 sysdeps/unix/sysv/linux/sh/be/ld.abilist           |  1 +
 sysdeps/unix/sysv/linux/sh/le/ld.abilist           |  1 +
 sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist   |  1 +
 sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist   |  1 +
 sysdeps/unix/sysv/linux/tst-rseq.c                 | 10 +++++++++-
 sysdeps/unix/sysv/linux/x86_64/64/ld.abilist       |  1 +
 sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist      |  1 +
 37 files changed, 93 insertions(+), 15 deletions(-)


base-commit: 9fc639f654dc004736836613be703e6bed0c36a8

Comments

Mathieu Desnoyers July 8, 2024, 12:22 a.m. UTC | #1
On 2024-07-07 10:37, Florian Weimer wrote:
> It is now the active area of struct rseq (so 20 initially), not
> the full struct size including padding at the end (32 initially).
> Introduce a new symbol version for __rseq_area, so that

I guess you mean __rseq_size rather than __rseq_area here ?

> applications can rely on the new semantics.
> 
> Update misc/tst-rseq to print some additional diagnostics.
> 
> This replaces Michael's __rseq_feature_size patch.  I prefer this
> approach because it avoids confusion with having three different sizes
> (__rseq_size, __rseq_feature_size, getauxval (AT_RSEQ_FEATURE_SIZE)).
> I looked at the __rseq_size usage in CRIU, and it seems to be compatible
> as long as the system has full ptrace support.  I do not think we
> need a compat symbol that is artificially increased to 32.  We
> can do this retroactively if necessary because there is a new symbol
> version (so that newly linked applications can depend on the new
> semantics).

I agree, your approach keeps the ABI simple, I like it.

> 
> I hope we can still put this into 2.40.

It would be great if it can make it. :)

If this patch is acceptable for 2.40, should we keep targetting
2.40 for the extensible rseq getauxval() integration or postpone
that part to 2.41 ? AFAIU, once this patch is integrated, the
getauxval() integration will not require any ABI change anymore.

> 
> Tested on aarch64-linux-gnu, i386-linux-gnu, x86_64-linux-gnu.
> Built with build-many-glibcs.py.

Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>

Thanks,

Mathieu
Florian Weimer July 8, 2024, 6:13 a.m. UTC | #2
* Mathieu Desnoyers:

> On 2024-07-07 10:37, Florian Weimer wrote:
>> It is now the active area of struct rseq (so 20 initially), not
>> the full struct size including padding at the end (32 initially).
>> Introduce a new symbol version for __rseq_area, so that
>
> I guess you mean __rseq_size rather than __rseq_area here ?

Right, fixed locally.

> If this patch is acceptable for 2.40, should we keep targetting
> 2.40 for the extensible rseq getauxval() integration or postpone
> that part to 2.41 ? AFAIU, once this patch is integrated, the
> getauxval() integration will not require any ABI change anymore.

I think we don't want to take further changes for 2.40 at this point.

> Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>

Thanks!

Andreas, is this okay from a release manager perspective, too?

Florian
Michael Jeanson July 8, 2024, 2:12 p.m. UTC | #3
On 2024-07-07 10 h 37, Florian Weimer wrote:
> It is now the active area of struct rseq (so 20 initially), not
> the full struct size including padding at the end (32 initially).
> Introduce a new symbol version for __rseq_area, so that
> applications can rely on the new semantics.
> 
> Update misc/tst-rseq to print some additional diagnostics.
> 
> This replaces Michael's __rseq_feature_size patch.  I prefer this
> approach because it avoids confusion with having three different sizes
> (__rseq_size, __rseq_feature_size, getauxval (AT_RSEQ_FEATURE_SIZE)).
> I looked at the __rseq_size usage in CRIU, and it seems to be compatible
> as long as the system has full ptrace support.  I do not think we
> need a compat symbol that is artificially increased to 32.  We
> can do this retroactively if necessary because there is a new symbol
> version (so that newly linked applications can depend on the new
> semantics).

One thing I'm not sure I understand, how would I write an application 
that can be built against any glibc with the '__rseq_symbol' that can 
distinguish between the old semantic of '__rseq_size == 32' and an 
hypothetical new kernel with 32 bytes of rseq features available?

> 
> I hope we can still put this into 2.40.
> 
> Tested on aarch64-linux-gnu, i386-linux-gnu, x86_64-linux-gnu.
> Built with build-many-glibcs.py.
> 
> Thanks,
> Florian
Florian Weimer July 8, 2024, 5:06 p.m. UTC | #4
* Michael Jeanson:

> On 2024-07-07 10 h 37, Florian Weimer wrote:
>> It is now the active area of struct rseq (so 20 initially), not
>> the full struct size including padding at the end (32 initially).
>> Introduce a new symbol version for __rseq_area, so that
>> applications can rely on the new semantics.
>> Update misc/tst-rseq to print some additional diagnostics.
>> This replaces Michael's __rseq_feature_size patch.  I prefer this
>> approach because it avoids confusion with having three different sizes
>> (__rseq_size, __rseq_feature_size, getauxval (AT_RSEQ_FEATURE_SIZE)).
>> I looked at the __rseq_size usage in CRIU, and it seems to be compatible
>> as long as the system has full ptrace support.  I do not think we
>> need a compat symbol that is artificially increased to 32.  We
>> can do this retroactively if necessary because there is a new symbol
>> version (so that newly linked applications can depend on the new
>> semantics).
>
> One thing I'm not sure I understand, how would I write an application
> that can be built against any glibc with the '__rseq_symbol' that can
> distinguish between the old semantic of '__rseq_size == 32' and an
> hypothetical new kernel with 32 bytes of rseq features available?

We don't know for sure because I do not think we have reached a
getauxval (AT_RSEQ_FEATURE_SIZE) value that is larger than 28.  For now,
it is reasonable to assume that if __rseq_size is 32, and getauxval
(AT_RSEQ_FEATURE_SIZE) is 28, then the usable part is 28.  But if
e.g. getauxval (AT_RSEQ_FEATURE_SIZE) is 40 and __rseq_size is still 32,
we don't know if bytes up to 32 are usable.  It could be that the kernel
supports 20 bytes only.

If __rseq_size is 32 and getauxval (AT_RSEQ_FEATURE_SIZE) is zero, the
usable part is 20 bytes long.

If __rseq_size is 0, rseq is not supported.

Otherwise, __rseq_size is usable size.

We discussed this a bit during today's call, and we concluded that this
patch here may not the best possible solution.

1) [your patch] New __rseq_feature_size symbol: Applications using the
   new logic will fail to compile on older glibc.  Compiled on new
   glibc, applications will fail to launch with a GLIBC_2.40 version
   error.

2) [this patch] New symbol version for __rseq_size (same variable as
   before): Compiled on new glibc, applications will fail to launch with
   a GLIBC_2.40 version error.  This is done because they might use the
   new size semantics.  But the application code specific to glibc 2.40
   will compile successfully on glibc 2.39 and earlier, and run, given
   the weird results.  This is not ideal.

3) [no patch, but similar to this patch] Treat this as a bug fix for
   __rseq_size: it should have been 20 initially.  No new symbol
   version, but backport it 2.35 and later.  Given so many distributions
   use stable release branches nowadays, it is likely the fix is
   available to users before they encounter rseq-using applications.

The rules above apply to both 2) & 3).  I'm leaning towards approach 3)
and would do the backports to 2.35 and later.

Thanks,
Florian
Michael Jeanson July 8, 2024, 5:52 p.m. UTC | #5
On 2024-07-08 13 h 06, Florian Weimer wrote:
> * Michael Jeanson:
> 
>> On 2024-07-07 10 h 37, Florian Weimer wrote:
>>> It is now the active area of struct rseq (so 20 initially), not
>>> the full struct size including padding at the end (32 initially).
>>> Introduce a new symbol version for __rseq_area, so that
>>> applications can rely on the new semantics.
>>> Update misc/tst-rseq to print some additional diagnostics.
>>> This replaces Michael's __rseq_feature_size patch.  I prefer this
>>> approach because it avoids confusion with having three different sizes
>>> (__rseq_size, __rseq_feature_size, getauxval (AT_RSEQ_FEATURE_SIZE)).
>>> I looked at the __rseq_size usage in CRIU, and it seems to be compatible
>>> as long as the system has full ptrace support.  I do not think we
>>> need a compat symbol that is artificially increased to 32.  We
>>> can do this retroactively if necessary because there is a new symbol
>>> version (so that newly linked applications can depend on the new
>>> semantics).
>>
>> One thing I'm not sure I understand, how would I write an application
>> that can be built against any glibc with the '__rseq_symbol' that can
>> distinguish between the old semantic of '__rseq_size == 32' and an
>> hypothetical new kernel with 32 bytes of rseq features available?
> 
> We don't know for sure because I do not think we have reached a
> getauxval (AT_RSEQ_FEATURE_SIZE) value that is larger than 28.  For now,
> it is reasonable to assume that if __rseq_size is 32, and getauxval
> (AT_RSEQ_FEATURE_SIZE) is 28, then the usable part is 28.  But if
> e.g. getauxval (AT_RSEQ_FEATURE_SIZE) is 40 and __rseq_size is still 32,
> we don't know if bytes up to 32 are usable.  It could be that the kernel
> supports 20 bytes only.
> 
> If __rseq_size is 32 and getauxval (AT_RSEQ_FEATURE_SIZE) is zero, the
> usable part is 20 bytes long.
> 
> If __rseq_size is 0, rseq is not supported.
> 
> Otherwise, __rseq_size is usable size.
> 
> We discussed this a bit during today's call, and we concluded that this
> patch here may not the best possible solution.
> 
> 1) [your patch] New __rseq_feature_size symbol: Applications using the
>     new logic will fail to compile on older glibc.  Compiled on new
>     glibc, applications will fail to launch with a GLIBC_2.40 version
>     error.
> 
> 2) [this patch] New symbol version for __rseq_size (same variable as
>     before): Compiled on new glibc, applications will fail to launch with
>     a GLIBC_2.40 version error.  This is done because they might use the
>     new size semantics.  But the application code specific to glibc 2.40
>     will compile successfully on glibc 2.39 and earlier, and run, given
>     the weird results.  This is not ideal.
> 
> 3) [no patch, but similar to this patch] Treat this as a bug fix for
>     __rseq_size: it should have been 20 initially.  No new symbol
>     version, but backport it 2.35 and later.  Given so many distributions
>     use stable release branches nowadays, it is likely the fix is
>     available to users before they encounter rseq-using applications.
> 
> The rules above apply to both 2) & 3).  I'm leaning towards approach 3)
> and would do the backports to 2.35 and later.

I also prefer 3) over 2), it could still break early adopters that
expect "__rseq_size >= 32" but it would most likely disable rseq usage
instead of potentially using unimplemented features.
Mathieu Desnoyers July 8, 2024, 5:57 p.m. UTC | #6
On 2024-07-08 13:06, Florian Weimer wrote:
> * Michael Jeanson:
> 
>> On 2024-07-07 10 h 37, Florian Weimer wrote:
>>> It is now the active area of struct rseq (so 20 initially), not
>>> the full struct size including padding at the end (32 initially).
>>> Introduce a new symbol version for __rseq_area, so that
>>> applications can rely on the new semantics.
>>> Update misc/tst-rseq to print some additional diagnostics.
>>> This replaces Michael's __rseq_feature_size patch.  I prefer this
>>> approach because it avoids confusion with having three different sizes
>>> (__rseq_size, __rseq_feature_size, getauxval (AT_RSEQ_FEATURE_SIZE)).
>>> I looked at the __rseq_size usage in CRIU, and it seems to be compatible
>>> as long as the system has full ptrace support.  I do not think we
>>> need a compat symbol that is artificially increased to 32.  We
>>> can do this retroactively if necessary because there is a new symbol
>>> version (so that newly linked applications can depend on the new
>>> semantics).
>>
>> One thing I'm not sure I understand, how would I write an application
>> that can be built against any glibc with the '__rseq_symbol' that can
>> distinguish between the old semantic of '__rseq_size == 32' and an
>> hypothetical new kernel with 32 bytes of rseq features available?
> 
> We don't know for sure because I do not think we have reached a
> getauxval (AT_RSEQ_FEATURE_SIZE) value that is larger than 28.  For now,
> it is reasonable to assume that if __rseq_size is 32, and getauxval
> (AT_RSEQ_FEATURE_SIZE) is 28, then the usable part is 28.

Correct.

>  But if
> e.g. getauxval (AT_RSEQ_FEATURE_SIZE) is 40 and __rseq_size is still 32,
> we don't know if bytes up to 32 are usable.  It could be that the kernel
> supports 20 bytes only.

Based on the rseq system call implementation:

[...]
          * In order to be valid, rseq_len is either the original rseq size, or
          * large enough to contain all supported fields, as communicated to
          * user-space through the ELF auxiliary vector AT_RSEQ_FEATURE_SIZE.
          */
         if (rseq_len < ORIG_RSEQ_SIZE ||
             (rseq_len == ORIG_RSEQ_SIZE && !IS_ALIGNED((unsigned long)rseq, ORIG_RSEQ_SIZE)) ||
             (rseq_len != ORIG_RSEQ_SIZE && (!IS_ALIGNED((unsigned long)rseq, __alignof__(*rseq)) ||
                                             rseq_len < offsetof(struct rseq, end))))
                 return -EINVAL;
[...]
         current->rseq_len = rseq_len;

When rseq_len=32 (ORIG_RSEQ_SIZE), it will be used as-is as current->rseq_len which
is used by rseq_update_cpu_node_id() to "gate" which features are populated.
I have placed a comment in this function to make sure only the fields _after_ 32 bytes
will be conditionally populated:

         if (!user_write_access_begin(rseq, t->rseq_len))
                 goto efault;
         unsafe_put_user(cpu_id, &rseq->cpu_id_start, efault_end);
         unsafe_put_user(cpu_id, &rseq->cpu_id, efault_end);
         unsafe_put_user(node_id, &rseq->node_id, efault_end);
         unsafe_put_user(mm_cid, &rseq->mm_cid, efault_end);
         /*
          * Additional feature fields added after ORIG_RSEQ_SIZE
          * need to be conditionally updated only if
          * t->rseq_len != ORIG_RSEQ_SIZE.
          */
         user_write_access_end();

This effectively ensures that the fields with

   offsetof(field) >= 20 && offsetofend(field) <= 32

are populated when "legacy" registration provides a rseq_len of 32.

Based on the rseq(2) man page found in librseq:

        Structure size
               This  structure  size  needs to be at least 32 bytes.  It can be
               either 32 bytes, or it needs to be large enough to hold the  re‐
               sult of getauxval() invoked with AT_RSEQ_FEATURE_SIZE.  Its size
               is passed as parameter to the rseq() system call.

Arguably, I do not state clearly what happens when the rseq registration has
size=32 and getauxval(AT_RSEQ_FEATURE_SIZE) returns a value larger than 32.

If the kernel getauxval(AT_RSEQ_FEATURE_SIZE) returns 40, it means the kernel
supports 40 bytes of feature. An application observing

__rseq_size == 32 && getauxval(AT_RSEQ_FEATURE_SIZE) == 40

should be able to use the intersection of the rseq area size supported by
libc and the feature fields supported by the kernel.

I fully agree that I should improve the rseq documentation and man page
to clarify this.

> 
> If __rseq_size is 32 and getauxval (AT_RSEQ_FEATURE_SIZE) is zero, the
> usable part is 20 bytes long.

Yes.

> 
> If __rseq_size is 0, rseq is not supported.

Yes.

> 
> Otherwise, __rseq_size is usable size.

Yes.

> 
> We discussed this a bit during today's call, and we concluded that this
> patch here may not the best possible solution.
> 
> 1) [your patch] New __rseq_feature_size symbol: Applications using the
>     new logic will fail to compile on older glibc.  Compiled on new
>     glibc, applications will fail to launch with a GLIBC_2.40 version
>     error.
> 
> 2) [this patch] New symbol version for __rseq_size (same variable as
>     before): Compiled on new glibc, applications will fail to launch with
>     a GLIBC_2.40 version error.  This is done because they might use the
>     new size semantics.  But the application code specific to glibc 2.40
>     will compile successfully on glibc 2.39 and earlier, and run, given
>     the weird results.  This is not ideal.

Agreed.

> 
> 3) [no patch, but similar to this patch] Treat this as a bug fix for
>     __rseq_size: it should have been 20 initially.  No new symbol
>     version, but backport it 2.35 and later.  Given so many distributions
>     use stable release branches nowadays, it is likely the fix is
>     available to users before they encounter rseq-using applications.
> 
> The rules above apply to both 2) & 3).  I'm leaning towards approach 3)
> and would do the backports to 2.35 and later.

I would also prefer approach 3.

Thanks,

Mathieu

> 
> Thanks,
> Florian
>
Andreas K. Huettel July 8, 2024, 6:31 p.m. UTC | #7
> 
> > 
> > 3) [no patch, but similar to this patch] Treat this as a bug fix for
> >     __rseq_size: it should have been 20 initially.  No new symbol
> >     version, but backport it 2.35 and later.  Given so many distributions
> >     use stable release branches nowadays, it is likely the fix is
> >     available to users before they encounter rseq-using applications.
> > 
> > The rules above apply to both 2) & 3).  I'm leaning towards approach 3)
> > and would do the backports to 2.35 and later.
> 
> I would also prefer approach 3.
> 

Approach 3 is technically not an ABI change, so OK at this stage.

After the discussion in the meeting, the explanations in the thread here and
some further reading it makes most sense to me too.
Florian Weimer July 8, 2024, 7:16 p.m. UTC | #8
* Andreas K. Huettel:

>> 
>> > 
>> > 3) [no patch, but similar to this patch] Treat this as a bug fix for
>> >     __rseq_size: it should have been 20 initially.  No new symbol
>> >     version, but backport it 2.35 and later.  Given so many distributions
>> >     use stable release branches nowadays, it is likely the fix is
>> >     available to users before they encounter rseq-using applications.
>> > 
>> > The rules above apply to both 2) & 3).  I'm leaning towards approach 3)
>> > and would do the backports to 2.35 and later.
>> 
>> I would also prefer approach 3.
>> 
>
> Approach 3 is technically not an ABI change, so OK at this stage.
>
> After the discussion in the meeting, the explanations in the thread here and
> some further reading it makes most sense to me too.

Great.  I've posted a v2:

  [PATCH v2] Linux: Make __rseq_size useful for feature detection (bug 31965)
  <https://inbox.sourceware.org/libc-alpha/87ikxfd7d3.fsf@oldenburg.str.redhat.com/>

Thanks,
Florian
diff mbox series

Patch

diff --git a/NEWS b/NEWS
index f626896aa0..3824815917 100644
--- a/NEWS
+++ b/NEWS
@@ -49,6 +49,9 @@  Deprecated and removed features, and other changes affecting compatibility:
   <utmpx.h> (except for login_tty) due to locking and session management
   problems.
 
+* __rseq_size now denotes the size of the active rseq area (20 bytes
+  initially), not the size of struct rseq (32 bytes initially).
+
 Changes to build and runtime requirements:
 
   [Add changes to build and runtime requirements here]
diff --git a/manual/threads.texi b/manual/threads.texi
index e5544ff3da..25e99c9606 100644
--- a/manual/threads.texi
+++ b/manual/threads.texi
@@ -1007,8 +1007,12 @@  This variable is either zero (if restartable sequence registration
 failed or has been disabled) or the size of the restartable sequence
 registration.  This can be different from the size of @code{struct rseq}
 if the kernel has extended the size of the registration.  If
-registration is successful, @code{__rseq_size} is at least 32 (the
-initial size of @code{struct rseq}).
+registration is successful, @code{__rseq_size} is at least 20 (the
+initially active size of @code{struct rseq}).
+
+Previous versions of @theglibc{} set this to 32 even if the kernel only
+supported the initial area of 20 bytes because the value included unused
+padding at the end of the restartable sequence area.
 @end deftypevar
 
 @deftypevar {unsigned int} __rseq_flags
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
index 7eb35fb133..7803e19fd1 100644
--- a/sysdeps/nptl/dl-tls_init_tp.c
+++ b/sysdeps/nptl/dl-tls_init_tp.c
@@ -46,10 +46,6 @@  rtld_mutex_dummy (pthread_mutex_t *lock)
 
 const unsigned int __rseq_flags;
 
-/* The variables are in .data.relro but are not yet write-protected.  */
-extern unsigned int _rseq_size attribute_hidden;
-extern ptrdiff_t _rseq_offset attribute_hidden;
-
 void
 __tls_pre_init_tp (void)
 {
@@ -106,9 +102,7 @@  __tls_init_tp (void)
     bool do_rseq = true;
     do_rseq = TUNABLE_GET (rseq, int, NULL);
     if (rseq_register_current_thread (pd, do_rseq))
-      {
-        _rseq_size = sizeof (pd->rseq_area);
-      }
+      _rseq_size = RSEQ_AREA_SIZE_INITIAL_USED;
 
 #ifdef RSEQ_SIG
     /* This should be a compile-time constant, but the current
diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 268ba1b6ac..e3b232db92 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -356,6 +356,9 @@  ld {
     __rseq_offset;
     __rseq_size;
   }
+  GLIBC_2.40 {
+    __rseq_size;
+  }
   GLIBC_PRIVATE {
     __nptl_change_stack_perm;
   }
diff --git a/sysdeps/unix/sysv/linux/aarch64/ld.abilist b/sysdeps/unix/sysv/linux/aarch64/ld.abilist
index 5151c0781d..04efaa1e4f 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x8
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/alpha/ld.abilist b/sysdeps/unix/sysv/linux/alpha/ld.abilist
index 3e296c5473..9103538e04 100644
--- a/sysdeps/unix/sysv/linux/alpha/ld.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x8
 GLIBC_2.35 __rseq_size D 0x4
 GLIBC_2.4 __stack_chk_guard D 0x8
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/arc/ld.abilist b/sysdeps/unix/sysv/linux/arc/ld.abilist
index 55f0c2ab9c..031a0b5e33 100644
--- a/sysdeps/unix/sysv/linux/arc/ld.abilist
+++ b/sysdeps/unix/sysv/linux/arc/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/arm/be/ld.abilist b/sysdeps/unix/sysv/linux/arm/be/ld.abilist
index f1da2c636d..4ee96084c1 100644
--- a/sysdeps/unix/sysv/linux/arm/be/ld.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.4 __stack_chk_guard D 0x4
 GLIBC_2.4 __tls_get_addr F
 GLIBC_2.4 _dl_mcount F
 GLIBC_2.4 _r_debug D 0x14
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/arm/le/ld.abilist b/sysdeps/unix/sysv/linux/arm/le/ld.abilist
index f1da2c636d..4ee96084c1 100644
--- a/sysdeps/unix/sysv/linux/arm/le/ld.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.4 __stack_chk_guard D 0x4
 GLIBC_2.4 __tls_get_addr F
 GLIBC_2.4 _dl_mcount F
 GLIBC_2.4 _r_debug D 0x14
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/csky/ld.abilist b/sysdeps/unix/sysv/linux/csky/ld.abilist
index 7f482276ed..ac51f7ca61 100644
--- a/sysdeps/unix/sysv/linux/csky/ld.abilist
+++ b/sysdeps/unix/sysv/linux/csky/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/dl-rseq-symbols.S b/sysdeps/unix/sysv/linux/dl-rseq-symbols.S
index b4bba06a99..2155a79e02 100644
--- a/sysdeps/unix/sysv/linux/dl-rseq-symbols.S
+++ b/sysdeps/unix/sysv/linux/dl-rseq-symbols.S
@@ -17,6 +17,7 @@ 
    <https://www.gnu.org/licenses/>.  */
 
 #include <sysdep.h>
+#include <shlib-compat.h>
 
 #if __WORDSIZE == 64
 #define RSEQ_OFFSET_SIZE	8
@@ -32,18 +33,34 @@ 
    dynamic linker which will initialize the value both symbols point to
    before copy relocations take place. */
 
-	.globl	__rseq_size
-	.type	__rseq_size, %object
-	.size	__rseq_size, 4
 	.hidden _rseq_size
 	.globl	_rseq_size
 	.type	_rseq_size, %object
 	.size	_rseq_size, 4
+#ifdef SHARED
+	.globl	__rseq_size_original
+	.type	__rseq_size_original, %object
+	.size	__rseq_size_original, 4
+	.globl	__rseq_size_current
+	.type	__rseq_size_current, %object
+	.size	__rseq_size_current, 4
+#else
+	.globl	__rseq_size
+	.type	__rseq_size, %object
+	.size	__rseq_size, 4
+#endif
 	.section .data.rel.ro
 	.balign 4
 __rseq_size:
+__rseq_size_original:
+__rseq_size_current:
 _rseq_size:
 	.zero	4
+#ifdef SHARED
+/* Ensure that new binaries get the new __rseq_size semantics.  */
+compat_symbol (ld, __rseq_size_original, __rseq_size, GLIBC_2_35)
+versioned_symbol (ld, __rseq_size_current, __rseq_size, GLIBC_2_40)
+#endif
 
 /* Define 2 symbols: '__rseq_offset' is public const and '_rseq_offset' (an
    alias of '__rseq_offset') is hidden and writable for internal use by the
diff --git a/sysdeps/unix/sysv/linux/hppa/ld.abilist b/sysdeps/unix/sysv/linux/hppa/ld.abilist
index 7f5527fb30..a23ea40dff 100644
--- a/sysdeps/unix/sysv/linux/hppa/ld.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
 GLIBC_2.4 __stack_chk_guard D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
index 9c4a45d8dc..6041d6473c 100644
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist
index 93fcd64eee..bf7fb6b1fd 100644
--- a/sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist
@@ -6,3 +6,4 @@  GLIBC_2.36 __stack_chk_guard D 0x8
 GLIBC_2.36 __tls_get_addr F
 GLIBC_2.36 _dl_mcount F
 GLIBC_2.36 _r_debug D 0x28
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist
index f1da2c636d..4ee96084c1 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.4 __stack_chk_guard D 0x4
 GLIBC_2.4 __tls_get_addr F
 GLIBC_2.4 _dl_mcount F
 GLIBC_2.4 _r_debug D 0x14
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist
index dadbf852d0..526c0d5fba 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
 GLIBC_2.4 __stack_chk_guard D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/microblaze/ld.abilist b/sysdeps/unix/sysv/linux/microblaze/ld.abilist
index 89a0b7e4fd..e57cec648d 100644
--- a/sysdeps/unix/sysv/linux/microblaze/ld.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist
index e304d1bb46..9033f384d5 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
 GLIBC_2.4 __stack_chk_guard D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist
index e304d1bb46..9033f384d5 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
 GLIBC_2.4 __stack_chk_guard D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
index f26e594a13..bf037e137a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x8
 GLIBC_2.35 __rseq_size D 0x4
 GLIBC_2.4 __stack_chk_guard D 0x8
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/nios2/ld.abilist b/sysdeps/unix/sysv/linux/nios2/ld.abilist
index 811ae9da2f..127829e91c 100644
--- a/sysdeps/unix/sysv/linux/nios2/ld.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/or1k/ld.abilist b/sysdeps/unix/sysv/linux/or1k/ld.abilist
index cff2ffd23b..55baff19f3 100644
--- a/sysdeps/unix/sysv/linux/or1k/ld.abilist
+++ b/sysdeps/unix/sysv/linux/or1k/ld.abilist
@@ -6,3 +6,4 @@  GLIBC_2.35 __stack_chk_guard D 0x4
 GLIBC_2.35 __tls_get_addr F
 GLIBC_2.35 _dl_mcount F
 GLIBC_2.35 _r_debug D 0x14
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
index b1073f0942..46b193e2ef 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
@@ -9,3 +9,4 @@  GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
 GLIBC_2.39 __parse_hwcap_3_4_and_convert_at_platform F
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
index 40942a2cc6..e8a9859d9a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
@@ -9,3 +9,4 @@  GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x8
 GLIBC_2.35 __rseq_size D 0x4
 GLIBC_2.39 __parse_hwcap_3_4_and_convert_at_platform F
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
index 01f2694a4d..e57d8e3331 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
@@ -9,3 +9,4 @@  GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x8
 GLIBC_2.35 __rseq_size D 0x4
 GLIBC_2.39 __parse_hwcap_3_4_and_convert_at_platform F
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist
index 068368878e..d9e51f124c 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
index a7758a0e52..ff2294932c 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x8
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
index 48eebc1e16..7ea935b4ad 100644
--- a/sysdeps/unix/sysv/linux/rseq-internal.h
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h
@@ -25,15 +25,34 @@ 
 #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).  */
+#define RSEQ_AREA_SIZE_INITIAL 32
+#define RSEQ_AREA_SIZE_INITIAL_USED 20
+
+/* The variables are in .data.relro but are not yet write-protected.  */
+extern unsigned int _rseq_size attribute_hidden;
+extern ptrdiff_t _rseq_offset attribute_hidden;
+
 #ifdef RSEQ_SIG
 static inline bool
 rseq_register_current_thread (struct pthread *self, bool do_rseq)
 {
   if (do_rseq)
     {
+      unsigned int size;
+#if IS_IN (rtld)
+      /* Use the hidden symbol in ld.so.  */
+      size = _rseq_size;
+#else
+      size = __rseq_size;
+#endif
+      if (size < RSEQ_AREA_SIZE_INITIAL)
+        /* The initial implementation used only 20 bytes out of 32,
+           but still expected size 32.  */
+        size = RSEQ_AREA_SIZE_INITIAL;
       int ret = INTERNAL_SYSCALL_CALL (rseq, &self->rseq_area,
-                                       sizeof (self->rseq_area),
-                                       0, RSEQ_SIG);
+                                       size, 0, RSEQ_SIG);
       if (!INTERNAL_SYSCALL_ERROR_P (ret))
         return true;
     }
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist
index c15288394a..b8b8e0dd30 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist
@@ -6,3 +6,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
index 78d071600b..b436ecbdf5 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
@@ -6,3 +6,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x8
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/sh/be/ld.abilist b/sysdeps/unix/sysv/linux/sh/be/ld.abilist
index 7f5527fb30..a23ea40dff 100644
--- a/sysdeps/unix/sysv/linux/sh/be/ld.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
 GLIBC_2.4 __stack_chk_guard D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/sh/le/ld.abilist b/sysdeps/unix/sysv/linux/sh/le/ld.abilist
index 7f5527fb30..a23ea40dff 100644
--- a/sysdeps/unix/sysv/linux/sh/le/ld.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/ld.abilist
@@ -7,3 +7,4 @@  GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
 GLIBC_2.4 __stack_chk_guard D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist
index 3aac73f3df..1ea464b376 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist
@@ -6,3 +6,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
index 5471b24d59..94ff921440 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
@@ -6,3 +6,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x8
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c
index 2c90409ba0..08a9533130 100644
--- a/sysdeps/unix/sysv/linux/tst-rseq.c
+++ b/sysdeps/unix/sysv/linux/tst-rseq.c
@@ -29,6 +29,7 @@ 
 # include <stdlib.h>
 # include <string.h>
 # include <syscall.h>
+# include <sys/auxv.h>
 # include <thread_pointer.h>
 # include <tls.h>
 # include "tst-rseq.h"
@@ -42,7 +43,8 @@  do_rseq_main_test (void)
   TEST_COMPARE (__rseq_flags, 0);
   TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset
                == (char *) &pd->rseq_area);
-  TEST_COMPARE (__rseq_size, sizeof (pd->rseq_area));
+  /* The current implementation only supports the initial size.  */
+  TEST_COMPARE (__rseq_size, 20);
 }
 
 static void
@@ -52,6 +54,12 @@  do_rseq_test (void)
     {
       FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test");
     }
+  printf ("info: __rseq_size: %u\n", __rseq_size);
+  printf ("info: __rseq_offset: %td\n", __rseq_offset);
+  printf ("info: __rseq_flags: %u\n", __rseq_flags);
+  printf ("info: getauxval (AT_RSEQ_FEATURE_SIZE): %ld\n",
+          getauxval (AT_RSEQ_FEATURE_SIZE));
+  printf ("info: getauxval (AT_RSEQ_ALIGN): %ld\n", getauxval (AT_RSEQ_ALIGN));
   do_rseq_main_test ();
 }
 #else /* RSEQ_SIG */
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index 5a8bd322cd..171b38a2b9 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -6,3 +6,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x8
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
index e17496d124..0a18a6c2d6 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
@@ -6,3 +6,4 @@  GLIBC_2.34 __rtld_version_placeholder F
 GLIBC_2.35 __rseq_flags D 0x4
 GLIBC_2.35 __rseq_offset D 0x4
 GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_size D 0x4