diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h index 1fd0dc023..612d9d16b 100644 --- a/include/parasite-syscall.h +++ b/include/parasite-syscall.h @@ -42,6 +42,7 @@ 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_get_proc_fd_seized(struct parasite_ctl *ctl); extern int parasite_cure_seized(struct parasite_ctl *ctl); extern struct parasite_ctl *parasite_infect_seized(pid_t pid, diff --git a/include/parasite.h b/include/parasite.h index c62230ef6..259dfef89 100644 --- a/include/parasite.h +++ b/include/parasite.h @@ -31,6 +31,7 @@ enum { PARASITE_CMD_DUMP_MISC, PARASITE_CMD_DUMP_TID_ADDR, PARASITE_CMD_DRAIN_FDS, + PARASITE_CMD_GET_PROC_FD, PARASITE_CMD_MAX, }; diff --git a/include/syscall-x86-64.def b/include/syscall-x86-64.def index 1cdfab680..be0ed637f 100644 --- a/include/syscall-x86-64.def +++ b/include/syscall-x86-64.def @@ -40,7 +40,10 @@ __NR_wait4 61 sys_waitpid (int pid, int *status, int options, struct rusage * __NR_kill 62 sys_kill (long pid, int sig) __NR_fcntl 72 sys_fcntl (int fd, int type, long arg) __NR_flock 73 sys_flock (int fd, unsigned long cmd) +__NR_mkdir 83 sys_mkdir (const char *name, int mode) +__NR_rmdir 84 sys_rmdir (const char *name) __NR_unlink 87 sys_unlink (char *pathname) +__NR_readlink 89 sys_readlink (const char *path, char *buf, int bufsize) __NR_setresuid 117 sys_setresuid (int uid, int euid, int suid) __NR_setresgid 119 sys_setresgid (int gid, int egid, int sgid) __NR_getpgid 121 sys_getpgid (void) @@ -51,6 +54,8 @@ __NR_capset 126 sys_capset (struct cap_header *h, struct cap_data *d) __NR_personality 135 sys_personality (unsigned int personality) __NR_prctl 157 sys_prctl (int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) __NR_arch_prctl 158 sys_arch_prctl (int option, unsigned long addr) +__NR_mount 165 sys_mount (char *dev_nmae, char *dir_name, char *type, unsigned long flags, void *data) +__NR_umount2 166 sys_umount2 (char *name, int flags) __NR_gettid 186 sys_gettid (void) __NR_futex 202 sys_futex (u32 *uaddr, int op, u32 val, struct timespec *utime, u32 *uaddr2, u32 val3) __NR_set_thread_area 205 sys_set_thread_area (user_desc_t *info) diff --git a/parasite-syscall.c b/parasite-syscall.c index 9a2747020..d6164468e 100644 --- a/parasite-syscall.c +++ b/parasite-syscall.c @@ -623,6 +623,25 @@ err: return ret; } +int parasite_get_proc_fd_seized(struct parasite_ctl *ctl) +{ + int ret = -1, fd; + + ret = parasite_execute(PARASITE_CMD_GET_PROC_FD, ctl, NULL, 0); + if (ret) { + pr_err("Parasite failed to get proc fd\n"); + return ret; + } + + fd = recv_fd(ctl->tsock); + if (fd < 0) { + pr_err("Can't retrieve FD from socket\n"); + return fd; + } + + return fd; +} + int parasite_cure_seized(struct parasite_ctl *ctl) { int ret = 0; diff --git a/parasite.c b/parasite.c index 58c958d8a..18858120a 100644 --- a/parasite.c +++ b/parasite.c @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "syscall.h" #include "parasite.h" @@ -375,6 +377,58 @@ static int init(struct parasite_init_args *args) return ret; } +static char proc_mountpoint[] = "proc.crtools"; +static int parasite_get_proc_fd() +{ + int ret, fd; + char buf[2]; + + ret = sys_readlink("/proc/self", buf, sizeof(buf)); + if (ret < 0 && ret != -ENOENT) { + sys_write_msg("Can't readlink /proc/self\n"); + return ret; + } + + /* Fast path -- if /proc belongs to this pidns */ + if (ret == 1 && buf[0] == '1') { + fd = sys_open("/proc", O_RDONLY, 0); + goto out_send_fd; + } + + if (sys_mkdir(proc_mountpoint, 0700)) { + sys_write_msg("Can't create a directory "); + sys_write_msg(proc_mountpoint); + sys_write_msg("\n"); + return ret; + } + + if (sys_mount("proc", proc_mountpoint, "proc", MS_MGC_VAL, NULL)) { + sys_write_msg("mount failed\n"); + ret = -1; + goto out_rmdir; + } + + fd = sys_open(proc_mountpoint, O_RDONLY, 0); + + if (sys_umount2(proc_mountpoint, MNT_DETACH)) { + sys_write_msg("Can't umount procfs\n"); + return -1; + } + +out_rmdir: + if (sys_rmdir(proc_mountpoint)) { + sys_write_msg("Can't remove directory\n"); + return -1; + } + +out_send_fd: + if (fd < 0) + return fd; + ret = send_fd(tsock, NULL, 0, fd); + sys_close(fd); + return ret; +} + static int parasite_set_logfd() { int ret; @@ -430,6 +484,8 @@ int __used parasite_service(unsigned long cmd, void *args) return dump_tid_info((struct parasite_dump_tid_info *)args); case PARASITE_CMD_DRAIN_FDS: return drain_fds((struct parasite_drain_fd *)args); + case PARASITE_CMD_GET_PROC_FD: + return parasite_get_proc_fd(); } sys_write_msg("Unknown command to parasite\n");