From 3c567693f2e6579109dbabcca0e90c059ce5af25 Mon Sep 17 00:00:00 2001 From: bb-cat 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 --- 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 #include #include +#include +#include #include #include #include @@ -36,6 +38,7 @@ #include "sockets.h" #include "net.h" #include "tun.h" +#include #include #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