[CRIU] [PATCH 2/3] ns: files-reg -- Don't fail to c/r if known namespace met

Cyrill Gorcunov gorcunov at openvz.org
Mon Apr 29 12:19:58 EDT 2013


In case if a task keeps a file descriptor to /proc/self/ns/$entry
and the namespace has been no switched to some new one, we should
be able to proceed c/r and simply re-open /proc/self/ns/$entry
on restore.

To achieve this we parse the link name read and if namespace
is known we substitude path with new "self" one which will
be used on restore.

Note, because calling lseek on this procfs entry causes error
we zap file position as well here and do not try to restore
it then.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 files-reg.c          | 27 +++++++++++++++++++++++----
 include/namespaces.h |  2 ++
 namespaces.c         | 22 ++++++++++++++++++++++
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/files-reg.c b/files-reg.c
index b52fe36..eaa96aa 100644
--- a/files-reg.c
+++ b/files-reg.c
@@ -18,6 +18,7 @@
 #include "protobuf/regfile.pb-c.h"
 #include "protobuf/remap-file-path.pb-c.h"
 
+#include "namespaces.h"
 #include "files-reg.h"
 
 /*
@@ -434,7 +435,9 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
 {
 	char fd_str[128];
 	char rpath[PATH_MAX + 1] = ".", *path = rpath + 1;
-	int len, rfd;
+	struct ns_proc_entry ns_proc;
+	unsigned long pos = p->pos;
+	int len, rfd, ret;
 
 	RegFileEntry rfe = REG_FILE_ENTRY__INIT;
 
@@ -449,12 +452,28 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p)
 	pr_info("Dumping path for %d fd via self %d [%s]\n",
 			p->fd, lfd, path);
 
-	if (check_path_remap(rpath, len, &p->stat, lfd, id))
+	ret = find_ns_proc_by_name(path, len, &ns_proc);
+	switch (ret) {
+	case -ENOENT:
+		if (check_path_remap(rpath, len, &p->stat, lfd, id))
+			return -1;
+		break;
+	case -EINVAL:
+		pr_err("Found NS link to an external resource %s\n", path);
 		return -1;
+		break;
+	case 0:
+		snprintf(path, sizeof(rpath) - 2, "/proc/self/ns/%s", ns_proc.name);
+		pos = 0;
+		break;
+	default:
+		BUG();
+		break;
+	}
 
 	rfe.id		= id;
 	rfe.flags	= p->flags;
-	rfe.pos		= p->pos;
+	rfe.pos		= pos;
 	rfe.fown	= (FownEntry *)&p->fown;
 	rfe.name	= path;
 
@@ -536,7 +555,7 @@ static int do_open_reg(struct reg_file_info *rfi, void *arg)
 		return fd;
 	}
 
-	if (lseek(fd, rfi->rfe->pos, SEEK_SET) < 0) {
+	if (rfi->rfe->pos && lseek(fd, rfi->rfe->pos, SEEK_SET) < 0) {
 		pr_perror("Can't restore file pos");
 		close(fd);
 		return -1;
diff --git a/include/namespaces.h b/include/namespaces.h
index f77f751..0c17501 100644
--- a/include/namespaces.h
+++ b/include/namespaces.h
@@ -47,5 +47,7 @@ struct ns_proc_entry {
 	}
 
 extern int ns_proc_entries_init(pid_t pid);
+extern int find_ns_proc_by_name(char *link, size_t len,
+				struct ns_proc_entry *found);
 
 #endif /* __CR_NS_H__ */
diff --git a/namespaces.c b/namespaces.c
index 6148166..ed391a4 100644
--- a/namespaces.c
+++ b/namespaces.c
@@ -19,6 +19,28 @@ static struct ns_proc_entry ns_proc_entries[PROC_NS_MAX] = {
 	NS_PROC_ENTRY(PROC_NS_MNT,	"mnt"),
 };
 
+int find_ns_proc_by_name(char *link, size_t len, struct ns_proc_entry *found)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ns_proc_entries); i++) {
+		size_t sz = ns_proc_entries[i].name_len;
+		char *end = NULL;
+
+		if (len < sz + 2)
+			continue;
+
+		if (link[sz] == ':' && memcmp(link, ns_proc_entries[i].name, sz) == 0) {
+			found->i_ino = strtoul(&link[sz + 2], &end, 10);
+			found->name = ns_proc_entries[i].name;
+			if (end && *end == ']')
+				return found->i_ino == ns_proc_entries[i].i_ino ? 0 : -EINVAL;
+		}
+	}
+
+	return -ENOENT;
+}
+
 int ns_proc_entries_init(pid_t pid)
 {
 	int nsfd, ret = 0;
-- 
1.8.1.4



More information about the CRIU mailing list