criu: kerndat: add kerndat_has_binfmt_misc_sandboxing()

Detect if the kernel supports binfmt_misc sandboxing and store the
result in kerndat.

The result will be used by the code that dumps and restores binfmt_misc
entries.

Signed-off-by: Dmitry Sepp <dmitry.sepp@virtuozzo.com>
This commit is contained in:
Dmitry Sepp 2026-02-10 14:28:42 +00:00 committed by Andrei Vagin
parent 0ae3a9498c
commit ecab9e3570
3 changed files with 102 additions and 0 deletions

View file

@ -1810,6 +1810,16 @@ static int check_external_net_ns(void)
return 0;
}
static int check_binfmt_misc_sandboxing(void)
{
if (!kdat.has_binfmt_misc_sandboxing) {
pr_info("binfmt_misc sandboxing isn't supported\n");
return -1;
}
return 0;
}
struct feature_list {
char *name;
int (*func)(void);
@ -1861,6 +1871,7 @@ static struct feature_list feature_list[] = {
{ "overlayfs_maps", check_overlayfs_maps },
{ "breakpoints", check_breakpoints },
{ "pagemap_scan_guard_pages", check_pagemap_scan_guard_pages },
{ "binfmt_misc_sandboxing", check_binfmt_misc_sandboxing },
{ NULL, NULL },
};

View file

@ -93,6 +93,7 @@ struct kerndat_s {
bool has_breakpoints;
bool has_madv_guard;
bool has_pagemap_scan_guard_pages;
bool has_binfmt_misc_sandboxing;
};
extern struct kerndat_s kdat;

View file

@ -1848,6 +1848,92 @@ void kerndat_warn_about_madv_guards(void)
"Please, consider updating your kernel.\n");
}
/* Keep the fd open so that it can be closed by the caller (required by the parent process) */
static int __mount_and_stat_detached_binfmt_misc(struct stat *st, int *mnt_fd)
{
int fd;
fd = mount_detached_fs("binfmt_misc");
if (fd < 0) {
/* Most likely a permission error, so we can't use binfmt_misc */
return 1;
}
if (fstat(fd, st) < 0) {
pr_perror("Failed to stat a binfmt_misc mountpoint");
close(fd);
return -1;
}
*mnt_fd = fd;
return 0;
}
struct has_binfmt_misc_arg {
dev_t st_dev;
bool has;
};
static int __has_binfmt_misc_sandboxing(void *arg)
{
struct has_binfmt_misc_arg *has_arg = (struct has_binfmt_misc_arg *)arg;
struct stat st;
int ret, mnt_fd;
if (unshare(CLONE_NEWNS | CLONE_NEWUSER)) {
pr_perror("Failed to unshare namespaces");
return 1;
}
ret = __mount_and_stat_detached_binfmt_misc(&st, &mnt_fd);
if (ret < 0) {
return 1;
} else if (ret == 1) {
has_arg->has = false;
return 0;
}
if (has_arg->st_dev != st.st_dev)
has_arg->has = true;
else
has_arg->has = false;
close(mnt_fd);
return 0;
}
static int kerndat_has_binfmt_misc_sandboxing(void)
{
int ret, mnt_fd;
struct stat st;
struct has_binfmt_misc_arg arg;
ret = __mount_and_stat_detached_binfmt_misc(&st, &mnt_fd);
if (ret < 0) {
return -1;
} else if (ret == 1) {
arg.has = false;
goto out;
}
arg.st_dev = st.st_dev;
ret = call_in_child_process(__has_binfmt_misc_sandboxing, (void *)&arg);
close(mnt_fd);
if (ret < 0) {
pr_err("Failed to check binfmt_misc sandboxing support in child process\n");
return -1;
}
out:
pr_info("binfmt_misc sandboxing is %s supported\n", arg.has ? "" : "not");
kdat.has_binfmt_misc_sandboxing = arg.has;
return 0;
}
/*
* Some features depend on resource that can be dynamically changed
* at the OS runtime. There are cases that we cannot determine the
@ -2121,6 +2207,10 @@ int kerndat_init(void)
pr_err("kerndat_has_madv_guard has failed when initializing kerndat.\n");
ret = -1;
}
if (!ret && kerndat_has_binfmt_misc_sandboxing()) {
pr_err("kerndat_has_binfmt_misc_sandboxing has failed when initializing kerndat.\n");
ret = -1;
}
kerndat_lsm();
kerndat_mmap_min_addr();