From c69be631e15f8ed111fe217f60e36e5736642e43 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Wed, 1 Aug 2012 07:00:48 +0400 Subject: [PATCH] mntns: crtools: stat pathes relatively of a mntns root If we dump tasks with mntns, we should look at pathes from point of a mntns root. Now we support a situation when a root of an init task has the same root as the mntns root, because we have not another way to get a root of mntns. A path to an unix socket is copied, because the origin copy will be gone out from the function, where it was created. Signed-off-by: Andrey Vagin Signed-off-by: Pavel Emelyanov --- cr-dump.c | 4 ++++ files-reg.c | 13 +++++++------ include/mount.h | 3 +++ mount.c | 35 +++++++++++++++++++++++++++++++++++ sk-unix.c | 7 +++++-- 5 files changed, 54 insertions(+), 8 deletions(-) diff --git a/cr-dump.c b/cr-dump.c index e41654d2c..039a74ed5 100644 --- a/cr-dump.c +++ b/cr-dump.c @@ -45,6 +45,7 @@ #include "eventpoll.h" #include "inotify.h" #include "pstree.h" +#include "mount.h" #include "protobuf.h" #include "protobuf/fdinfo.pb-c.h" @@ -1474,6 +1475,9 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts) * in the dump stage */ + if (mntns_collect_root(root_item->pid.real)) + goto err; + collect_sockets(); glob_fdset = cr_glob_fdset_open(O_DUMP); diff --git a/files-reg.c b/files-reg.c index 54bfb9e73..e9549f1be 100644 --- a/files-reg.c +++ b/files-reg.c @@ -7,6 +7,7 @@ #include "crtools.h" +#include "mount.h" #include "files.h" #include "image.h" #include "list.h" @@ -257,7 +258,7 @@ dump_entry: &rpe, remap_file_path_entry); } -static int check_path_remap(char *path, const struct stat *ost, int lfd, u32 id) +static int check_path_remap(char *rpath, const struct stat *ost, int lfd, u32 id) { int ret; struct stat pst; @@ -269,9 +270,9 @@ static int check_path_remap(char *path, const struct stat *ost, int lfd, u32 id) * be careful whether anybody still has any of its hardlinks * also open. */ - return dump_ghost_remap(path, ost, lfd, id); + return dump_ghost_remap(rpath + 1, ost, lfd, id); - ret = stat(path, &pst); + ret = fstatat(mntns_root, rpath, &pst, 0); if (ret < 0) { /* * FIXME linked file, but path is not accessible (unless any @@ -304,13 +305,13 @@ static int check_path_remap(char *path, const struct stat *ost, int lfd, u32 id) int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p) { char fd_str[128]; - char path[PATH_MAX]; + char rpath[PATH_MAX + 1] = ".", *path = rpath + 1;; int len, rfd; RegFileEntry rfe = REG_FILE_ENTRY__INIT; snprintf(fd_str, sizeof(fd_str), "/proc/self/fd/%d", lfd); - len = readlink(fd_str, path, sizeof(path) - 1); + len = readlink(fd_str, path, sizeof(rpath) - 2); if (len < 0) { pr_perror("Can't readlink %s", fd_str); return len; @@ -320,7 +321,7 @@ int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p) pr_info("Dumping path for %d fd via self %d [%s]\n", p->fd, lfd, path); - if (check_path_remap(path, &p->stat, lfd, id)) + if (check_path_remap(rpath, &p->stat, lfd, id)) return -1; rfe.id = id; diff --git a/include/mount.h b/include/mount.h index 300807c68..eaeca4339 100644 --- a/include/mount.h +++ b/include/mount.h @@ -1,6 +1,9 @@ #ifndef MOUNT_H__ #define MOUNT_H__ +extern int mntns_root; +int mntns_collect_root(pid_t pid); + struct proc_mountinfo; extern int open_mount(unsigned int s_dev); diff --git a/mount.c b/mount.c index 1c601de7f..be907a986 100644 --- a/mount.c +++ b/mount.c @@ -22,6 +22,7 @@ #include "protobuf/mnt.pb-c.h" static struct mount_info *mntinfo; +int mntns_root = -1; int open_mount(unsigned int s_dev) { @@ -499,3 +500,37 @@ void show_mountpoints(int fd, struct cr_options *o) { pb_show_plain(fd, mnt_entry); } + +int mntns_collect_root(pid_t pid) +{ + int fd, pfd; + int ret; + char path[PATH_MAX + 1]; + + /* If /proc/pid/root links on '/', it signs that a root of the task + * and a root of mntns is the same. */ + + pfd = open_pid_proc(pid); + ret = readlinkat(pfd, "root", path, PATH_MAX); + if (ret < 0) + return ret; + + path[ret + 1] = '\0'; + + if (ret != 1 || path[0] != '/') { + pr_err("The root task has another root than mntns: %s\n", path); + close_pid_proc(); + return -1; + } + + fd = openat(pfd, "root", O_RDONLY | O_DIRECTORY, 0); + close_pid_proc(); + if (fd < 0) { + pr_perror("Can't open the task root"); + return -1; + } + + mntns_root = fd; + + return 0; +} diff --git a/sk-unix.c b/sk-unix.c index 69a4be1ff..43c408e44 100644 --- a/sk-unix.c +++ b/sk-unix.c @@ -19,6 +19,7 @@ #include "util-net.h" #include "sockets.h" #include "sk-queue.h" +#include "mount.h" #include "protobuf.h" #include "protobuf/sk-unix.pb-c.h" @@ -261,6 +262,7 @@ static int unix_collect_one(const struct unix_diag_msg *m, if (name[0] != '\0') { struct unix_diag_vfs *uv; struct stat st; + char rpath[PATH_MAX]; if (name[0] != '/') { pr_warn("Relative bind path '%s' " @@ -275,9 +277,10 @@ static int unix_collect_one(const struct unix_diag_msg *m, } uv = RTA_DATA(tb[UNIX_DIAG_VFS]); - if (stat(name, &st)) { + snprintf(rpath, sizeof(rpath), ".%s", name); + if (fstatat(mntns_root, rpath, &st, 0)) { pr_perror("Can't stat socket %d(%s)", - m->udiag_ino, name); + m->udiag_ino, rpath); goto skip; }