2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-09-03 15:55:53 +00:00

rseq: fix headers conflict on Mariner GNU/Linux

1. For some reason, Marier distribution headers
not correctly define __GLIBC_HAVE_KERNEL_RSEQ
compile-time constant. It remains undefined,
but in fact header files provides corresponding
rseq types declaration which leads to conflict.

2. Another issue, is that they use uint*_t types
instead of __u* types as in original rseq.h.

This leads to compile time issues like this:
format '%llx' expects argument of type 'long long unsigned int', but argument 5 has type 'uint64_t' {aka 'long unsigned int'}

and we can't even replace %llx to %PRIx64 because it will break
compilation on other distros (like Fedora) with analogical error:

error: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 6 has type ‘__u64’ {aka ‘long long unsigned int’}

Let's use our-own struct rseq copy fully equal to the kernel one,
it's safe because this structure is a part of Linux Kernel ABI.

Fixes #1934

Reported-by: Nikola Bojanic
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
This commit is contained in:
Alexander Mikhalitsyn
2022-07-08 12:36:57 +00:00
committed by Andrei Vagin
parent ad58553d90
commit e30d18f435
5 changed files with 44 additions and 15 deletions

View File

@@ -78,7 +78,8 @@ export DEFINES += $(FEATURE_DEFINES)
export CFLAGS += $(FEATURE_DEFINES) export CFLAGS += $(FEATURE_DEFINES)
FEATURES_LIST := TCP_REPAIR STRLCPY STRLCAT PTRACE_PEEKSIGINFO \ FEATURES_LIST := TCP_REPAIR STRLCPY STRLCAT PTRACE_PEEKSIGINFO \
SETPROCTITLE_INIT MEMFD TCP_REPAIR_WINDOW FSCONFIG MEMFD_CREATE OPENAT2 SETPROCTITLE_INIT MEMFD TCP_REPAIR_WINDOW FSCONFIG MEMFD_CREATE \
OPENAT2 NO_LIBC_RSEQ_DEFS
# $1 - config name # $1 - config name
define gen-feature-test define gen-feature-test

View File

