criu: Remove legacy binfmt_misc handling code

Remove the OpenVZ specific code that was not used outside of the OpenVZ
infrastructure in preparation for implementing support for upstream
Linux kernel binfmt_misc sandboxing.

Signed-off-by: Dmitry Sepp <dmitry.sepp@virtuozzo.com>
This commit is contained in:
Dmitry Sepp 2026-02-10 11:00:04 +00:00 committed by Andrei Vagin
parent 100b3087fc
commit 0ae3a9498c
11 changed files with 5 additions and 382 deletions

View file

@ -2098,7 +2098,6 @@ static int cr_dump_finish(int ret)
unsuspend_lsm();
network_unlock();
delete_link_remaps();
clean_cr_time_mounts();
}
if (!ret && opts.lazy_pages)

View file

@ -250,9 +250,6 @@ static int crtools_prepare_shared(void)
if (!files_collected() && collect_image(&inet_sk_cinfo))
return -1;
if (collect_binfmt_misc())
return -1;
if (tty_prep_fds())
return -1;

View file

@ -32,25 +32,6 @@ static int attach_option(struct mount_info *pm, char *opt)
return pm->options ? 0 : -1;
}
#ifdef CONFIG_BINFMT_MISC_VIRTUALIZED
struct binfmt_misc_info {
BinfmtMiscEntry *bme;
struct list_head list;
};
LIST_HEAD(binfmt_misc_list);
static int binfmt_misc_parse_or_collect(struct mount_info *pm)
{
opts.has_binfmt_misc = true;
return 0;
}
static int binfmt_misc_virtual(struct mount_info *pm)
{
return kerndat_fs_virtualized(KERNDAT_FS_STAT_BINFMT_MISC, pm->s_dev);
}
static int parse_binfmt_misc_entry(struct bfd *f, BinfmtMiscEntry *bme)
{
while (1) {
@ -98,7 +79,7 @@ static int parse_binfmt_misc_entry(struct bfd *f, BinfmtMiscEntry *bme)
return 0;
}
static int dump_binfmt_misc_entry(int dfd, char *name, struct cr_img *img)
static int __maybe_unused dump_binfmt_misc_entry(int dfd, char *name, struct cr_img *img)
{
BinfmtMiscEntry bme = BINFMT_MISC_ENTRY__INIT;
struct bfd f;
@ -131,62 +112,6 @@ err:
return ret;
}
static int binfmt_misc_dump(struct mount_info *pm)
{
static bool dumped = false;
struct cr_img *img = NULL;
struct dirent *de;
DIR *fdir = NULL;
int fd, ret;
ret = binfmt_misc_virtual(pm);
if (ret <= 0)
return ret;
if (dumped) {
pr_err("Second binfmt_misc superblock\n");
return -1;
}
dumped = true;
fd = open_mountpoint(pm);
if (fd < 0)
return fd;
fdir = fdopendir(fd);
if (fdir == NULL) {
close(fd);
return -1;
}
ret = -1;
while ((de = readdir(fdir))) {
if (dir_dots(de))
continue;
if (!strcmp(de->d_name, "register"))
continue;
if (!strcmp(de->d_name, "status"))
continue;
if (!img) {
/* Create image only if an entry exists, i.e. here */
img = open_image(CR_FD_BINFMT_MISC, O_DUMP);
if (!img)
goto out;
}
if (dump_binfmt_misc_entry(fd, de->d_name, img))
goto out;
}
ret = 0;
out:
if (img)
close_image(img);
closedir(fdir);
return ret;
}
static int write_binfmt_misc_entry(char *mp, char *buf, BinfmtMiscEntry *bme)
{
int fd, len, ret = -1;
@ -267,7 +192,7 @@ static int make_bfmtm_magic_str(char *buf, BinfmtMiscEntry *bme)
return 1;
}
static int binfmt_misc_restore_bme(struct mount_info *mi, BinfmtMiscEntry *bme, char *buf)
static int __maybe_unused binfmt_misc_restore_bme(struct mount_info *mi, BinfmtMiscEntry *bme, char *buf)
{
int ret;
@ -299,83 +224,6 @@ bad_dump:
return -1;
}
static int binfmt_misc_restore(struct mount_info *mi)
{
struct cr_img *img;
char *buf;
int ret = -1;
buf = xmalloc(BINFMT_MISC_STR);
if (!buf)
return -1;
if (!list_empty(&binfmt_misc_list)) {
struct binfmt_misc_info *bmi;
list_for_each_entry(bmi, &binfmt_misc_list, list) {
ret = binfmt_misc_restore_bme(mi, bmi->bme, buf);
if (ret)
break;
}
goto free_buf;
}
img = open_image(CR_FD_BINFMT_MISC_OLD, O_RSTR, mi->s_dev);
if (!img) {
pr_err("Can't open binfmt_misc_old image\n");
goto free_buf;
} else if (empty_image(img)) {
close_image(img);
ret = 0;
goto free_buf;
}
ret = 0;
while (ret == 0) {
BinfmtMiscEntry *bme;
ret = pb_read_one_eof(img, &bme, PB_BINFMT_MISC);
if (ret <= 0)
break;
ret = binfmt_misc_restore_bme(mi, bme, buf);
binfmt_misc_entry__free_unpacked(bme, NULL);
}
close_image(img);
free_buf:
free(buf);
return ret;
}
static int collect_one_binfmt_misc_entry(void *o, ProtobufCMessage *msg, struct cr_img *img)
{
struct binfmt_misc_info *bmi = o;
bmi->bme = pb_msg(msg, BinfmtMiscEntry);
list_add_tail(&bmi->list, &binfmt_misc_list);
return 0;
}
struct collect_image_info binfmt_misc_cinfo = {
.fd_type = CR_FD_BINFMT_MISC,
.pb_type = PB_BINFMT_MISC,
.priv_size = sizeof(struct binfmt_misc_info),
.collect = collect_one_binfmt_misc_entry,
};
int collect_binfmt_misc(void)
{
return collect_image(&binfmt_misc_cinfo);
}
#else
#define binfmt_misc_dump NULL
#define binfmt_misc_restore NULL
#define binfmt_misc_parse_or_collect NULL
#endif
static int tmpfs_dump(struct mount_info *pm)
{
int ret = -1, fd = -1, userns_pid = -1;
@ -689,11 +537,7 @@ static struct fstype fstypes[] = {
},
{
.name = "binfmt_misc",
.parse = binfmt_misc_parse_or_collect,
.collect = binfmt_misc_parse_or_collect,
.code = FSTYPE__BINFMT_MISC,
.dump = binfmt_misc_dump,
.restore = binfmt_misc_restore,
},
{
.name = "tmpfs",

View file

@ -81,8 +81,6 @@ struct cr_fd_desc_tmpl imgset_template[CR_FD_MAX] = {
FD_ENTRY_F(TMPFS_IMG, "tmpfs-%u.tar.gz", O_NOBUF),
FD_ENTRY_F(TMPFS_DEV, "tmpfs-dev-%u.tar.gz", O_NOBUF),
FD_ENTRY_F(AUTOFS, "autofs-%u", O_NOBUF),
FD_ENTRY(BINFMT_MISC_OLD, "binfmt-misc-%u"),
FD_ENTRY(BINFMT_MISC, "binfmt-misc"),
FD_ENTRY(TTY_FILES, "tty"),
FD_ENTRY(TTY_INFO, "tty-info"),
FD_ENTRY_F(TTY_DATA, "tty-data", O_NOBUF),

View file

@ -181,9 +181,6 @@ struct cr_options {
bool aufs; /* auto-detected, not via cli */
bool overlayfs;
int ghost_fiemap;
#ifdef CONFIG_BINFMT_MISC_VIRTUALIZED
bool has_binfmt_misc; /* auto-detected */
#endif
size_t ghost_limit;
struct list_head irmap_scan_paths;
bool lsm_supplied;

View file

@ -27,6 +27,4 @@ extern int aufs_parse(struct mount_info *mi);
/* callback for OverlayFS support */
extern int overlayfs_parse(struct mount_info *mi);
/* FIXME -- remove */
extern struct list_head binfmt_misc_list;
#endif

View file

@ -145,14 +145,6 @@ static inline bool mnt_is_nodev_external(struct mount_info *mi)
}
extern struct ns_desc mnt_ns_desc;
#ifdef CONFIG_BINFMT_MISC_VIRTUALIZED
extern int collect_binfmt_misc(void);
#else
static inline int collect_binfmt_misc(void)
{
return 0;
}
#endif
extern struct mount_info *mnt_entry_alloc(bool rst);
extern void mnt_entry_free(struct mount_info *mi);
@ -191,7 +183,6 @@ extern int ext_mount_parse_auto(char *key);
extern int mntns_maybe_create_roots(void);
extern int read_mnt_ns_img(void);
extern void cleanup_mnt_ns(void);
extern void clean_cr_time_mounts(void);
extern char *get_plain_mountpoint(int mnt_id, char *name);
@ -221,8 +212,6 @@ extern int mnt_tree_for_each(struct mount_info *start, int (*fn)(struct mount_in
extern char *service_mountpoint(const struct mount_info *mi);
extern int validate_mounts(struct mount_info *info, bool for_dump);
extern __maybe_unused struct mount_info *add_cr_time_mount(struct mount_info *root, char *fsname, const char *path,
unsigned int s_dev, bool rst);
extern char *resolve_source(struct mount_info *mi);
extern int fetch_rt_stat(struct mount_info *m, const char *where);
extern int do_simple_mount(struct mount_info *mi, const char *src, const char *fstype, unsigned long mountflags);

View file

@ -360,11 +360,6 @@ static dev_t get_host_dev(unsigned int which)
.path = "/dev",
.magic = TMPFS_MAGIC,
},
[KERNDAT_FS_STAT_BINFMT_MISC] = {
.name = "binfmt_misc",
.path = "/proc/sys/fs/binfmt_misc",
.magic = BINFMTFS_MAGIC,
},
};
if (which >= KERNDAT_FS_STAT_MAX) {

View file

@ -1289,19 +1289,6 @@ int prepare_mnt_ns_v2(void)
if (!(root_ns_mask & CLONE_NEWNS))
return 0;
#ifdef CONFIG_BINFMT_MISC_VIRTUALIZED
if (!opts.has_binfmt_misc && !list_empty(&binfmt_misc_list)) {
/*
* Add to root yard along with other plain mounts and mntns
* directories. This mount would be created and restored by
* generic mount creation code, but it would never be moved to
* any restored mount namespaces.
*/
if (!add_cr_time_mount(root_yard_mp, "binfmt_misc", "binfmt_misc", 0, true))
return -1;
}
#endif
if (validate_mounts(mntinfo, false))
return -1;

View file

@ -1659,123 +1659,6 @@ char *get_plain_mountpoint(int mnt_id, char *name)
return xstrdup(tmp);
}
struct mount_info __maybe_unused *add_cr_time_mount(struct mount_info *root, char *fsname, const char *path,
unsigned int s_dev, bool rst)
{
struct mount_info *mi, *t, *parent;
bool add_slash = false;
int len;
mi = mnt_entry_alloc(rst);
if (!mi)
return NULL;
len = strlen(root->mountpoint);
/* It may be "./" or "./path/to/dir" */
if (root->mountpoint[len - 1] != '/') {
add_slash = true;
len++;
}
mi->mountpoint = xmalloc(len + strlen(path) + 1);
if (!mi->mountpoint)
goto err;
if (!rst)
mi->ns_mountpoint = mi->mountpoint;
if (!add_slash)
sprintf(mi->mountpoint, "%s%s", root->mountpoint, path);
else
sprintf(mi->mountpoint, "%s/%s", root->mountpoint, path);
if (rst) {
mi->plain_mountpoint = get_plain_mountpoint(-1, "crtime");
if (!mi->plain_mountpoint)
goto err;
}
mi->mnt_id = HELPER_MNT_ID;
mi->is_dir = true;
mi->flags = mi->sb_flags = 0;
mi->root = xstrdup("/");
mi->fsname = xstrdup(fsname);
mi->source = xstrdup(fsname);
mi->options = xstrdup("");
if (!mi->root || !mi->fsname || !mi->source || !mi->options)
goto err;
mi->fstype = find_fstype_by_name(fsname);
mi->s_dev = mi->s_dev_rt = s_dev;
parent = root;
while (1) {
list_for_each_entry(t, &parent->children, siblings) {
if (strstartswith(service_mountpoint(mi), service_mountpoint(t))) {
parent = t;
break;
}
}
if (&t->siblings == &parent->children)
break;
}
mi->mnt_bind_is_populated = true;
mi->is_overmounted = false;
mi->nsid = parent->nsid;
mi->parent = parent;
mi->parent_mnt_id = parent->mnt_id;
list_add(&mi->siblings, &parent->children);
pr_info("Add cr-time mountpoint %s with parent %s(%u)\n", service_mountpoint(mi), service_mountpoint(parent),
parent->mnt_id);
return mi;
err:
mnt_entry_free(mi);
return NULL;
}
/*
* Returns:
* 0 - success
* -1 - error
* 1 - skip
*/
static __maybe_unused int mount_cr_time_mount(struct ns_id *ns, unsigned int *s_dev, const char *source,
const char *target, const char *type)
{
int mnt_fd, cwd_fd, exit_code = -1;
struct stat st;
if (switch_mnt_ns(ns->ns_pid, &mnt_fd, &cwd_fd)) {
pr_err("Can't switch mnt_ns\n");
return -1;
}
if (mount(source, target, type, 0, NULL)) {
switch (errno) {
case EPERM:
case EBUSY:
case ENODEV:
case ENOENT:
pr_debug("Skipping %s as was unable to mount it: %s\n", type, strerror(errno));
exit_code = 1;
break;
default:
pr_perror("Unable to mount %s %s %s", type, source, target);
}
goto restore_ns;
}
if (stat(target, &st)) {
pr_perror("Can't stat %s", target);
goto restore_ns;
}
*s_dev = MKKDEV(major(st.st_dev), minor(st.st_dev));
exit_code = 0;
restore_ns:
if (restore_mnt_ns(mnt_fd, &cwd_fd))
exit_code = -1;
return exit_code;
}
static int dump_one_fs(struct mount_info *mi)
{
struct mount_info *pm = mi;
@ -3517,7 +3400,7 @@ void fini_restore_mntns(void)
/*
* All nested mount namespaces are restore as sub-trees of the root namespace.
*/
static int populate_roots_yard(struct mount_info *cr_time)
static int populate_roots_yard(void)
{
struct mnt_remap_entry *r;
char path[PATH_MAX];
@ -3548,28 +3431,13 @@ static int populate_roots_yard(struct mount_info *cr_time)
}
}
if (cr_time && mkdirpat(AT_FDCWD, service_mountpoint(cr_time), 0755)) {
pr_perror("Unable to create %s", service_mountpoint(cr_time));
return -1;
}
return 0;
}
static int populate_mnt_ns(void)
{
struct mount_info *cr_time = NULL;
int ret;
#ifdef CONFIG_BINFMT_MISC_VIRTUALIZED
if (!opts.has_binfmt_misc && !list_empty(&binfmt_misc_list)) {
/* Add to mount tree. Generic code will mount it later */
cr_time = add_cr_time_mount(root_yard_mp, "binfmt_misc", "binfmt_misc", 0, true);
if (!cr_time)
return -1;
}
#endif
if (resolve_shared_mounts(mntinfo))
return -1;
@ -3579,7 +3447,7 @@ static int populate_mnt_ns(void)
if (find_remap_mounts(root_yard_mp))
return -1;
if (populate_roots_yard(cr_time))
if (populate_roots_yard())
return -1;
if (mount_clean_path())
@ -3992,29 +3860,6 @@ int collect_mnt_namespaces(bool for_dump)
search_bindmounts();
#ifdef CONFIG_BINFMT_MISC_VIRTUALIZED
if (for_dump && !opts.has_binfmt_misc) {
unsigned int s_dev = 0;
struct ns_id *ns;
for (ns = ns_ids; ns != NULL; ns = ns->next) {
if (ns->type == NS_ROOT && ns->nd == &mnt_ns_desc)
break;
}
if (ns) {
ret = mount_cr_time_mount(ns, &s_dev, "binfmt_misc", "/" BINFMT_MISC_HOME, "binfmt_misc");
if (ret == -1) {
goto err;
} else if (ret == 0 && !add_cr_time_mount(ns->mnt.mntinfo_tree, "binfmt_misc", BINFMT_MISC_HOME,
s_dev, false)) {
ret = -1;
goto err;
}
}
}
#endif
ret = resolve_external_mounts(mntinfo);
if (ret)
goto err;
@ -4057,32 +3902,6 @@ int dump_mnt_namespaces(void)
return 0;
}
void clean_cr_time_mounts(void)
{
struct mount_info *mi;
int ns_old, ret;
for (mi = mntinfo; mi; mi = mi->next) {
int cwd_fd;
if (mi->mnt_id != HELPER_MNT_ID)
continue;
ret = switch_mnt_ns(mi->nsid->ns_pid, &ns_old, &cwd_fd);
if (ret) {
pr_err("Can't switch to pid's %u mnt_ns\n", mi->nsid->ns_pid);
continue;
}
if (umount(mi->ns_mountpoint) < 0)
pr_perror("Can't umount forced mount %s", mi->ns_mountpoint);
if (restore_mnt_ns(ns_old, &cwd_fd)) {
pr_err("cleanup_forced_mounts exiting with wrong mnt_ns\n");
return;
}
}
}
struct ns_desc mnt_ns_desc = NS_DESC_ENTRY(CLONE_NEWNS, "mnt");
static int call_helper_process(int (*call)(void *), void *arg)

View file

@ -1 +1 @@
{'flavor': 'ns', 'flags': 'excl suid'}
{'flavor': 'ns', 'flags': 'noauto excl suid'}