mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 14:25:49 +00:00
mem: check existence of parent images before dumping pages (v2)
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@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
committed by
Pavel Emelyanov
parent
0fc19cf7d2
commit
71a0b5dc31
@@ -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__ */
|
||||
|
9
mem.c
9
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
84
page-xfer.c
84
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;
|
||||
@@ -759,3 +766,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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user