From 164ccc095f040d3da16253326fd293191f39da5f Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Sun, 22 Jan 2012 20:20:40 +0400 Subject: [PATCH] crtools: R/W API rewrite Kill all the macros for reading/writing image parts. New API looks like * write_img_buf/write_img Write an object into an image. Reports 0 for OK, -1 for error. The _buf version accepts object size as an argument, the other one uses sizeof() * read_img_buf/read_img Reads an object from image. Reports 0 for OK, -1 for error or EOF. * read_img_buf_eof/read_img Reads an object from image. Reports 1 for OK, 0 for EOF and -1 for error. This is not symmetrical with the previous one, but it was done deliberately to make it possible to write code like ret = read_img_bug_eof(); if (ret <= 0) return ret; /* 0 means OK, all is done, -1 means error was met */. ... /* 1 means object was read, can proceed */ Signed-off-by: Pavel Emelyanov Signed-off-by: Cyrill Gorcunov --- cr-dump.c | 43 ++++++++++++------- cr-restore.c | 10 +++-- cr-show.c | 105 +++++++++++++++++++-------------------------- crtools.c | 7 ++- files.c | 3 +- include/util.h | 88 +++++++++++++++++++++++++------------ libnetlink.c | 1 + parasite-syscall.c | 3 +- sockets.c | 34 ++++++++------- 9 files changed, 167 insertions(+), 127 deletions(-) diff --git a/cr-dump.c b/cr-dump.c index 1409fc892..d2141497f 100644 --- a/cr-dump.c +++ b/cr-dump.c @@ -127,8 +127,10 @@ static int dump_one_reg_file(int type, struct fd_parms *p, int lfd, pr_info("fdinfo: type: %2x len: %2x flags: %4x pos: %8x addr: %16lx\n", type, len, p->flags, p->pos, p->fd_name); - write_ptr_safe(cr_fdset->fds[CR_FD_FDINFO], &e, err); - write_safe(cr_fdset->fds[CR_FD_FDINFO], big_buffer, e.len, err); + if (write_img(cr_fdset->fds[CR_FD_FDINFO], &e)) + goto err; + if (write_img_buf(cr_fdset->fds[CR_FD_FDINFO], big_buffer, e.len)) + goto err; ret = 0; err: @@ -189,7 +191,8 @@ static int dump_pipe_and_data(int lfd, struct pipe_entry *e, } e->bytes = has_bytes; - write_ptr_safe(fd_pipes, e, err_close); + if (write_img(fd_pipes, e)) + goto err_close; if (has_bytes) { ret = splice(steal_pipe[0], NULL, fd_pipes, @@ -224,8 +227,7 @@ static int dump_one_pipe(struct fd_parms *p, unsigned int id, int lfd, if (p->flags & O_WRONLY) { e.bytes = 0; - write_ptr_safe(cr_fdset->fds[CR_FD_PIPES], &e, err); - ret = 0; + ret = write_img(cr_fdset->fds[CR_FD_PIPES], &e); } else ret = dump_pipe_and_data(lfd, &e, cr_fdset); @@ -395,7 +397,8 @@ static int dump_task_mappings(pid_t pid, struct list_head *vma_area_list, struct pr_info("shmem: s: %16lx e: %16lx shmid: %16lx\n", e.start, e.end, e.shmid); - write_ptr_safe(cr_fdset->fds[CR_FD_SHMEM], &e, err); + if (write_img(cr_fdset->fds[CR_FD_SHMEM], &e)) + goto err; } else if (vma_entry_is(vma, VMA_FILE_PRIVATE) || vma_entry_is(vma, VMA_FILE_SHARED)) { struct fd_parms p = { @@ -612,7 +615,8 @@ static int dump_task_core_seized(pid_t pid, int pid_dir, struct proc_pid_stat *s core->header.arch = HEADER_ARCH_X86_64; core->header.flags = 0; - write_ptr_safe(fd_core, core, err_free); + if (write_img(fd_core, core)) + goto err_free; pr_info("OK\n"); ret = 0; @@ -814,21 +818,24 @@ static int dump_pstree(pid_t pid, struct list_head *pstree_list, struct cr_fdset e.nr_children = item->nr_children; e.nr_threads = item->nr_threads; - write_ptr_safe(cr_fdset->fds[CR_FD_PSTREE], &e, err); + if (write_img(cr_fdset->fds[CR_FD_PSTREE], &e)) + goto err; pr_info("Children:"); for (i = 0; i < item->nr_children; i++) { pr_info(" %d", item->children[i]); - write_ptr_safe(cr_fdset->fds[CR_FD_PSTREE], - &item->children[i], err); + if (write_img(cr_fdset->fds[CR_FD_PSTREE], + &item->children[i])) + goto err; } pr_info("\n"); pr_info("Threads:\n"); for (i = 0; i < item->nr_threads; i++) { pr_info(" %d", item->threads[i]); - write_ptr_safe(cr_fdset->fds[CR_FD_PSTREE], - &item->threads[i], err); + if (write_img(cr_fdset->fds[CR_FD_PSTREE], + &item->threads[i])) + goto err; } pr_info("\n"); } @@ -889,7 +896,8 @@ static int finalize_core(pid_t pid, struct list_head *vma_area_list, struct cr_f /* Ending marker */ memzero_p(&ve); - write_ptr_safe(fd_core, &ve, err); + if (write_img(fd_core, &ve)) + goto err; pr_info("OK (%li written)\n", num); @@ -908,8 +916,10 @@ static int finalize_core(pid_t pid, struct list_head *vma_area_list, struct cr_f /* Ending marker */ if (va == 0) { - write_ptr_safe(fd_core, &zero_page_entry, err); - write_ptr_safe(fd_pages_shmem, &zero_page_entry, err); + if (write_img(fd_core, &zero_page_entry)) + goto err; + if (write_img(fd_pages_shmem, &zero_page_entry)) + goto err; break; } @@ -1007,7 +1017,8 @@ static int dump_task_thread(pid_t pid, struct cr_fdset *cr_fdset) core->header.arch = HEADER_ARCH_X86_64; core->header.flags = 0; - write_ptr_safe(fd_core, core, err_free); + if (write_img(fd_core, core)) + goto err_free; pr_info("OK\n"); ret = 0; diff --git a/cr-restore.c b/cr-restore.c index 7ae07668d..7c1932836 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -1104,7 +1104,8 @@ static inline int fork_with_pid(int pid) goto err; } - write_safe(fd, buf, strlen(buf), err_unlock); + if (write_img_buf(fd, buf, strlen(buf))) + goto err_unlock; ret = fork(); if (ret < 0) { @@ -1460,8 +1461,8 @@ static void sigreturn_restore(pid_t pstree_pid, pid_t pid) */ lseek(fd_pstree, MAGIC_OFFSET, SEEK_SET); while (1) { - ret = read_ptr_safe_eof(fd_pstree, &pstree_entry, err); - if (!ret) { + ret = read_img_eof(fd_pstree, &pstree_entry); + if (ret <= 0) { pr_perror("Pid %d not found in process tree\n", pid); goto err; } @@ -1595,7 +1596,8 @@ static void sigreturn_restore(pid_t pstree_pid, pid_t pid) */ lseek(fd_pstree, sizeof(u32) * pstree_entry.nr_children, SEEK_CUR); for (i = 0; i < pstree_entry.nr_threads; i++) { - read_ptr_safe(fd_pstree, &thread_args[i].pid, err); + if (read_img(fd_pstree, &thread_args[i].pid) < 0) + goto err; /* skip self */ if (thread_args[i].pid == pid) diff --git a/cr-show.c b/cr-show.c index 8811b8d88..eab480236 100644 --- a/cr-show.c +++ b/cr-show.c @@ -58,8 +58,10 @@ static void show_shmem(int fd_shmem) pr_img_head(CR_FD_SHMEM); while (1) { - int ret = read_ptr_safe_eof(fd_shmem, &e, out); - if (!ret) + int ret; + + ret = read_img_eof(fd_shmem, &e); + if (ret <= 0) goto out; pr_info("0x%lx-0x%lx id %lu\n", e.start, e.end, e.shmid); } @@ -75,8 +77,10 @@ static void show_files(int fd_files) pr_img_head(CR_FD_FDINFO); while (1) { - int ret = read_ptr_safe_eof(fd_files, &e, out); - if (!ret) + int ret; + + ret = read_img_eof(fd_files, &e); + if (ret <= 0) goto out; pr_info("type: %02x len: %02x flags: %4x pos: %8x addr: %16lx id: %s", @@ -107,8 +111,10 @@ static void show_pipes(int fd_pipes) pr_img_head(CR_FD_PIPES); while (1) { - int ret = read_ptr_safe_eof(fd_pipes, &e, out); - if (!ret) + int ret; + + ret = read_img_eof(fd_pipes, &e); + if (ret <= 0) goto out; pr_info("fd: %8lx pipeid: %8lx flags: %8lx bytes: %8lx\n", e.fd, e.pipeid, e.flags, e.bytes); @@ -127,7 +133,8 @@ static void show_vma(int fd_vma) pr_info("\n\t---[VMA areas]---\n"); while (1) { - read_ptr_safe(fd_vma, &ve, out); + if (read_img(fd_vma, &ve) < 0) + break; if (final_vma_entry(&ve)) break; @@ -136,8 +143,6 @@ static void show_vma(int fd_vma) vma_area.vma = ve; pr_info_vma(&vma_area); } -out: - ; /* to placate gcc */ } static void show_pages(int fd_pages, bool show_content) @@ -150,7 +155,8 @@ static void show_pages(int fd_pages, bool show_content) unsigned long addr; int i, j; - read_ptr_safe(fd_pages, &e, out); + if (read_img(fd_pages, &e) < 0) + break; if (final_page_entry(&e)) break; @@ -181,7 +187,8 @@ static void show_pages(int fd_pages, bool show_content) pr_info("\t"); for (i = 0; i < DEF_PAGES_PER_LINE; i++) { - read_ptr_safe(fd_pages, &e, out); + if (read_img(fd_pages, &e) < 0) + goto out; if (final_page_entry(&e)) { pr_info("\n"); goto out; @@ -203,8 +210,10 @@ static void show_sigacts(int fd_sigacts) pr_img_head(CR_FD_SIGACT); while (1) { - int ret = read_ptr_safe_eof(fd_sigacts, &e, out); - if (!ret) + int ret; + + ret = read_img_eof(fd_sigacts, &e); + if (ret <= 0) goto out; pr_info("sigaction: %016lx mask: %08lx " "flags: %016lx restorer: %016lx\n", @@ -229,8 +238,8 @@ static int show_pstree(int fd_pstree, struct list_head *collect) int ret; struct pstree_item *item = NULL; - ret = read_ptr_safe_eof(fd_pstree, &e, out); - if (!ret) + ret = read_img_eof(fd_pstree, &e); + if (ret <= 0) goto out; pr_info("pid: %8d nr_children: %8d nr_threads: %8d\n", e.pid, e.nr_children, e.nr_threads); @@ -255,8 +264,8 @@ static int show_pstree(int fd_pstree, struct list_head *collect) pr_info("\\\n"); pr_info(" +--- children: "); while (e.nr_children--) { - ret = read_ptr_safe_eof(fd_pstree, &pid, out); - if (!ret) + ret = read_img_eof(fd_pstree, &pid); + if (ret <= 0) goto out; pr_info(" %6d", pid); } @@ -267,8 +276,8 @@ static int show_pstree(int fd_pstree, struct list_head *collect) pr_info(" \\\n"); pr_info(" --- threads: "); while (e.nr_threads--) { - ret = read_ptr_safe_eof(fd_pstree, &pid, out); - if (!ret) + ret = read_img_eof(fd_pstree, &pid); + if (ret <= 0) goto out; pr_info(" %6d", pid); if (item) @@ -294,7 +303,8 @@ static void show_core_regs(int fd_core) lseek(fd_core, GET_FILE_OFF(struct core_entry, arch.gpregs), SEEK_SET); - read_ptr_safe(fd_core, ®s, err); + if (read_img(fd_core, ®s) < 0) + goto err; pr_regs4(regs, cs, ip, ds, es); pr_regs4(regs, ss, sp, fs, gs); @@ -311,49 +321,23 @@ err: static void show_core_rest(int fd_core) { - u64 mm_start_data, mm_end_data, mm_start_stack, mm_start_brk; - u64 mm_brk, mm_start_code, mm_end_code; - char comm[TASK_COMM_LEN]; - u32 personality; + struct task_core_entry tc; int i; - lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.personality), SEEK_SET); - read_ptr_safe(fd_core, &personality, err); - - lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.comm), SEEK_SET); - read_safe(fd_core, comm, TASK_COMM_LEN, err); - - lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_brk), SEEK_SET); - read_ptr_safe(fd_core, &mm_brk, err); - - lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_start_code), SEEK_SET); - read_ptr_safe(fd_core, &mm_start_code, err); - - lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_end_code), SEEK_SET); - read_ptr_safe(fd_core, &mm_end_code, err); - - lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_start_stack), SEEK_SET); - read_ptr_safe(fd_core, &mm_start_stack, err); - - lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_start_data), SEEK_SET); - read_ptr_safe(fd_core, &mm_start_data, err); - - lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_end_data), SEEK_SET); - read_ptr_safe(fd_core, &mm_end_data, err); - - lseek(fd_core, GET_FILE_OFF(struct core_entry, tc.mm_start_brk), SEEK_SET); - read_ptr_safe(fd_core, &mm_start_brk, err); + lseek(fd_core, GET_FILE_OFF(struct core_entry, tc), SEEK_SET); + if (read_img(fd_core, &tc) < 0) + goto err; pr_info("\n\t---[Task parameters]---\n"); - pr_info("\tPersonality: %x\n", personality); - pr_info("\tCommand: %s\n", comm); - pr_info("\tBrk: %lx\n", mm_brk); - pr_info("\tStart code: %lx\n", mm_start_code); - pr_info("\tEnd code: %lx\n", mm_end_code); - pr_info("\tStart stack: %lx\n", mm_start_stack); - pr_info("\tStart data: %lx\n", mm_start_data); - pr_info("\tEnd data: %lx\n", mm_end_data); - pr_info("\tStart brk: %lx\n", mm_start_brk); + pr_info("\tPersonality: %x\n", tc.personality); + pr_info("\tCommand: %s\n", tc.comm); + pr_info("\tBrk: %lx\n", tc.mm_brk); + pr_info("\tStart code: %lx\n", tc.mm_start_code); + pr_info("\tEnd code: %lx\n", tc.mm_end_code); + pr_info("\tStart stack: %lx\n", tc.mm_start_stack); + pr_info("\tStart data: %lx\n", tc.mm_start_data); + pr_info("\tEnd data: %lx\n", tc.mm_end_data); + pr_info("\tStart brk: %lx\n", tc.mm_start_brk); pr_info("\n"); err: @@ -410,7 +394,8 @@ static int cr_parse_file(struct cr_options *opts) goto err; } - read_ptr_safe(fd, &magic, err); + if (read_img(fd, &magic) < 0) + goto err; switch (magic) { case FDINFO_MAGIC: diff --git a/crtools.c b/crtools.c index 18bd99c12..15d19f67c 100644 --- a/crtools.c +++ b/crtools.c @@ -142,7 +142,9 @@ struct cr_fdset *cr_fdset_open(int pid, unsigned long use_mask, struct cr_fdset } pr_debug("Opened %s with %d\n", path, ret); - write_ptr_safe(ret, &fdset_template[i].magic, err); + if (write_img(ret, &fdset_template[i].magic)) + goto err; + cr_fdset->fds[i] = ret; } err: @@ -177,7 +179,8 @@ struct cr_fdset *prep_cr_fdset_for_restore(int pid, unsigned long use_mask) } pr_debug("Opened %s with %d\n", path, ret); - read_ptr_safe(ret, &magic, err); + if (read_img(ret, &magic) < 0) + goto err; if (magic != fdset_template[i].magic) { close(ret); pr_err("Magic doesn't match for %s\n", path); diff --git a/files.c b/files.c index cf2cee046..29b7ec34d 100644 --- a/files.c +++ b/files.c @@ -603,7 +603,8 @@ int try_fixup_file_map(int pid, struct vma_entry *vma_entry, int fd) lseek(fd, -sizeof(*vma_entry), SEEK_CUR); vma_entry->fd = fmap_fd->fd; - write_ptr_safe(fd, vma_entry, err); + if (write_img(fd, vma_entry)) + goto err; free(fmap_fd); } diff --git a/include/util.h b/include/util.h index 4445bd37b..efe1b03ef 100644 --- a/include/util.h +++ b/include/util.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -116,40 +117,73 @@ extern void printk(const char *format, ...); #define BUG_ON(condition) BUG_ON_HANDLER((condition)) -#define write_ptr(fd, ptr) \ - write(fd, (ptr), sizeof(*(ptr))) +/* + * Write buffer @ptr of @size bytes into @fd file + * Returns + * 0 on success + * -1 on error (error message is printed) + */ +static inline int write_img_buf(int fd, void *ptr, int size) +{ + int ret; + ret = write(fd, ptr, size); + if (ret == size) + return 0; -#define write_ptr_safe(fd, ptr, err) \ - jerr(write_ptr(fd, ptr) != sizeof(*(ptr)), err) + if (ret < 0) + pr_perror("Can't write img file\n"); + else + pr_err("Img trimmed %d/%d\n", ret, size); + return -1; +} -#define write_safe(fd, ptr, size, err) \ - jerr(write(fd, (ptr), (size)) != (size), err) +#define write_img(fd, ptr) write_img_buf((fd), (ptr), sizeof(*(ptr))) -#define write_safe_imm(fd, imm, err) \ - do { \ - typeof(imm) x__ = imm; \ - write_ptr_safe(fd, &x__, err); \ - } while (0) +/* + * Read buffer @ptr of @size bytes from @fd file + * Returns + * 1 on success + * 0 on EOF (silently) + * -1 on error (error message is printed) + */ +static inline int read_img_buf_eof(int fd, void *ptr, int size) +{ + int ret; + ret = read(fd, ptr, size); + if (ret == size) + return 1; + if (ret == 0) + return 0; -#define read_safe(fd, ptr, size, err) \ - jerr(read(fd, ptr, (size)) != (size), err) + if (ret < 0) + pr_perror("Can't read img file\n"); + else + pr_err("Img trimmed %d/%d\n", ret, size); + return -1; +} -#define read_ptr_safe(fd, ptr, err) \ - jerr(read(fd, ptr, sizeof(*(ptr))) != sizeof(*(ptr)), err) +#define read_img_eof(fd, ptr) read_img_buf_eof((fd), (ptr), sizeof(*(ptr))) -#define read_safe_eof(fd, ptr, size, err) \ - ({ \ - size_t rc__ = read(fd, ptr, (size)); \ - if (rc__ && rc__ != (size)) { \ - pr_err("img corruption %d/%d\n", \ - rc__, (size)); \ - goto err; \ - } \ - rc__; \ - }) +/* + * Read buffer @ptr of @size bytes from @fd file + * Returns + * 1 on success + * -1 on error or EOF (error message is printed) + */ +static inline int read_img_buf(int fd, void *ptr, int size) +{ + int ret; -#define read_ptr_safe_eof(fd, ptr, err) \ - read_safe_eof(fd, ptr, sizeof(*(ptr)), err) + ret = read_img_buf_eof(fd, ptr, size); + if (ret == 0) { + pr_err("Unexpected EOF\n"); + ret = -1; + } + + return ret; +} + +#define read_img(fd, ptr) read_img_buf((fd), (ptr), sizeof(*(ptr))) #define memzero_p(p) memset(p, 0, sizeof(*p)) #define memzero(p, size) memset(p, 0, size) diff --git a/libnetlink.c b/libnetlink.c index 04d7e4eb5..7e3f967c1 100644 --- a/libnetlink.c +++ b/libnetlink.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "libnetlink.h" #include "util.h" diff --git a/parasite-syscall.c b/parasite-syscall.c index 4dabaf261..ef9950fde 100644 --- a/parasite-syscall.c +++ b/parasite-syscall.c @@ -472,7 +472,8 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a lseek(cr_fdset->fds[CR_FD_PAGES], 0, SEEK_END); /* Ending page */ - write_ptr_safe(cr_fdset->fds[CR_FD_PAGES], &zero_page_entry, err_restore); + if (write_img(cr_fdset->fds[CR_FD_PAGES], &zero_page_entry)) + goto err_restore; pr_info("\n"); pr_info("Summary: %16li pages dumped\n", nrpages_dumped); diff --git a/sockets.c b/sockets.c index b39b8da55..987903dc9 100644 --- a/sockets.c +++ b/sockets.c @@ -187,7 +187,8 @@ static int dump_one_inet(struct socket_desc *_sk, int fd, struct cr_fdset *cr_fd ie.backlog = sk->wqlen; memcpy(ie.src_addr, sk->src_addr, sizeof(u32) * 4); - write_ptr_safe(cr_fdset->fds[CR_FD_INETSK], &ie, err); + if (write_img(cr_fdset->fds[CR_FD_INETSK], &ie)) + goto err; pr_info("Dumping inet socket at %d\n", fd); show_one_inet("Dumping", sk); @@ -270,8 +271,10 @@ static int dump_one_unix(struct socket_desc *_sk, int fd, struct cr_fdset *cr_fd ue.pad = 0; ue.peer = sk->peer_ino; - write_ptr_safe(cr_fdset->fds[CR_FD_UNIXSK], &ue, err); - write_safe(cr_fdset->fds[CR_FD_UNIXSK], sk->name, ue.namelen, err); + if (write_img(cr_fdset->fds[CR_FD_UNIXSK], &ue)) + goto err; + if (write_img_buf(cr_fdset->fds[CR_FD_UNIXSK], sk->name, ue.namelen)) + goto err; pr_info("Dumping unix socket at %d\n", fd); show_one_unix("Dumping", sk); @@ -941,8 +944,8 @@ static int prepare_unix_sockets(int pid) while (1) { struct unix_sk_entry ue; - ret = read_ptr_safe_eof(usk_fd, &ue, err); - if (ret == 0) + ret = read_img_eof(usk_fd, &ue); + if (ret <= 0) break; ret = open_unix_sk(&ue, &usk_fd); @@ -1025,8 +1028,8 @@ static int prepare_inet_sockets(int pid) while (1) { struct inet_sk_entry ie; - ret = read_ptr_safe_eof(isk_fd, &ie, err); - if (ret == 0) + ret = read_img_eof(isk_fd, &ie); + if (ret <= 0) break; ret = open_inet_sk(&ie, &isk_fd); @@ -1059,8 +1062,8 @@ void show_inetsk(int fd) while (1) { char src_addr[INET_ADDR_LEN] = ""; - ret = read_ptr_safe_eof(fd, &ie, out); - if (!ret) + ret = read_img_eof(fd, &ie); + if (ret <= 0) goto out; if (inet_ntop(AF_INET, (void *)ie.src_addr, src_addr, @@ -1087,27 +1090,26 @@ void show_unixsk(int fd) pr_img_head(CR_FD_UNIXSK); while (1) { - ret = read_ptr_safe_eof(fd, &ue, out); - if (!ret) + ret = read_img_eof(fd, &ue); + if (ret <= 0) goto out; pr_info("fd %4d type %2d state %2d namelen %4d backlog %4d id %6d peer %6d", ue.fd, ue.type, ue.state, ue.namelen, ue.namelen, ue.id, ue.peer); if (ue.namelen) { - ret = read_safe_eof(fd, buf, ue.namelen, out); - if (!ret) + ret = read_img_buf(fd, buf, ue.namelen); + if (ret < 0) { + pr_info("\n"); goto out; + } if (!buf[0]) buf[0] = '@'; pr_info(" --> %s\n", buf); } else pr_info("\n"); } - out: - if (ret) - pr_info("\n"); pr_img_tail(CR_FD_UNIXSK); }