[CRIU] [PATCH 08/10] mount: prevent dumping mounts, if they can't be restored (v2)

Andrey Vagin avagin at openvz.org
Tue Aug 13 09:02:51 EDT 2013


Currently we check that all shared mounts have identical set of
children and that Each non-root mount has a proper root mount.

v2: check that nobody is overmounted
    check a tree before trying to restore it.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 mount.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/mount.c b/mount.c
index 7cd4e98..767aa12 100644
--- a/mount.c
+++ b/mount.c
@@ -27,6 +27,9 @@
 static struct mount_info *mntinfo;
 int mntns_root = -1;
 
+static DIR *open_mountpoint(struct mount_info *pm);
+static int close_mountpoint(DIR *dfd);
+
 static inline int is_root(char *p)
 {
 	return p[0] == '/' && p[1] == '\0';
@@ -216,6 +219,68 @@ static void mnt_tree_show(struct mount_info *tree, int off)
 	pr_info("%*s<--\n", off, "");
 }
 
+static int validate_mounts(struct mount_info *info)
+{
+	struct mount_info *m, *t;
+
+	for (m = info; m; m = m->next) {
+		if (m->parent && m->parent->shared_id) {
+			struct mount_info *ct;
+			if (list_empty(&m->parent->mnt_share))
+				continue;
+			t = list_first_entry(&m->parent->mnt_share, struct mount_info, mnt_share);
+
+			list_for_each_entry(ct, &t->children, siblings) {
+				if (mounts_equal(m, ct, false))
+					break;
+			}
+			if (&ct->siblings == &t->children) {
+				pr_err("Two shared mounts %d, %d have different sets of children\n",
+					m->parent->mnt_id, t->mnt_id);
+				pr_err("%d:%s doesn't have a proper point for %d:%s\n",
+					t->mnt_id, t->mountpoint,
+					m->mnt_id, m->mountpoint);
+				return -1;
+			}
+		}
+
+		if (m->parent && !fsroot_mounted(m)) {
+			list_for_each_entry(t, &m->mnt_bind, mnt_bind) {
+				if (fsroot_mounted(t))
+					break;
+			}
+			if (&t->mnt_bind == &m->mnt_bind) {
+				pr_err("%d:%s doesn't have a proper root mount\n",
+					t->mnt_id, t->mountpoint);
+				return -1;
+			}
+		}
+
+		if (m->parent == NULL)
+			continue;
+
+		list_for_each_entry(t, &m->parent->children, siblings) {
+			int tlen, mlen;
+
+			if (m == t)
+				continue;
+
+			tlen = strlen(t->mountpoint);
+			mlen = strlen(m->mountpoint);
+			if (mlen < tlen)
+				continue;
+			if (strncmp(t->mountpoint, m->mountpoint, tlen))
+				continue;
+			if (mlen > tlen && m->mountpoint[tlen] != '/')
+				continue;
+			pr_err("%d:%s is overmounted", m->mnt_id, m->mountpoint);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
 static int collect_shared(struct mount_info *info)
 {
 	struct mount_info *m, *t;
@@ -587,6 +652,9 @@ int dump_mnt_ns(int ns_pid, struct cr_fdset *fdset)
 	if (mnt_build_tree(pm) == NULL)
 		return -1;
 
+	if (validate_mounts(pm))
+		return -1;
+
 	pr_info("Dumping mountpoints\n");
 
 	img_fd = fdset_fd(fdset, CR_FD_MOUNTPOINTS);
@@ -1115,6 +1183,9 @@ static int populate_mnt_ns(int ns_pid)
 	if (!pms)
 		return -1;
 
+	if (validate_mounts(pms))
+		return -1;
+
 	return mnt_tree_for_each(pms, do_mount_one);
 err:
 	while (pms) {
-- 
1.8.3.1



More information about the CRIU mailing list