diff --git a/cr-dump.c b/cr-dump.c index 5eaa62472..8eb565638 100644 --- a/cr-dump.c +++ b/cr-dump.c @@ -65,7 +65,7 @@ void free_mappings(struct list_head *vma_area_list) INIT_LIST_HEAD(vma_area_list); } -static int collect_mappings(pid_t pid, struct list_head *vma_area_list) +static int collect_mappings(pid_t pid, int pid_dir, struct list_head *vma_area_list) { struct vma_area *vma_area; int ret = -1; @@ -74,7 +74,7 @@ static int collect_mappings(pid_t pid, struct list_head *vma_area_list) pr_info("Collecting mappings (pid: %d)\n", pid); pr_info("----------------------------------------\n"); - ret = parse_maps(pid, vma_area_list, true); + ret = parse_maps(pid, pid_dir, vma_area_list, true); if (ret) goto err; @@ -93,8 +93,9 @@ err_bogus_mapping: } static int dump_one_reg_file(int type, unsigned long fd_name, int lfd, - bool do_close, unsigned long pos, unsigned int flags, - char *id, struct cr_fdset *cr_fdset) + bool do_close_lfd, unsigned long pos, + unsigned int flags, char *id, + struct cr_fdset *cr_fdset) { struct fdinfo_entry e; char fd_str[128]; @@ -112,7 +113,7 @@ static int dump_one_reg_file(int type, unsigned long fd_name, int lfd, pr_info("Dumping path for %lx fd via self %d [%s]\n", fd_name, lfd, big_buffer); - if (do_close) + if (do_close_lfd) close(lfd); e.type = type; @@ -136,14 +137,14 @@ err: return ret; } -static int dump_cwd(char *path, struct cr_fdset *cr_fdset) +static int dump_cwd(int pid_dir, struct cr_fdset *cr_fdset) { int ret = -1; int fd; - fd = open(path, O_RDONLY | O_DIRECTORY); + fd = open_proc(pid_dir, "cwd"); if (fd < 0) { - pr_perror("Failed to openat %s\n", path); + pr_perror("Failed to openat cwd\n"); return -1; } @@ -234,7 +235,7 @@ err: return ret; } -static int dump_one_fd(char *pid_fd_dir, int dir, char *fd_name, unsigned long pos, +static int dump_one_fd(pid_t pid, int pid_dir, char *fd_name, unsigned long pos, unsigned int flags, char *id, struct cr_fdset *cr_fdset) { struct statfs stfs_buf; @@ -242,18 +243,18 @@ static int dump_one_fd(char *pid_fd_dir, int dir, char *fd_name, unsigned long p int err = -1; int fd = -1; - fd = openat(dir, fd_name, O_RDONLY); + fd = open_proc(pid_dir, "fd/%s", fd_name); if (fd < 0) { - err = try_dump_socket(pid_fd_dir, fd_name, cr_fdset); + err = try_dump_socket(pid, fd_name, cr_fdset); if (err != 1) return err; - pr_perror("Failed to openat %s/%d %s\n", pid_fd_dir, dir, fd_name); + pr_perror("Failed to openat %d/fd/%s\n", pid, fd_name); return -1; } if (fstat(fd, &st_buf) < 0) { - pr_perror("Can't get stat on %s\n", fd_name); + pr_perror("Can't get stat on %d/fd/%s\n", pid, fd_name); goto out_close; } @@ -263,7 +264,7 @@ static int dump_one_fd(char *pid_fd_dir, int dir, char *fd_name, unsigned long p /* skip only standard destriptors */ if (atoi(fd_name) < 3) { err = 0; - pr_info("... Skipping tty ... %s/%s\n", pid_fd_dir, fd_name); + pr_info("... Skipping tty ... %d/fd/%s\n", pid, fd_name); goto out_close; } goto err; @@ -294,13 +295,14 @@ out_close: return err; } -static int read_fd_params(pid_t pid, char *fd, unsigned long *pos, - unsigned int *flags, char *id) +static int read_fd_params(pid_t pid, int pid_dir, char *fd, + unsigned long *pos, unsigned int *flags, + char *id) { FILE *file; unsigned int f; - file = fopen_proc("%d/fdinfo/%s", "r", pid, fd); + file = fopen_proc(pid_dir, "fdinfo/%s", fd); if (!file) { pr_perror("Can't open %d's %s fdinfo\n", pid, fd); return -1; @@ -309,15 +311,14 @@ static int read_fd_params(pid_t pid, char *fd, unsigned long *pos, fscanf(file, "pos:\t%li\nflags:\t%o\nid:\t%s\n", pos, flags, id); fclose(file); - pr_info("%d fdinfo %s: pos: %16lx flags: %16o id %s\n", - pid, fd, *pos, *flags, id); + pr_info("%d fdinfo %s: pos: %16lx flags: %16o id %20s\n", + pid, fd, *pos, *flags, id); return 0; } -static int dump_task_files(pid_t pid, struct cr_fdset *cr_fdset) +static int dump_task_files(pid_t pid, int pid_dir, struct cr_fdset *cr_fdset) { - char pid_fd_dir[64]; struct dirent *de; unsigned long pos; unsigned int flags; @@ -328,26 +329,23 @@ static int dump_task_files(pid_t pid, struct cr_fdset *cr_fdset) pr_info("Dumping opened files (pid: %d)\n", pid); pr_info("----------------------------------------\n"); - snprintf(pid_fd_dir, sizeof(pid_fd_dir), "/proc/%d/cwd", pid); - if (dump_cwd(pid_fd_dir, cr_fdset)) { - pr_perror("Can't dump cwd %s\n", pid_fd_dir); + if (dump_cwd(pid_dir, cr_fdset)) { + pr_perror("Can't dump %d's cwd %s\n", pid); return -1; } - snprintf(pid_fd_dir, sizeof(pid_fd_dir), "/proc/%d/fd", pid); - fd_dir = opendir(pid_fd_dir); + fd_dir = opendir_proc(pid_dir, "fd"); if (!fd_dir) { - pr_perror("Can't open %s\n", pid_fd_dir); + pr_perror("Can't open %d's fd\n", pid); return -1; } while ((de = readdir(fd_dir))) { if (de->d_name[0] == '.') continue; - if (read_fd_params(pid, de->d_name, &pos, &flags, id)) + if (read_fd_params(pid, pid_dir, de->d_name, &pos, &flags, id)) return -1; - if (dump_one_fd(pid_fd_dir, dirfd(fd_dir), de->d_name, - pos, flags, id, cr_fdset)) + if (dump_one_fd(pid, pid_dir, de->d_name, pos, flags, id, cr_fdset)) return -1; } @@ -424,7 +422,7 @@ err: #define assign_reg(dst, src, e) dst.e = (__typeof__(dst.e))src.e #define assign_array(dst, src, e) memcpy(&dst.e, &src.e, sizeof(dst.e)) -static int get_task_stat(pid_t pid, u8 *comm, u32 *flags, +static int get_task_stat(pid_t pid, int pid_dir, u8 *comm, u32 *flags, u64 *start_code, u64 *end_code, u64 *start_data, u64 *end_data, u64 *start_stack, u64 *start_brk, @@ -439,7 +437,7 @@ static int get_task_stat(pid_t pid, u8 *comm, u32 *flags, * '0' symbol at argument 20 in format string. */ - file = fopen_proc("%d/stat", "r", pid); + file = fopen_proc(pid_dir, "stat"); if (!file) { pr_perror("Can't open %d stat\n", pid); goto err; @@ -526,7 +524,7 @@ static int get_task_stat(pid_t pid, u8 *comm, u32 *flags, * Now signals. */ fclose(file); - file = fopen_proc("%d/status", "r", pid); + file = fopen_proc(pid_dir, "status"); if (!file) { pr_perror("Can't open %d status\n", pid); goto err; @@ -550,12 +548,12 @@ err_corrupted: goto err; } -static int get_task_personality(pid_t pid, u32 *personality) +static int get_task_personality(pid_t pid, int pid_dir, u32 *personality) { FILE *file = NULL; int ret = -1; - file = fopen_proc("%d/personality", "r", pid); + file = fopen_proc(pid_dir, "personality"); if (!file) { pr_perror("Can't open %d personality\n", pid); goto err; @@ -648,7 +646,7 @@ err: return ret; } -static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset) +static int dump_task_core_seized(pid_t pid, int pid_dir, struct cr_fdset *cr_fdset) { struct core_entry *core = xzalloc(sizeof(*core)); int fd_core = cr_fdset->fds[CR_FD_CORE]; @@ -671,13 +669,13 @@ static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset) pr_info("OK\n"); pr_info("Obtainting personality ... "); - ret = get_task_personality(pid, &core->task_personality); + ret = get_task_personality(pid, pid_dir, &core->task_personality); if (ret) goto err_free; pr_info("OK\n"); pr_info("Obtainting task stat ... "); - ret = get_task_stat(pid, core->task_comm, + ret = get_task_stat(pid, pid_dir, core->task_comm, &core->task_flags, &core->mm_start_code, &core->mm_end_code, @@ -715,14 +713,14 @@ err: return ret; } -static int parse_threads(pid_t pid, struct pstree_item *item) +static int parse_threads(pid_t pid, int pid_dir, struct pstree_item *item) { struct dirent *de; DIR *dir; u32 *t = NULL; int nr = 1; - dir = opendir_proc("%d/task", pid); + dir = opendir_proc(pid_dir, "task"); if (!dir) { pr_perror("Can't open %d/task\n", pid); return -1; @@ -753,7 +751,7 @@ static int parse_threads(pid_t pid, struct pstree_item *item) return 0; } -static int parse_children(pid_t pid, struct pstree_item *item) +static int parse_children(pid_t pid, int pid_dir, struct pstree_item *item) { FILE *file; char *tok; @@ -762,8 +760,7 @@ static int parse_children(pid_t pid, struct pstree_item *item) for (i = 0; i < item->nr_threads; i++) { - file = fopen_fmt("/proc/%d/task/%d/children", "r", - pid, item->threads[i]); + file = fopen_proc(pid_dir, "task/%d/children", item->threads[i]); if (!file) { pr_perror("Can't open %d children %d\n", pid, item->threads[i]); @@ -798,7 +795,7 @@ err: return -1; } -static struct pstree_item *find_pstree_entry(pid_t pid) +static struct pstree_item *find_pstree_entry(pid_t pid, int pid_dir) { struct pstree_item *item; @@ -806,10 +803,10 @@ static struct pstree_item *find_pstree_entry(pid_t pid) if (!item) goto err; - if (parse_threads(pid, item)) + if (parse_threads(pid, pid_dir, item)) goto err_free; - if (parse_children(pid, item)) + if (parse_children(pid, pid_dir, item)) goto err_free; item->pid = pid; @@ -827,9 +824,14 @@ static int collect_pstree(pid_t pid, struct list_head *pstree_list) { struct pstree_item *item; unsigned long i; + int pid_dir; int ret = -1; - item = find_pstree_entry(pid); + pid_dir = open_pid_proc(pid); + if (pid_dir < 0) + goto err; + + item = find_pstree_entry(pid, pid_dir); if (!item) goto err; @@ -838,10 +840,12 @@ static int collect_pstree(pid_t pid, struct list_head *pstree_list) for (i = 0; i < item->nr_children; i++) { ret = collect_pstree(item->children[i], pstree_list); if (ret) - goto err; + goto err_close; } ret = 0; +err_close: + close(pid_dir); err: return ret; } @@ -1076,13 +1080,20 @@ static int dump_one_task(pid_t pid, struct cr_fdset *cr_fdset) { LIST_HEAD(vma_area_list); struct parasite_ctl *parasite_ctl; - int ret = 0; + int ret = -1; + int pid_dir; pr_info("========================================\n"); pr_info("Dumping task (pid: %d)\n", pid); pr_info("========================================\n"); - ret = collect_mappings(pid, &vma_area_list); + pid_dir = open_pid_proc(pid); + if (pid_dir < 0) { + pr_perror("Can't open %d proc dir\n", pid); + goto err; + } + + ret = collect_mappings(pid, pid_dir, &vma_area_list); if (ret) { pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret); goto err; @@ -1095,7 +1106,7 @@ static int dump_one_task(pid_t pid, struct cr_fdset *cr_fdset) goto err; } - ret = dump_task_core_seized(pid, cr_fdset); + ret = dump_task_core_seized(pid, pid_dir, cr_fdset); if (ret) { pr_err("Dump core (pid: %d) failed with %d\n", pid, ret); goto err; @@ -1131,7 +1142,7 @@ static int dump_one_task(pid_t pid, struct cr_fdset *cr_fdset) goto err; } - ret = dump_task_files(pid, cr_fdset); + ret = dump_task_files(pid, pid_dir, cr_fdset); if (ret) { pr_err("Dump files (pid: %d) failed with %d\n", pid, ret); goto err; @@ -1185,7 +1196,7 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts) struct cr_fdset *cr_fdset = NULL; struct cr_fdset *cr_fdset_thread = NULL; struct pstree_item *item; - int i, ret = -1; + int i, ret = -1, pid_dir; pr_info("========================================\n"); if (!opts->leader_only) diff --git a/cr-restore.c b/cr-restore.c index 0a41fa457..a695c96fa 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -1307,6 +1307,7 @@ static void sigreturn_restore(pid_t pstree_pid, pid_t pid) struct pstree_entry pstree_entry; int *fd_core_threads; int fd_pstree = -1; + int pid_dir; pr_info("%d: Restore via sigreturn\n", pid); @@ -1316,7 +1317,13 @@ static void sigreturn_restore(pid_t pstree_pid, pid_t pid) restore_thread_vma_len = 0; restore_shmem_vma_len = SHMEMS_SIZE; - if (parse_maps(getpid(), &self_vma_list, false)) + pid_dir = open_pid_proc(pid); + if (pid_dir < 0) + goto err; + + ret = parse_maps(getpid(), pid_dir, &self_vma_list, false); + close(pid_dir); + if (ret) goto err; /* pr_info_vma_list(&self_vma_list); */ diff --git a/include/sockets.h b/include/sockets.h index 1885a3a29..a692ab9bb 100644 --- a/include/sockets.h +++ b/include/sockets.h @@ -1,10 +1,12 @@ #ifndef CR_SOCKETS_H__ #define CR_SOCKETS_H__ +#include +#include #include struct cr_fdset; -extern int try_dump_socket(char *dir_name, char *fd_name, struct cr_fdset *cr_fdset); +extern int try_dump_socket(pid_t pid, char *fd_name, struct cr_fdset *cr_fdset); extern int collect_sockets(void); extern int prepare_sockets(int pid); diff --git a/include/util.h b/include/util.h index 2a0155f77..749ff800f 100644 --- a/include/util.h +++ b/include/util.h @@ -165,7 +165,7 @@ extern void printk_vma(struct vma_area *vma_area); #define pr_info_siginfo(siginfo) printk_siginfo(siginfo) extern int move_img_fd(int *img_fd, int want_fd); -extern int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files); +extern int parse_maps(pid_t pid, int pid_dir, struct list_head *vma_area_list, bool use_map_files); extern int close_safe(int *fd); extern int reopen_fd_as_safe(int new_fd, int old_fd, bool allow_reuse_fd); @@ -174,10 +174,10 @@ extern int reopen_fd_as_safe(int new_fd, int old_fd, bool allow_reuse_fd); extern void hex_dump(void *addr, unsigned long len); -extern DIR *opendir_proc(char *fmt, ...); -extern FILE *fopen_proc(char *fmt, char *mode, ...); -extern FILE *fopen_fmt(char *fmt, char *mode, ...); -extern int open_fmt(char *fmt, int mode, ...); +int open_pid_proc(pid_t pid); +int open_proc(int pid_dir_fd, char *fmt, ...); +DIR *opendir_proc(int pid_dir_fd, char *fmt, ...); +FILE *fopen_proc(int pid_dir_fd, char *fmt, ...); #define __xalloc(op, size, ...) \ ({ \ diff --git a/sockets.c b/sockets.c index 12881466d..ea5a18eb1 100644 --- a/sockets.c +++ b/sockets.c @@ -175,13 +175,18 @@ err: return -1; } -int try_dump_socket(char *dir, char *fd, struct cr_fdset *cr_fdset) +int try_dump_socket(pid_t pid, char *fd, struct cr_fdset *cr_fdset) { struct socket_desc *sk; struct statfs fst; struct stat st; + char path[64]; - snprintf(buf, sizeof(buf), "%s/%s", dir, fd); + /* + * Sockets are tricky, we can't open it but can + * do stats over and check for sokets magic. + */ + snprintf(buf, sizeof(buf), "/proc/%d/fd/%s", pid, fd); if (statfs(buf, &fst)) { pr_err("Can't statfs %s\n", buf); return -1; @@ -206,8 +211,10 @@ int try_dump_socket(char *dir, char *fd, struct cr_fdset *cr_fdset) return dump_one_unix(sk, fd, cr_fdset); default: pr_err("BUG! Unknown socket collected\n"); - return -1; + break; } + + return -1; } static int unix_collect_one(struct unix_diag_msg *m, struct rtattr **tb) diff --git a/util.c b/util.c index d6f48313d..f8719c7eb 100644 --- a/util.c +++ b/util.c @@ -180,12 +180,11 @@ int move_img_fd(int *img_fd, int want_fd) return 0; } -int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files) +int parse_maps(pid_t pid, int pid_dir, struct list_head *vma_area_list, bool use_map_files) { struct vma_area *vma_area = NULL; u64 start, end, pgoff; char big_buffer[1024]; - char path[64]; unsigned long ino; char r,w,x,s; int dev_maj, dev_min; @@ -194,18 +193,16 @@ int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files) DIR *map_files_dir = NULL; FILE *maps = NULL; - snprintf(path, sizeof(path), "/proc/%d/maps", pid); - maps = fopen(path, "r"); + maps = fopen_proc(pid_dir, "maps"); if (!maps) { - pr_perror("Can't open: %s\n", path); + pr_perror("Can't open %d's maps\n", pid); goto err; } if (use_map_files) { - snprintf(path, sizeof(path), "/proc/%d/map_files", pid); - map_files_dir = opendir(path); + map_files_dir = opendir_proc(pid_dir, "map_files"); if (!map_files_dir) { - pr_err("Can't open %s, old kernel?\n", path); + pr_err("Can't open %d's, old kernel?\n", pid); goto err; } } @@ -227,6 +224,8 @@ int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files) goto err; if (map_files_dir) { + char path[32]; + /* Figure out if it's file mapping */ snprintf(path, sizeof(path), "%lx-%lx", start, end); @@ -341,56 +340,6 @@ err_bogus_mapping: goto err; } -DIR *opendir_proc(char *fmt, ...) -{ - DIR *dir; - char path[128]; - va_list args; - - sprintf(path, "/proc/"); - va_start(args, fmt); - vsnprintf(path + 6, sizeof(path) - 6, fmt, args); - va_end(args); - - dir = opendir(path); - if (!dir) - pr_perror("Can't open %s\n", path); - return dir; -} - -FILE *fopen_proc(char *fmt, char *mode, ...) -{ - FILE *file; - char fname[128]; - va_list args; - - sprintf(fname, "/proc/"); - va_start(args, mode); - vsnprintf(fname + 6, sizeof(fname) - 6, fmt, args); - va_end(args); - - file = fopen(fname, mode); - if (!file) - pr_perror("Can't open %s\n", fname); - return file; -} - -FILE *fopen_fmt(char *fmt, char *mode, ...) -{ - FILE *file; - char fname[128]; - va_list args; - - va_start(args, mode); - vsnprintf(fname, sizeof(fname), fmt, args); - va_end(args); - - file = fopen(fname, mode); - if (!file) - pr_perror("Can't open %s\n", fname); - return file; -} - int open_image_ro_nocheck(const char *fmt, int pid) { char path[PATH_MAX]; @@ -424,3 +373,54 @@ int open_image_ro(int type, int pid) return fd; } + +int open_pid_proc(pid_t pid) +{ + char path[18]; + int fd; + + sprintf(path, "/proc/%d", pid); + fd = open(path, O_RDONLY); + if (fd < 0) + pr_perror("Can't open %s\n", path); + return fd; +} + +#define do_open_proc(pid_dir_fd, fmt) \ + ({ \ + char fname[64]; \ + va_list args; \ + \ + va_start(args, fmt); \ + vsnprintf(fname, sizeof(fname), fmt, args); \ + va_end(args); \ + \ + openat(pid_dir_fd, fname, O_RDONLY); \ + }) + +int open_proc(int pid_dir_fd, char *fmt, ...) +{ + return do_open_proc(pid_dir_fd, fmt); +} + +DIR *opendir_proc(int pid_dir_fd, char *fmt, ...) +{ + int dirfd; + + dirfd = do_open_proc(pid_dir_fd, fmt); + if (dirfd >= 0) + return fdopendir(dirfd); + + return NULL; +} + +FILE *fopen_proc(int pid_dir_fd, char *fmt, ...) +{ + int fd; + + fd = do_open_proc(pid_dir_fd, fmt); + if (fd >= 0) + return fdopen(fd, "r"); + + return NULL; +}