From e30d18f435e534f210cbaa3db0d97f0f586bdf0a Mon Sep 17 00:00:00 2001 From: Alexander Mikhalitsyn Date: Fri, 8 Jul 2022 12:36:57 +0000 Subject: [PATCH] rseq: fix headers conflict on Mariner GNU/Linux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- Makefile.config | 3 ++- criu/cr-dump.c | 15 ++++++++------- criu/include/linux/rseq.h | 20 ++++++++++++++------ criu/include/pstree.h | 2 +- scripts/feature-tests.mak | 19 +++++++++++++++++++ 5 files changed, 44 insertions(+), 15 deletions(-) diff --git a/Makefile.config b/Makefile.config index d46d84f2d..d113e2246 100644 --- a/Makefile.config +++ b/Makefile.config @@ -78,7 +78,8 @@ export DEFINES += $(FEATURE_DEFINES) export CFLAGS += $(FEATURE_DEFINES) 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 define gen-feature-test diff --git a/criu/cr-dump.c b/criu/cr-dump.c index e60da88ed..210f66232 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -1039,7 +1039,7 @@ static int dump_task_signals(pid_t pid, struct pstree_item *item) 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) { int ret; @@ -1070,10 +1070,11 @@ static int read_rseq_cs(pid_t tid, struct __ptrace_rseq_configuration *rseqc, st if (!rseq->rseq_cs) 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) { 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; } @@ -1088,7 +1089,7 @@ static int dump_thread_rseq(struct pstree_item *item, int i) CoreEntry *core = item->core[i]; RseqEntry **rseqep = &core->thread_core->rseq_entry; 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; /* @@ -1154,7 +1155,7 @@ err: static int dump_task_rseq(pid_t pid, struct pstree_item *item) { 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 (!kdat.has_rseq) @@ -1179,7 +1180,7 @@ free_rseq: 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; } @@ -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) { 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; /* equivalent to (struct rseq)->rseq_cs is NULL */ diff --git a/criu/include/linux/rseq.h b/criu/include/linux/rseq.h index a47876e66..5ceefbf8e 100644 --- a/criu/include/linux/rseq.h +++ b/criu/include/linux/rseq.h @@ -9,7 +9,12 @@ #endif #endif -#ifndef __GLIBC_HAVE_KERNEL_RSEQ +#include +#include + +#include "common/config.h" + +#ifdef CONFIG_HAS_NO_LIBC_RSEQ_DEFS /* * linux/rseq.h * @@ -18,9 +23,6 @@ * Copyright (c) 2015-2018 Mathieu Desnoyers */ -#include -#include - enum rseq_cpu_id_state { RSEQ_CPU_ID_UNINITIALIZED = -1, 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_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 * contained within a single cache-line. It is usually declared as * link-time constant data. */ -struct rseq_cs { +struct criu_rseq_cs { /* Version of this structure. */ __u32 version; /* enum rseq_cs_flags */ @@ -57,7 +66,6 @@ struct rseq_cs { __u64 post_commit_offset; __u64 abort_ip; } __attribute__((aligned(4 * sizeof(__u64)))); -#endif /* __GLIBC_HAVE_KERNEL_RSEQ */ /* * We have to have our own copy of struct rseq definition because diff --git a/criu/include/pstree.h b/criu/include/pstree.h index 8ae750e1a..1137046d4 100644 --- a/criu/include/pstree.h +++ b/criu/include/pstree.h @@ -63,7 +63,7 @@ struct dmp_info { struct parasite_ctl *parasite_ctl; struct parasite_thread_ctl **thread_ctls; 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, diff --git a/scripts/feature-tests.mak b/scripts/feature-tests.mak index 592552cb8..014e893a8 100644 --- a/scripts/feature-tests.mak +++ b/scripts/feature-tests.mak @@ -196,3 +196,22 @@ int main(void) return 0; } endef + +define FEATURE_TEST_NO_LIBC_RSEQ_DEFS + +#ifdef __has_include +#if __has_include(\"sys/rseq.h\") +#include +#endif +#endif + +enum rseq_cpu_id_state { + RSEQ_CPU_ID_UNINITIALIZED = -1, + RSEQ_CPU_ID_REGISTRATION_FAILED = -2, +}; + +int main(void) +{ + return 0; +} +endef