From 0a2d380e6b9110ec809101757c243ce316f4d1bb Mon Sep 17 00:00:00 2001
From: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Date: Thu, 13 Feb 2020 18:28:15 +0300
Subject: [PATCH 057/120] ghost/mount: allocate remounted_rw in shmem to get
info from other processes
Previousely remounted_rw was not shared between all processes on
restore, thus cleanup didn't got this info from rfi_remap and these
mounts were wrongly left writable after restore.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/3a1a592e7
Fixes: fd0a3cd9efb9 ("mount: remount ro mounts writable before
ghost-file restore")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
---
criu/include/mount.h | 4 ++--
criu/mount.c | 32 ++++++++++++++++++++++----------
criu/proc_parse.c | 2 +-
3 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/criu/include/mount.h b/criu/include/mount.h
index 833a75ca0..7705279e4 100644
--- a/criu/include/mount.h
+++ b/criu/include/mount.h
@@ -84,7 +84,7 @@ struct mount_info {
struct list_head postpone;
int is_overmounted;
- int remounted_rw;
+ int *remounted_rw;
void *private; /* associated filesystem data */
};
@@ -100,7 +100,7 @@ static inline int collect_binfmt_misc(void)
}
#endif
-extern struct mount_info *mnt_entry_alloc(void);
+extern struct mount_info *mnt_entry_alloc(bool rst);
extern void mnt_entry_free(struct mount_info *mi);
extern int __mntns_get_root_fd(pid_t pid);
diff --git a/criu/mount.c b/criu/mount.c
index 93725e526..d75ca5598 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -27,6 +27,7 @@
#include "external.h"
#include "clone-noasan.h"
#include "fdstore.h"
+#include "rst-malloc.h"
#include "images/mnt.pb-c.h"
@@ -1415,7 +1416,8 @@ err:
return -1;
}
-static __maybe_unused int add_cr_time_mount(struct mount_info *root, char *fsname, const char *path, unsigned int s_dev)
+static __maybe_unused int 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;
@@ -1434,7 +1436,7 @@ static __maybe_unused int add_cr_time_mount(struct mount_info *root, char *fsnam
}
}
- mi = mnt_entry_alloc();
+ mi = mnt_entry_alloc(rst);
if (!mi)
return -1;
@@ -2723,7 +2725,7 @@ err_root:
return exit_code;
}
-struct mount_info *mnt_entry_alloc()
+struct mount_info *mnt_entry_alloc(bool rst)
{
struct mount_info *new;
@@ -2734,6 +2736,13 @@ struct mount_info *mnt_entry_alloc()
new = xzalloc(sizeof(struct mount_info));
if (new) {
+ if (rst) {
+ new->remounted_rw = shmalloc(sizeof(int));
+ if (!new->remounted_rw) {
+ xfree(new);
+ return NULL;
+ }
+ }
new->fd = -1;
new->is_overmounted = -1;
INIT_LIST_HEAD(&new->children);
@@ -2956,7 +2965,7 @@ static int collect_mnt_from_image(struct mount_info **head, struct mount_info **
if (ret <= 0)
break;
- pm = mnt_entry_alloc();
+ pm = mnt_entry_alloc(true);
if (!pm)
goto err;
@@ -3234,7 +3243,7 @@ static int populate_mnt_ns(void)
{
int ret;
- root_yard_mp = mnt_entry_alloc();
+ root_yard_mp = mnt_entry_alloc(true);
if (!root_yard_mp)
return -1;
@@ -3247,7 +3256,7 @@ static int populate_mnt_ns(void)
#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 */
- ret = add_cr_time_mount(root_yard_mp, "binfmt_misc", BINFMT_MISC_HOME, 0);
+ ret = add_cr_time_mount(root_yard_mp, "binfmt_misc", BINFMT_MISC_HOME, 0, true);
if (ret)
return -1;
}
@@ -3697,7 +3706,7 @@ int collect_mnt_namespaces(bool for_dump)
ret = -1;
goto err;
} else if (ret > 0 && add_cr_time_mount(ns->mnt.mntinfo_tree, "binfmt_misc", BINFMT_MISC_HOME,
- s_dev) < 0) {
+ s_dev, false) < 0) {
ret = -1;
goto err;
}
@@ -3838,7 +3847,10 @@ int try_remount_writable(struct mount_info *mi, bool ns)
if (!ns)
remounted = REMOUNTED_RW_SERVICE;
- if (mi->flags & MS_RDONLY && !(mi->remounted_rw & remounted)) {
+ /* All mounts in mntinfo list should have it on restore */
+ BUG_ON(mi->remounted_rw == NULL);
+
+ if (mi->flags & MS_RDONLY && !(*mi->remounted_rw & remounted)) {
if (mnt_is_overmounted(mi)) {
pr_err("The mount %d is overmounted so paths are invisible\n", mi->mnt_id);
return -1;
@@ -3861,7 +3873,7 @@ int try_remount_writable(struct mount_info *mi, bool ns)
if (call_helper_process(ns_remount_writable, mi))
return -1;
}
- mi->remounted_rw |= remounted;
+ *mi->remounted_rw |= remounted;
}
return 0;
@@ -3876,7 +3888,7 @@ static int __remount_readonly_mounts(struct ns_id *ns)
if (ns && mi->nsid != ns)
continue;
- if (!(mi->remounted_rw && REMOUNTED_RW))
+ if (!(*mi->remounted_rw && REMOUNTED_RW))
continue;
/*
diff --git a/criu/proc_parse.c b/criu/proc_parse.c
index 8a9ce3a37..094f9b84e 100644
--- a/criu/proc_parse.c
+++ b/criu/proc_parse.c
@@ -1541,7 +1541,7 @@ struct mount_info *parse_mountinfo(pid_t pid, struct ns_id *nsid, bool for_dump)
int ret = -1;
char *fsname = NULL;
- new = mnt_entry_alloc();
+ new = mnt_entry_alloc(false);
if (!new)
goto end;
--
2.34.1