2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-30 13:58:34 +00:00

zdtm/static/rseq00: fix rseq test when linking with a fresh Glibc

Fresh Glibc does rseq() register by default. We need to unregister
rseq before registering our own.

Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
This commit is contained in:
Alexander Mikhalitsyn
2021-12-24 22:56:56 +03:00
committed by Andrei Vagin
parent f70ddab24e
commit 441310c260

View File

@@ -19,12 +19,52 @@
#include "zdtmtst.h"
#ifdef __has_include
#if __has_include("sys/rseq.h")
#include <sys/rseq.h>
#endif
#endif
#if defined(__x86_64__)
#if defined(RSEQ_SIG)
static inline void *__criu_thread_pointer(void)
{
#if __GNUC_PREREQ(11, 1)
return __builtin_thread_pointer();
#else
void *__result;
#ifdef __x86_64__
__asm__("mov %%fs:0, %0" : "=r"(__result));
#else
__asm__("mov %%gs:0, %0" : "=r"(__result));
#endif /* __x86_64__ */
return __result;
#endif /* !GCC 11 */
}
static inline void unregister_glibc_rseq(void)
{
struct rseq *rseq = (struct rseq *)((char *)__criu_thread_pointer() + __rseq_offset);
/* hack: mark glibc rseq structure as failed to register */
rseq->cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED;
/* unregister rseq */
syscall(__NR_rseq, (void *)rseq, __rseq_size, 1, RSEQ_SIG);
}
#else
static inline void unregister_glibc_rseq(void)
{
}
#endif /* defined(RSEQ_SIG) */
const char *test_doc = "Check that rseq() basic C/R works";
const char *test_author = "Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>";
/* some useful definitions from kernel uapi */
#ifndef RSEQ_SIG
enum rseq_flags {
RSEQ_FLAG_UNREGISTER = (1 << 0),
};
@@ -36,6 +76,10 @@ struct rseq {
uint32_t flags;
} __attribute__((aligned(4 * sizeof(uint64_t))));
#define RSEQ_SIG 0x53053053
#endif /* RSEQ_SIG */
#ifndef __NR_rseq
#define __NR_rseq 334
#endif
@@ -43,8 +87,6 @@ struct rseq {
static __thread volatile struct rseq __rseq_abi;
#define RSEQ_SIG 0x53053053
static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len, int flags, uint32_t sig)
{
return syscall(__NR_rseq, rseq_abi, rseq_len, flags, sig);
@@ -53,6 +95,7 @@ static int sys_rseq(volatile struct rseq *rseq_abi, uint32_t rseq_len, int flags
static void register_thread(void)
{
int rc;
unregister_glibc_rseq();
rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), 0, RSEQ_SIG);
if (rc) {
fail("Failed to register rseq");
@@ -60,16 +103,6 @@ static void register_thread(void)
}
}
static void unregister_thread(void)
{
int rc;
rc = sys_rseq(&__rseq_abi, sizeof(struct rseq), RSEQ_FLAG_UNREGISTER, RSEQ_SIG);
if (rc) {
fail("Failed to unregister rseq");
exit(1);
}
}
static void check_thread(void)
{
int rc;