see https://github.com/checkpoint-restore/criu/issues/1696 and https://github.com/checkpoint-restore/criu/pull/1706
163 lines
4.4 KiB
Diff
163 lines
4.4 KiB
Diff
From 3c567693f2e6579109dbabcca0e90c059ce5af25 Mon Sep 17 00:00:00 2001
|
|
From: bb-cat <ningyu9@huawei.com>
|
|
Date: Wed, 2 Mar 2022 15:30:18 +0800
|
|
Subject: [PATCH 05/16] cr-check: Add ptrace rseq conf dump feature Add
|
|
"get_rseq_conf" feature corresponding to the
|
|
ptrace(PTRACE_GET_RSEQ_CONFIGURATION) support.
|
|
|
|
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
|
|
---
|
|
compel/include/uapi/ptrace.h | 12 +++++++
|
|
criu/cr-check.c | 11 +++++++
|
|
criu/include/kerndat.h | 1 +
|
|
criu/kerndat.c | 41 ++++++++++++++++++++++++
|
|
4 files changed, 65 insertions(+)
|
|
|
|
diff --git a/compel/include/uapi/ptrace.h b/compel/include/uapi/ptrace.h
|
|
index c5291d2..bfe28c7 100644
|
|
--- a/compel/include/uapi/ptrace.h
|
|
+++ b/compel/include/uapi/ptrace.h
|
|
@@ -65,6 +65,18 @@ typedef struct {
|
|
uint64_t flags; /* Output: filter's flags */
|
|
} seccomp_metadata_t;
|
|
|
|
+#ifndef PTRACE_GET_RSEQ_CONFIGURATION
|
|
+#define PTRACE_GET_RSEQ_CONFIGURATION 0x420f
|
|
+
|
|
+struct ptrace_rseq_configuration {
|
|
+ __u64 rseq_abi_pointer;
|
|
+ __u32 rseq_abi_size;
|
|
+ __u32 signature;
|
|
+ __u32 flags;
|
|
+ __u32 pad;
|
|
+};
|
|
+#endif
|
|
+
|
|
#ifdef PTRACE_EVENT_STOP
|
|
#if PTRACE_EVENT_STOP == 7 /* Bad value from Linux 3.1-3.3, fixed in 3.4 */
|
|
#undef PTRACE_EVENT_STOP
|
|
diff --git a/criu/cr-check.c b/criu/cr-check.c
|
|
index d41ef8f..ba87511 100644
|
|
--- a/criu/cr-check.c
|
|
+++ b/criu/cr-check.c
|
|
@@ -794,6 +794,15 @@ static int check_ptrace_dump_seccomp_filters(void)
|
|
return ret;
|
|
}
|
|
|
|
+static int check_ptrace_get_rseq_conf(void)
|
|
+{
|
|
+ if (!kdat.has_ptrace_get_rseq_conf) {
|
|
+ pr_warn("ptrace(PTRACE_GET_RSEQ_CONFIGURATION) isn't supported. C/R of processes which are using rseq() won't work.\n");
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int check_mem_dirty_track(void)
|
|
{
|
|
if (!kdat.has_dirty_track) {
|
|
@@ -1435,6 +1444,7 @@ int cr_check(void)
|
|
ret |= check_ns_pid();
|
|
ret |= check_apparmor_stacking();
|
|
ret |= check_network_lock_nftables();
|
|
+ ret |= check_ptrace_get_rseq_conf();
|
|
}
|
|
|
|
/*
|
|
@@ -1547,6 +1557,7 @@ static struct feature_list feature_list[] = {
|
|
{ "ns_pid", check_ns_pid },
|
|
{ "apparmor_stacking", check_apparmor_stacking },
|
|
{ "network_lock_nftables", check_network_lock_nftables },
|
|
+ { "get_rseq_conf", check_ptrace_get_rseq_conf },
|
|
{ NULL, NULL },
|
|
};
|
|
|
|
diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
|
|
index 44a6976..05abeda 100644
|
|
--- a/criu/include/kerndat.h
|
|
+++ b/criu/include/kerndat.h
|
|
@@ -75,6 +75,7 @@ struct kerndat_s {
|
|
bool has_nspid;
|
|
bool has_nftables_concat;
|
|
bool has_rseq;
|
|
+ bool has_ptrace_get_rseq_conf;
|
|
};
|
|
|
|
extern struct kerndat_s kdat;
|
|
diff --git a/criu/kerndat.c b/criu/kerndat.c
|
|
index f5a4490..4841387 100644
|
|
--- a/criu/kerndat.c
|
|
+++ b/criu/kerndat.c
|
|
@@ -4,6 +4,8 @@
|
|
#include <sys/file.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
+#include <sys/ptrace.h>
|
|
+#include <sys/wait.h>
|
|
#include <sys/mman.h>
|
|
#include <errno.h>
|
|
#include <sys/syscall.h>
|
|
@@ -36,6 +38,7 @@
|
|
#include "sockets.h"
|
|
#include "net.h"
|
|
#include "tun.h"
|
|
+#include <compel/ptrace.h>
|
|
#include <compel/plugins/std/syscall-codes.h>
|
|
#include "netfilter.h"
|
|
#include "fsnotify.h"
|
|
@@ -830,6 +833,40 @@ static int kerndat_has_rseq(void)
|
|
return 0;
|
|
}
|
|
|
|
+static int kerndat_has_ptrace_get_rseq_conf(void)
|
|
+{
|
|
+ pid_t pid;
|
|
+ int len;
|
|
+ struct ptrace_rseq_configuration rseq;
|
|
+
|
|
+ pid = fork_and_ptrace_attach(NULL);
|
|
+ if (pid < 0)
|
|
+ return -1;
|
|
+
|
|
+ len = ptrace(PTRACE_GET_RSEQ_CONFIGURATION, pid, sizeof(rseq), &rseq);
|
|
+ if (len != sizeof(rseq)) {
|
|
+ kdat.has_ptrace_get_rseq_conf = false;
|
|
+ pr_info("ptrace(PTRACE_GET_RSEQ_CONFIGURATION) is not supported\n");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * flags is always zero from the kernel side, if it will be changed
|
|
+ * we need to pay attention to that and, possibly, make changes on the CRIU side.
|
|
+ */
|
|
+ if (rseq.flags != 0) {
|
|
+ kdat.has_ptrace_get_rseq_conf = false;
|
|
+ pr_err("ptrace(PTRACE_GET_RSEQ_CONFIGURATION): rseq.flags != 0\n");
|
|
+ } else {
|
|
+ kdat.has_ptrace_get_rseq_conf = true;
|
|
+ }
|
|
+
|
|
+out:
|
|
+ kill(pid, SIGKILL);
|
|
+ waitpid(pid, NULL, 0);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
#define KERNDAT_CACHE_FILE KDAT_RUNDIR "/criu.kdat"
|
|
#define KERNDAT_CACHE_FILE_TMP KDAT_RUNDIR "/.criu.kdat"
|
|
|
|
@@ -1378,6 +1415,10 @@ int kerndat_init(void)
|
|
pr_err("kerndat_has_rseq failed when initializing kerndat.\n");
|
|
ret = -1;
|
|
}
|
|
+ if (!ret && kerndat_has_ptrace_get_rseq_conf()) {
|
|
+ pr_err("kerndat_has_ptrace_get_rseq_conf failed when initializing kerndat.\n");
|
|
+ ret = -1;
|
|
+ }
|
|
kerndat_lsm();
|
|
kerndat_mmap_min_addr();
|
|
kerndat_files_stat();
|
|
--
|
|
2.30.0
|
|
|