[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