[CRIU] [PATCH] mem: check existence of parent images before dumping pages (v2)

Andrey Vagin avagin at openvz.org
Fri Nov 28 13:18:42 PST 2014


When we are doing pre-dump, we splice pages in pipes and only then open
images and dump pages. But when we are splicing pages, we need to know
about existence of parent images. This patch adds a new call to determin
existence of parent images.

In addition this patch fixes a following issue:
CID 83244 (#1 of 1): Uninitialized pointer read (UNINIT)
14. uninit_use: Using uninitialized value xfer.parent.

v2: initialize unused field of struct page_server_iov, because it sends
in network.

CID 83451 (#1 of 1): Uninitialized scalar variable (UNINIT)
2. uninit_use_in_call: Using uninitialized value pi. Field pi.nr_pages
is uninitialized when calling write.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 include/page-xfer.h |  2 ++
 mem.c               |  9 +++++-
 page-xfer.c         | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 94 insertions(+), 1 deletion(-)

diff --git a/include/page-xfer.h b/include/page-xfer.h
index b50065d..8492daa 100644
--- a/include/page-xfer.h
+++ b/include/page-xfer.h
@@ -42,4 +42,6 @@ extern int page_xfer_dump_pages(struct page_xfer *, struct page_pipe *,
 extern int connect_to_page_server(void);
 extern int disconnect_from_page_server(void);
 
+extern int check_parent_page_xfer(int fd_type, long id);
+
 #endif /* __CR_PAGE_XFER__H__ */
diff --git a/mem.c b/mem.c
index 9aedf37..e6af5a8 100644
--- a/mem.c
+++ b/mem.c
@@ -244,7 +244,7 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
 	pmc_t pmc = PMC_INIT;
 	struct page_pipe *pp;
 	struct vma_area *vma_area;
-	struct page_xfer xfer;
+	struct page_xfer xfer = { .parent = NULL };
 	int ret = -1;
 
 	pr_info("\n");
@@ -276,6 +276,13 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
 		ret = open_page_xfer(&xfer, CR_FD_PAGEMAP, ctl->pid.virt);
 		if (ret < 0)
 			goto out_pp;
+	} else {
+		ret = check_parent_page_xfer(CR_FD_PAGEMAP, ctl->pid.virt);
+		if (ret < 0)
+			goto out_pp;
+
+		if (ret)
+			xfer.parent = NULL + 1;
 	}
 
 	/*
diff --git a/page-xfer.c b/page-xfer.c
index 0dc8439..b02606a 100644
--- a/page-xfer.c
+++ b/page-xfer.c
@@ -6,6 +6,7 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <sys/stat.h>
 
 #include "cr_options.h"
 #include "servicefd.h"
@@ -41,6 +42,7 @@ static int open_page_local_xfer(struct page_xfer *xfer, int fd_type, long id);
 #define PS_IOV_HOLE	2
 #define PS_IOV_OPEN	3
 #define PS_IOV_OPEN2	4
+#define PS_IOV_PARENT	5
 
 #define PS_IOV_FLUSH		0x1023
 #define PS_IOV_FLUSH_N_CLOSE	0x1024
@@ -174,6 +176,8 @@ static int page_server_hole(int sk, struct page_server_iov *pi)
 	return 0;
 }
 
+static int page_server_check_parent(int sk, struct page_server_iov *pi);
+
 static int page_server_serve(int sk)
 {
 	int ret = -1;
@@ -210,6 +214,9 @@ static int page_server_serve(int sk)
 		case PS_IOV_OPEN2:
 			ret = page_server_open(sk, &pi);
 			break;
+		case PS_IOV_PARENT:
+			ret = page_server_check_parent(sk, &pi);
+			break;
 		case PS_IOV_ADD:
 			ret = page_server_add(sk, &pi);
 			break;
@@ -758,3 +765,80 @@ int open_page_xfer(struct page_xfer *xfer, int fd_type, long id)
 	else
 		return open_page_local_xfer(xfer, fd_type, id);
 }
+
+/*
+ * Return:
+ *	 1 - if a parent image exists
+ *	 0 - if a parent image doesn't exist
+ *	-1 - in error cases
+ */
+int check_parent_local_xfer(int fd_type, int id)
+{
+	char path[PATH_MAX];
+	struct stat st;
+	int ret, pfd;
+
+	pfd = openat(get_service_fd(IMG_FD_OFF), CR_PARENT_LINK, O_RDONLY);
+	if (pfd < 0 && errno == ENOENT)
+		return 0;;
+
+	snprintf(path, sizeof(path), imgset_template[fd_type].fmt, id);
+	ret = fstatat(pfd, path, &st, 0);
+	if (ret == -1 && errno != ENOENT) {
+		pr_perror("Unable to stat %s", path);
+		close(pfd);
+		return -1;
+	}
+
+	close(pfd);
+	return (ret == 0);
+}
+
+static int page_server_check_parent(int sk, struct page_server_iov *pi)
+{
+	int type, ret;
+	long id;
+
+	type = decode_pm_type(pi->dst_id);
+	id = decode_pm_id(pi->dst_id);
+
+	ret = check_parent_local_xfer(type, id);
+	if (ret < 0)
+		return -1;
+
+	if (write(sk, &ret, sizeof(ret)) != sizeof(ret)) {
+		pr_perror("Unable to send reponse");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int check_parent_server_xfer(int fd_type, long id)
+{
+	struct page_server_iov pi = {};
+	int has_parent;
+
+	pi.cmd = PS_IOV_PARENT;
+	pi.dst_id = encode_pm_id(fd_type, id);
+
+	if (write(page_server_sk, &pi, sizeof(pi)) != sizeof(pi)) {
+		pr_perror("Can't write to page server");
+		return -1;
+	}
+
+	if (read(page_server_sk, &has_parent, sizeof(int)) != sizeof(int)) {
+		pr_perror("The page server doesn't answer");
+		return -1;
+	}
+
+	return has_parent;
+}
+
+int check_parent_page_xfer(int fd_type, long id)
+{
+	if (opts.use_page_server)
+		return check_parent_server_xfer(fd_type, id);
+	else
+		return check_parent_local_xfer(fd_type, id);
+}
-- 
1.9.3



More information about the CRIU mailing list