From 97cfb7074713484947fb54650aca5b1941b6d995 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Wed, 5 Sep 2012 16:41:14 +0400 Subject: [PATCH] fown: get pid and uid-s from parasite A task may be in another pidns and crtools should get a pid from this pidns. Signed-off-by: Andrey Vagin Signed-off-by: Pavel Emelyanov --- cr-dump.c | 49 +++++++++++++------------------------- include/parasite-syscall.h | 6 +++-- include/util-net.h | 15 ++++++++++-- parasite-syscall.c | 4 ++-- util-net.c | 40 ++++++++++++++++++++++++------- 5 files changed, 67 insertions(+), 47 deletions(-) diff --git a/cr-dump.c b/cr-dump.c index 996468994..f710f4402 100644 --- a/cr-dump.c +++ b/cr-dump.c @@ -184,11 +184,9 @@ static int dump_task_exe_link(pid_t pid, MmEntry *mm) return ret; } -static int fill_fd_params(pid_t pid, int fd, int lfd, char fd_flags, struct fd_parms *p) +static int fill_fd_params(pid_t pid, int fd, int lfd, + struct fd_opts *opts, struct fd_parms *p) { - struct f_owner_ex owner_ex; - u32 v[2]; - if (fstat(lfd, &p->stat) < 0) { pr_perror("Can't stat fd %d\n", lfd); return -1; @@ -198,12 +196,12 @@ static int fill_fd_params(pid_t pid, int fd, int lfd, char fd_flags, struct fd_p p->pos = lseek(lfd, 0, SEEK_CUR); p->flags = fcntl(lfd, F_GETFL); p->pid = pid; - p->fd_flags = fd_flags; + p->fd_flags = opts->flags; fown_entry__init(&p->fown); pr_info("%d fdinfo %d: pos: 0x%16lx flags: %16o/%#x\n", - pid, fd, p->pos, p->flags, (int)fd_flags); + pid, fd, p->pos, p->flags, (int)p->fd_flags); p->fown.signum = fcntl(lfd, F_GETSIG, 0); if (p->fown.signum < 0) { @@ -211,26 +209,13 @@ static int fill_fd_params(pid_t pid, int fd, int lfd, char fd_flags, struct fd_p return -1; } - if (fcntl(lfd, F_GETOWN_EX, (long)&owner_ex)) { - pr_perror("Can't get owners on %d\n", lfd); - return -1; - } - - /* - * Simple case -- nothing is changed. - */ - if (owner_ex.pid == 0) + if (opts->fown.pid == 0) return 0; - if (fcntl(lfd, F_GETOWNER_UIDS, (long)&v)) { - pr_perror("Can't get owner uids on %d\n", lfd); - return -1; - } - - p->fown.uid = v[0]; - p->fown.euid = v[1]; - p->fown.pid_type = owner_ex.type; - p->fown.pid = owner_ex.pid; + p->fown.pid = opts->fown.pid; + p->fown.pid_type = opts->fown.pid_type; + p->fown.uid = opts->fown.uid; + p->fown.euid = opts->fown.euid; return 0; } @@ -264,13 +249,13 @@ static int dump_chrdev(struct fd_parms *p, int lfd, const struct cr_fdset *set) #define PIPEFS_MAGIC 0x50495045 #endif -static int dump_one_file(pid_t pid, int fd, int lfd, char fd_flags, +static int dump_one_file(pid_t pid, int fd, int lfd, struct fd_opts *opts, const struct cr_fdset *cr_fdset) { struct fd_parms p; struct statfs statfs; - if (fill_fd_params(pid, fd, lfd, fd_flags, &p) < 0) { + if (fill_fd_params(pid, fd, lfd, opts, &p) < 0) { pr_perror("Can't get stat on %d", fd); return -1; } @@ -316,7 +301,7 @@ static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdse struct parasite_drain_fd *dfds) { int *lfds; - char *flags; + struct fd_opts *opts; int i, ret = -1; pr_info("\n"); @@ -327,16 +312,16 @@ static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdse if (!lfds) goto err; - flags = xmalloc(dfds->nr_fds * sizeof(char)); - if (!flags) + opts = xmalloc(dfds->nr_fds * sizeof(struct fd_opts)); + if (!opts) goto err1; - ret = parasite_drain_fds_seized(ctl, dfds, lfds, flags); + ret = parasite_drain_fds_seized(ctl, dfds, lfds, opts); if (ret) goto err2; for (i = 0; i < dfds->nr_fds; i++) { - ret = dump_one_file(ctl->pid, dfds->fds[i], lfds[i], flags[i], cr_fdset); + ret = dump_one_file(ctl->pid, dfds->fds[i], lfds[i], opts + i, cr_fdset); close(lfds[i]); if (ret) goto err2; @@ -344,7 +329,7 @@ static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdse pr_info("----------------------------------------\n"); err2: - xfree(flags); + xfree(opts); err1: xfree(lfds); err: diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h index 7a7201042..1fd0dc023 100644 --- a/include/parasite-syscall.h +++ b/include/parasite-syscall.h @@ -38,8 +38,10 @@ extern int parasite_dump_thread_seized(struct parasite_ctl *ctl, pid_t pid, unsigned int **tid_add, u32 *tid); struct parasite_drain_fd; -extern int parasite_drain_fds_seized(struct parasite_ctl *ctl, struct parasite_drain_fd *dfds, - int *lfds, char *flags); +struct fd_opts; +extern int parasite_drain_fds_seized(struct parasite_ctl *ctl, + struct parasite_drain_fd *dfds, + int *lfds, struct fd_opts *flags); extern int parasite_cure_seized(struct parasite_ctl *ctl); extern struct parasite_ctl *parasite_infect_seized(pid_t pid, diff --git a/include/util-net.h b/include/util-net.h index ec5888153..a4c33c95f 100644 --- a/include/util-net.h +++ b/include/util-net.h @@ -21,16 +21,27 @@ #define CR_SCM_MSG_SIZE (1024) #define CR_SCM_MAX_FD (252) +struct fd_opts { + char flags; + struct { + uint32_t uid; + uint32_t euid; + uint32_t signum; + uint32_t pid_type; + uint32_t pid; + } fown; +}; + struct scm_fdset { struct msghdr hdr; struct iovec iov; char msg_buf[CR_SCM_MSG_SIZE]; - char msg[CR_SCM_MAX_FD]; + struct fd_opts opts[CR_SCM_MAX_FD]; }; extern int send_fds(int sock, struct sockaddr_un *saddr, int saddr_len, int *fds, int nr_fds, bool with_flags); -extern int recv_fds(int sock, int *fds, int nr_fds, char *flags); +extern int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts); static inline int send_fd(int sock, struct sockaddr_un *saddr, int saddr_len, int fd) { diff --git a/parasite-syscall.c b/parasite-syscall.c index 2c3dd4a8a..9a2747020 100644 --- a/parasite-syscall.c +++ b/parasite-syscall.c @@ -602,7 +602,7 @@ out: } int parasite_drain_fds_seized(struct parasite_ctl *ctl, - struct parasite_drain_fd *dfds, int *lfds, char *flags) + struct parasite_drain_fd *dfds, int *lfds, struct fd_opts *opts) { int ret = -1; @@ -613,7 +613,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl, goto err; } - ret = recv_fds(ctl->tsock, lfds, dfds->nr_fds, flags); + ret = recv_fds(ctl->tsock, lfds, dfds->nr_fds, opts); if (ret) { pr_err("Can't retrieve FDs from socket\n"); goto err; diff --git a/util-net.c b/util-net.c index 1d5a360e3..0feae03c6 100644 --- a/util-net.c +++ b/util-net.c @@ -28,8 +28,8 @@ static int *scm_fdset_init(struct scm_fdset *fdset, struct sockaddr_un *saddr, BUILD_BUG_ON(CR_SCM_MAX_FD > SCM_MAX_FD); BUILD_BUG_ON(sizeof(fdset->msg_buf) < (CMSG_SPACE(sizeof(int) * CR_SCM_MAX_FD))); - fdset->iov.iov_base = &fdset->msg; - fdset->iov.iov_len = with_flags ? sizeof(fdset->msg) : 1; + fdset->iov.iov_base = fdset->opts; + fdset->iov.iov_len = with_flags ? sizeof(fdset->opts) : 1; fdset->hdr.msg_iov = &fdset->iov; fdset->hdr.msg_iovlen = 1; @@ -64,13 +64,35 @@ int send_fds(int sock, struct sockaddr_un *saddr, int len, int j; for (j = 0; j < min_fd; j++) { - int flags; + int flags, fd = fds[i + j]; + struct fd_opts *p = fdset.opts + j; + struct f_owner_ex owner_ex; + u32 v[2]; - flags = sys_fcntl(fds[i + j], F_GETFD, 0); + flags = sys_fcntl(fd, F_GETFD, 0); if (flags < 0) return -1; - fdset.msg[j] = (char)flags; + p->flags = (char)flags; + + if (sys_fcntl(fd, F_GETOWN_EX, (long)&owner_ex)) + return -1; + + /* + * Simple case -- nothing is changed. + */ + if (owner_ex.pid == 0) { + p->fown.pid = 0; + continue; + } + + if (sys_fcntl(fd, F_GETOWNER_UIDS, (long)&v)) + return -1; + + p->fown.uid = v[0]; + p->fown.euid = v[1]; + p->fown.pid_type = owner_ex.type; + p->fown.pid = owner_ex.pid; } } @@ -82,7 +104,7 @@ int send_fds(int sock, struct sockaddr_un *saddr, int len, return 0; } -int recv_fds(int sock, int *fds, int nr_fds, char *flags) +int recv_fds(int sock, int *fds, int nr_fds, struct fd_opts *opts) { struct scm_fdset fdset; struct cmsghdr *cmsg; @@ -90,7 +112,7 @@ int recv_fds(int sock, int *fds, int nr_fds, char *flags) int ret; int i, min_fd; - cmsg_data = scm_fdset_init(&fdset, NULL, 0, flags != NULL); + cmsg_data = scm_fdset_init(&fdset, NULL, 0, opts != NULL); for (i = 0; i < nr_fds; i += min_fd) { min_fd = min(CR_SCM_MAX_FD, nr_fds - i); scm_fdset_init_chunk(&fdset, min_fd); @@ -120,8 +142,8 @@ int recv_fds(int sock, int *fds, int nr_fds, char *flags) if (unlikely(min_fd <= 0)) return -1; builtin_memcpy(&fds[i], cmsg_data, sizeof(int) * min_fd); - if (flags) - builtin_memcpy(flags + i, fdset.msg, sizeof(char) * min_fd); + if (opts) + builtin_memcpy(opts + i, fdset.opts, sizeof(struct fd_opts) * min_fd); } return 0;