diff --git a/criu/apparmor.c b/criu/apparmor.c index 67553c8f1..de5840bf2 100644 --- a/criu/apparmor.c +++ b/criu/apparmor.c @@ -141,7 +141,7 @@ static int collect_profile(char *path, int offset, char *dir, AaNamespace *ns) if (!cur->blob.data) goto close; - n = read(fd, cur->blob.data, sb.st_size); + n = read_all(fd, cur->blob.data, sb.st_size); if (n < 0) { pr_perror("failed to read %s", path); goto close; diff --git a/criu/cr-dump.c b/criu/cr-dump.c index e4c78dbba..94ecae992 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -467,7 +467,7 @@ static int get_task_auxv(pid_t pid, MmEntry *mm) if (fd < 0) return -1; - ret = read(fd, mm_saved_auxv, sizeof(mm_saved_auxv)); + ret = read_all(fd, mm_saved_auxv, sizeof(mm_saved_auxv)); if (ret < 0) { ret = -1; pr_perror("Error reading %d's auxv", pid); diff --git a/criu/files-reg.c b/criu/files-reg.c index c0624f0d2..d8528f374 100644 --- a/criu/files-reg.c +++ b/criu/files-reg.c @@ -1576,7 +1576,7 @@ static int get_build_id(const int fd, const struct stat *fd_status, unsigned cha size_t mapped_size; int ret = -1; - if (read(fd, buf, SELFMAG + 1) != SELFMAG + 1) + if (read_all(fd, buf, SELFMAG + 1) != SELFMAG + 1) return -1; /* diff --git a/criu/include/util.h b/criu/include/util.h index 4e29c079e..53cd9edb8 100644 --- a/criu/include/util.h +++ b/criu/include/util.h @@ -388,6 +388,7 @@ extern char *get_legacy_iptables_bin(bool ipv6); extern ssize_t read_all(int fd, void *buf, size_t size); extern ssize_t write_all(int fd, const void *buf, size_t size); +extern ssize_t pread_all(int fd, void *buf, size_t size, off_t offset); #define cleanup_free __attribute__((cleanup(cleanup_freep))) static inline void cleanup_freep(void *p) diff --git a/criu/ipc_ns.c b/criu/ipc_ns.c index 4fe082fbb..efe0797fe 100644 --- a/criu/ipc_ns.c +++ b/criu/ipc_ns.c @@ -790,26 +790,20 @@ static int prepare_ipc_msg(int pid) static int restore_content(void *data, struct cr_img *img, const IpcShmEntry *shm) { int ifd; - ssize_t size, off; + ssize_t size, ret; ifd = img_raw_fd(img); if (ifd < 0) { pr_err("Failed getting raw image fd\n"); return -1; } - size = round_up(shm->size, sizeof(u32)); - off = 0; - do { - ssize_t ret; - - ret = read(ifd, data + off, size - off); - if (ret <= 0) { - pr_perror("Failed to write IPC shared memory data"); - return (int)ret; - } - off += ret; - } while (off < size); + size = round_up(shm->size, sizeof(u32)); + ret = read_all(ifd, data, size); + if (ret != size) { + pr_perror("Failed to write IPC shared memory data"); + return -1; + } return 0; } diff --git a/criu/kerndat.c b/criu/kerndat.c index 46a305421..6277681cc 100644 --- a/criu/kerndat.c +++ b/criu/kerndat.c @@ -71,7 +71,7 @@ static int check_pagemap(void) } /* Get the PFN of some present page. Stack is here, so try it :) */ - ret = pread(fd, &pfn, sizeof(pfn), (((unsigned long)&ret) / page_size()) * sizeof(pfn)); + ret = pread_all(fd, &pfn, sizeof(pfn), (((unsigned long)&ret) / page_size()) * sizeof(pfn)); if (ret != sizeof(pfn)) { pr_perror("Can't read pagemap"); return -1; @@ -1090,7 +1090,7 @@ static int kerndat_try_load_cache(void) return 1; } - ret = read(fd, &kdat, sizeof(kdat)); + ret = read_all(fd, &kdat, sizeof(kdat)); if (ret < 0) { pr_perror("Can't read kdat cache"); close(fd); @@ -1361,7 +1361,7 @@ static int kerndat_has_pidfd_getfd(void) goto close_all; } - if (read(fds[1], &val_b, sizeof(val_b)) != sizeof(val_b)) { + if (read_all(fds[1], &val_b, sizeof(val_b)) != sizeof(val_b)) { pr_perror("Can't read from socket"); ret = -1; goto close_all; diff --git a/criu/pagemap-cache.c b/criu/pagemap-cache.c index 00f088ff3..7a9188444 100644 --- a/criu/pagemap-cache.c +++ b/criu/pagemap-cache.c @@ -153,7 +153,7 @@ static int pmc_fill_cache(pmc_t *pmc, const struct vma_area *vma) BUG_ON(pmc->map_len < size_map); BUG_ON(pmc->fd < 0); - if (pread(pmc->fd, pmc->map, size_map, PAGEMAP_PFN_OFF(pmc->start)) != size_map) { + if (pread_all(pmc->fd, pmc->map, size_map, PAGEMAP_PFN_OFF(pmc->start)) != size_map) { pmc_zap(pmc); pr_perror("Can't read %d's pagemap file", pmc->pid); return -1; diff --git a/criu/pagemap.c b/criu/pagemap.c index 83f69bba3..97c3c4594 100644 --- a/criu/pagemap.c +++ b/criu/pagemap.c @@ -235,7 +235,6 @@ static int read_local_page(struct page_read *pr, unsigned long vaddr, unsigned l { int fd; ssize_t ret; - size_t curr = 0; fd = img_raw_fd(pr->pi); if (fd < 0) { @@ -250,15 +249,10 @@ static int read_local_page(struct page_read *pr, unsigned long vaddr, unsigned l return -1; pr_debug("\tpr%lu-%u Read page from self %lx/%" PRIx64 "\n", pr->img_id, pr->id, pr->cvaddr, pr->pi_off); - while (1) { - ret = pread(fd, buf + curr, len - curr, pr->pi_off + curr); - if (ret < 1) { - pr_perror("Can't read mapping page %zd", ret); - return -1; - } - curr += ret; - if (curr == len) - break; + ret = pread_all(fd, buf, len, pr->pi_off); + if (ret != len) { + pr_perror("Can't read mapping page %zd", ret); + return -1; } if (opts.auto_dedup) { @@ -407,7 +401,6 @@ static int maybe_read_page_img_streamer(struct page_read *pr, unsigned long vadd unsigned long len = nr * PAGE_SIZE; int fd; int ret; - size_t curr = 0; fd = img_raw_fd(pr->pi); if (fd < 0) { @@ -420,18 +413,13 @@ static int maybe_read_page_img_streamer(struct page_read *pr, unsigned long vadd /* We can't seek. The requested address better match */ BUG_ON(pr->cvaddr != vaddr); - while (1) { - ret = read(fd, buf + curr, len - curr); - if (ret == 0) { - pr_err("Reached EOF unexpectedly while reading page from image\n"); - return -1; - } else if (ret < 0) { - pr_perror("Can't read mapping page %d", ret); - return -1; - } - curr += ret; - if (curr == len) - break; + ret = read_all(fd, buf, len); + if (ret < len) { + pr_err("Reached EOF unexpectedly while reading page from image\n"); + return -1; + } else if (ret < 0) { + pr_perror("Can't read mapping page %d", ret); + return -1; } if (opts.auto_dedup) diff --git a/criu/util.c b/criu/util.c index 92ffccf38..ba185bf74 100644 --- a/criu/util.c +++ b/criu/util.c @@ -840,7 +840,7 @@ int vaddr_to_pfn(int fd, unsigned long vaddr, u64 *pfn) } off = (vaddr / page_size()) * sizeof(u64); - ret = pread(fd, pfn, sizeof(*pfn), off); + ret = pread_all(fd, pfn, sizeof(*pfn), off); if (ret != sizeof(*pfn)) { pr_perror("Can't read pme for pid %d", getpid()); ret = -1; @@ -1686,6 +1686,32 @@ ssize_t write_all(int fd, const void *buf, size_t size) return n; } +ssize_t pread_all(int fd, void *buf, size_t size, off_t offset) +{ + ssize_t n = 0; + while (size > 0) { + ssize_t ret = pread(fd, buf, size, offset); + if (ret == -1) { + if (errno == EINTR) + continue; + /* + * The caller should use standard read() for + * non-blocking I/O. + */ + if (errno == EAGAIN || errno == EWOULDBLOCK) + errno = EINVAL; + return ret; + } + if (ret == 0) + break; + n += ret; + buf = (char *)buf + ret; + size -= ret; + offset += ret; + } + return n; +} + static int remove_one(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf) { int ret;