Linux: Change meaning of __rseq_size slightly
Checks
Context |
Check |
Description |
redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
redhat-pt-bot/TryBot-32bit |
success
|
Build for i686
|
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_glibc_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_glibc_check--master-arm |
success
|
Test passed
|
Commit Message
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
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
* 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
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
* 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
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.
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
>
>
> >
> > 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.
* 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
@@ -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]
@@ -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
@@ -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
@@ -356,6 +356,9 @@ ld {
__rseq_offset;
__rseq_size;
}
+ GLIBC_2.40 {
+ __rseq_size;
+ }
GLIBC_PRIVATE {
__nptl_change_stack_perm;
}
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
}
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 */
@@ -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
@@ -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