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>
This commit is contained in:
Alexander Mikhalitsyn 2021-12-21 18:29:14 +03:00 committed by Andrei Vagin
parent ca54dfcac9
commit bd9ee32554
4 changed files with 65 additions and 0 deletions

View file

@ -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 {
uint64_t rseq_abi_pointer;
uint32_t rseq_abi_size;
uint32_t signature;
uint32_t flags;
uint32_t 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

View file

@ -798,6 +798,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) {
@ -1475,6 +1484,7 @@ int cr_check(void)
ret |= check_memfd_hugetlb();
ret |= check_move_mount_set_group();
ret |= check_openat2();
ret |= check_ptrace_get_rseq_conf();
}
/*
@ -1591,6 +1601,7 @@ static struct feature_list feature_list[] = {
{ "memfd_hugetlb", check_memfd_hugetlb },
{ "move_mount_set_group", check_move_mount_set_group },
{ "openat2", check_openat2 },
{ "get_rseq_conf", check_ptrace_get_rseq_conf },
{ NULL, NULL },
};

View file

@ -81,6 +81,7 @@ struct kerndat_s {
bool has_move_mount_set_group;
bool has_openat2;
bool has_rseq;
bool has_ptrace_get_rseq_conf;
};
extern struct kerndat_s kdat;

View file

@ -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>
@ -37,6 +39,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"
@ -919,6 +922,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;
}
int kerndat_sockopt_buf_lock(void)
{
int exit_code = -1;
@ -1624,6 +1661,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();