Skip to content

Commit

Permalink
Adjust to glibc __rseq_size semantic change
Browse files Browse the repository at this point in the history
In commit 2e456ccf0c34a056e3ccafac4a0c7effef14d918 ("Linux: Make
__rseq_size useful for feature detection (bug 31965)") glibc 2.40
changed the meaning of __rseq_size slightly: it is now the size
of the active/feature area (20 bytes initially), and not the size
of the entire initially defined struct (32 bytes including padding).
The reason for the change is that the size including padding does not
allow detection of newly added features while previously unused
padding is consumed.

The prep_libc_rseq_info change in criu/cr-restore.c is not necessary
on kernels which have full ptrace support for obtaining rseq
information because the code is not used.  On older kernels, it is
a correctness fix because with size 20 (the new value), rseq
registeration would fail.

The two other changes are required to make rseq unregistration work
in tests.
  • Loading branch information
fweimer-rh committed Jul 10, 2024
1 parent 116c689 commit da33648
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 3 deletions.
8 changes: 8 additions & 0 deletions criu/cr-restore.c
Original file line number Diff line number Diff line change
Expand Up @@ -2618,7 +2618,15 @@ static void prep_libc_rseq_info(struct rst_rseq_param *rseq)
if (!kdat.has_ptrace_get_rseq_conf) {
#if defined(__GLIBC__) && defined(RSEQ_SIG)
rseq->rseq_abi_pointer = encode_pointer(__criu_thread_pointer() + __rseq_offset);
/*
* Current glibc reports the feature/active size in
* __rseq_size, not the size passed to the kernel.
* This could be 20, but older kernels expect 32 for
* the size argument even if only 20 bytes are used.
*/
rseq->rseq_abi_size = __rseq_size;
if (rseq->rseq_abi_size < 32)
rseq->rseq_abi_size = 32;
rseq->signature = RSEQ_SIG;
#else
rseq->rseq_abi_pointer = 0;
Expand Down
7 changes: 5 additions & 2 deletions test/zdtm/static/rseq00.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ static inline void unregister_glibc_rseq(void)
rseq->cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED;

/* unregister rseq */
syscall(__NR_rseq, (void *)rseq, __rseq_size, 1, RSEQ_SIG);
unsigned int size = __rseq_size;
if (__rseq_size < 32)
size = 32;
syscall(__NR_rseq, (void *)rseq, size, 1, RSEQ_SIG);
}
#else
static inline void unregister_glibc_rseq(void)
Expand Down Expand Up @@ -140,4 +143,4 @@ int main(int argc, char *argv[])
return 0;
}

#endif /* #if defined(__x86_64__) */
#endif /* #if defined(__x86_64__) */
5 changes: 4 additions & 1 deletion test/zdtm/transition/rseq01.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ static inline void *thread_pointer(void)
static inline void unregister_old_rseq(void)
{
/* unregister rseq */
syscall(__NR_rseq, (void *)((char *)thread_pointer() + __rseq_offset), __rseq_size, 1, RSEQ_SIG);
unsigned int size = __rseq_size;
if (__rseq_size < 32)
size = 32;
syscall(__NR_rseq, (void *)((char *)thread_pointer() + __rseq_offset), size, 1, RSEQ_SIG);
}
#else
static inline void unregister_old_rseq(void)
Expand Down

0 comments on commit da33648

Please sign in to comment.