@@ -1039,7 +1039,7 @@ static int dump_task_signals(pid_t pid, struct pstree_item *item)
return 0; return 0;
} }
static int read_rseq_cs(pid_t tid, struct __ptrace_rseq_configuration *rseqc, struct rseq_cs *rseq_cs, static int read_rseq_cs(pid_t tid, struct __ptrace_rseq_configuration *rseqc, struct criu_rseq_cs *rseq_cs,
struct criu_rseq *rseq) struct criu_rseq *rseq)
{ {
int ret; int ret;
@@ -1070,10 +1070,11 @@ static int read_rseq_cs(pid_t tid, struct __ptrace_rseq_configuration *rseqc, st
if (!rseq->rseq_cs) if (!rseq->rseq_cs)
return 0; return 0;
ret = ptrace_peek_area(tid, rseq_cs, decode_pointer(rseq->rseq_cs), sizeof(struct rseq_cs)); ret = ptrace_peek_area(tid, rseq_cs, decode_pointer(rseq->rseq_cs), sizeof(struct criu_rseq_cs));
if (ret) { if (ret) {
pr_err("ptrace_peek_area(%d, %lx, %lx, %lx): fail to read rseq_cs struct\n", tid, pr_err("ptrace_peek_area(%d, %lx, %lx, %lx): fail to read rseq_cs struct\n", tid,
(unsigned long)rseq_cs, (unsigned long)rseq->rseq_cs, (unsigned long)sizeof(struct rseq_cs)); (unsigned long)rseq_cs, (unsigned long)rseq->rseq_cs,
(unsigned long)sizeof(struct criu_rseq_cs));
return -1; return -1;
} }
@@ -1088,7 +1089,7 @@ static int dump_thread_rseq(struct pstree_item *item, int i)
CoreEntry *core = item->core[i]; CoreEntry *core = item->core[i];
RseqEntry **rseqep = &core->thread_core->rseq_entry; RseqEntry **rseqep = &core->thread_core->rseq_entry;
struct criu_rseq rseq = {}; struct criu_rseq rseq = {};
struct rseq_cs *rseq_cs = &dmpi(item)->thread_rseq_cs[i]; struct criu_rseq_cs *rseq_cs = &dmpi(item)->thread_rseq_cs[i];
pid_t tid = item->threads[i].real; pid_t tid = item->threads[i].real;
/* /*
@@ -1154,7 +1155,7 @@ err:
static int dump_task_rseq(pid_t pid, struct pstree_item *item) static int dump_task_rseq(pid_t pid, struct pstree_item *item)
{ {
int i; int i;
struct rseq_cs *thread_rseq_cs; struct criu_rseq_cs *thread_rseq_cs;
/* if rseq() syscall isn't supported then nothing to dump */ /* if rseq() syscall isn't supported then nothing to dump */
if (!kdat.has_rseq) if (!kdat.has_rseq)
@@ -1179,7 +1180,7 @@ free_rseq:
return -1; return -1;
} }
static bool task_in_rseq(struct rseq_cs *rseq_cs, uint64_t addr) static bool task_in_rseq(struct criu_rseq_cs *rseq_cs, uint64_t addr)
{ {
return addr >= rseq_cs->start_ip && addr < rseq_cs->start_ip + rseq_cs->post_commit_offset; return addr >= rseq_cs->start_ip && addr < rseq_cs->start_ip + rseq_cs->post_commit_offset;
} }
@@ -1187,7 +1188,7 @@ static bool task_in_rseq(struct rseq_cs *rseq_cs, uint64_t addr)
static int fixup_thread_rseq(struct pstree_item *item, int i) static int fixup_thread_rseq(struct pstree_item *item, int i)
{ {
CoreEntry *core = item->core[i]; CoreEntry *core = item->core[i];
struct rseq_cs *rseq_cs = &dmpi(item)->thread_rseq_cs[i]; struct criu_rseq_cs *rseq_cs = &dmpi(item)->thread_rseq_cs[i];
pid_t tid = item->threads[i].real; pid_t tid = item->threads[i].real;
/* equivalent to (struct rseq)->rseq_cs is NULL */ /* equivalent to (struct rseq)->rseq_cs is NULL */

View File

@@ -9,7 +9,12 @@
#endif #endif
#endif #endif
#ifndef __GLIBC_HAVE_KERNEL_RSEQ #include <linux/types.h>
#include <asm/byteorder.h>
#include "common/config.h"
#ifdef CONFIG_HAS_NO_LIBC_RSEQ_DEFS
/* /*
* linux/rseq.h * linux/rseq.h
* *
@@ -18,9 +23,6 @@
* Copyright (c) 2015-2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> * Copyright (c) 2015-2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*/ */
#include <linux/types.h>
#include <asm/byteorder.h>
enum rseq_cpu_id_state { enum rseq_cpu_id_state {
RSEQ_CPU_ID_UNINITIALIZED = -1, RSEQ_CPU_ID_UNINITIALIZED = -1,
RSEQ_CPU_ID_REGISTRATION_FAILED = -2, RSEQ_CPU_ID_REGISTRATION_FAILED = -2,
@@ -41,13 +43,20 @@ enum rseq_cs_flags {
RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL = (1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT), RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL = (1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE = (1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT), RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE = (1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
}; };
#endif /* CONFIG_HAS_NO_LIBC_RSEQ_DEFS */
/*
* Let's use our own definition of struct rseq_cs because some distros
* (for example Mariner GNU/Linux) declares this structure their-own way.
* This makes trouble with inconsistency between printf formatters and
* struct rseq_cs field types.
*/
/* /*
* struct rseq_cs is aligned on 4 * 8 bytes to ensure it is always * struct rseq_cs is aligned on 4 * 8 bytes to ensure it is always
* contained within a single cache-line. It is usually declared as * contained within a single cache-line. It is usually declared as
* link-time constant data. * link-time constant data.
*/ */
struct rseq_cs { struct criu_rseq_cs {
/* Version of this structure. */ /* Version of this structure. */
__u32 version; __u32 version;
/* enum rseq_cs_flags */ /* enum rseq_cs_flags */
@@ -57,7 +66,6 @@ struct rseq_cs {
__u64 post_commit_offset; __u64 post_commit_offset;
__u64 abort_ip; __u64 abort_ip;
} __attribute__((aligned(4 * sizeof(__u64)))); } __attribute__((aligned(4 * sizeof(__u64))));
#endif /* __GLIBC_HAVE_KERNEL_RSEQ */
/* /*
* We have to have our own copy of struct rseq definition because * We have to have our own copy of struct rseq definition because

View File

@@ -63,7 +63,7 @@ struct dmp_info {
struct parasite_ctl *parasite_ctl; struct parasite_ctl *parasite_ctl;
struct parasite_thread_ctl **thread_ctls; struct parasite_thread_ctl **thread_ctls;
uint64_t *thread_sp; uint64_t *thread_sp;
struct rseq_cs *thread_rseq_cs; struct criu_rseq_cs *thread_rseq_cs;
/* /*
* Although we don't support dumping different struct creds in general, * Although we don't support dumping different struct creds in general,

View File

@@ -196,3 +196,22 @@ int main(void)
return 0; return 0;
} }
endef endef
define FEATURE_TEST_NO_LIBC_RSEQ_DEFS
#ifdef __has_include
#if __has_include(\"sys/rseq.h\")
#include <sys/rseq.h>
#endif
#endif
enum rseq_cpu_id_state {
RSEQ_CPU_ID_UNINITIALIZED = -1,
RSEQ_CPU_ID_REGISTRATION_FAILED = -2,
};
int main(void)
{
return 0;
}
endef