Commit 05e3c4d2 authored by Pavel Emelyanov's avatar Pavel Emelyanov

fd: Handle close-on-exec bits

This bit is not per-file, but per-fd, thus put it on the fdinfo_entry.
Draing these bits from parasite together with the fds themselves, save
into image and restore with fcntl F_SETFD cmd where applicable.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 30224abc
...@@ -305,6 +305,7 @@ static int do_dump_gen_file(const struct fd_parms *p, int lfd, ...@@ -305,6 +305,7 @@ static int do_dump_gen_file(const struct fd_parms *p, int lfd,
e.type = p->type; e.type = p->type;
e.fd = p->fd; e.fd = p->fd;
e.id = p->id; e.id = p->id;
e.flags = p->fd_flags;
ret = fd_id_generate(p->pid, &e); ret = fd_id_generate(p->pid, &e);
if (ret == 1) /* new ID generated */ if (ret == 1) /* new ID generated */
...@@ -368,7 +369,7 @@ static int dump_task_exe_link(pid_t pid, struct mm_entry *mm) ...@@ -368,7 +369,7 @@ static int dump_task_exe_link(pid_t pid, struct mm_entry *mm)
return ret; return ret;
} }
static int fill_fd_params(pid_t pid, int fd, int lfd, struct fd_parms *p) static int fill_fd_params(pid_t pid, int fd, int lfd, char fd_flags, struct fd_parms *p)
{ {
if (fstat(lfd, &p->stat) < 0) { if (fstat(lfd, &p->stat) < 0) {
pr_perror("Can't stat fd %d\n", lfd); pr_perror("Can't stat fd %d\n", lfd);
...@@ -380,9 +381,10 @@ static int fill_fd_params(pid_t pid, int fd, int lfd, struct fd_parms *p) ...@@ -380,9 +381,10 @@ static int fill_fd_params(pid_t pid, int fd, int lfd, struct fd_parms *p)
p->flags = fcntl(lfd, F_GETFL); p->flags = fcntl(lfd, F_GETFL);
p->pid = pid; p->pid = pid;
p->id = FD_ID_INVALID; p->id = FD_ID_INVALID;
p->fd_flags = fd_flags;
pr_info("%d fdinfo %d: pos: %16lx flags: %16o\n", pr_info("%d fdinfo %d: pos: %16lx flags: %16o/%x\n",
pid, fd, p->pos, p->flags); pid, fd, p->pos, p->flags, (int)fd_flags);
return 0; return 0;
} }
...@@ -411,12 +413,12 @@ static int dump_chrdev(struct fd_parms *p, int lfd, const struct cr_fdset *set) ...@@ -411,12 +413,12 @@ static int dump_chrdev(struct fd_parms *p, int lfd, const struct cr_fdset *set)
return dump_unsupp_fd(p); return dump_unsupp_fd(p);
} }
static int dump_one_file(pid_t pid, int fd, int lfd, static int dump_one_file(pid_t pid, int fd, int lfd, char fd_flags,
const struct cr_fdset *cr_fdset) const struct cr_fdset *cr_fdset)
{ {
struct fd_parms p; struct fd_parms p;
if (fill_fd_params(pid, fd, lfd, &p) < 0) { if (fill_fd_params(pid, fd, lfd, fd_flags, &p) < 0) {
pr_perror("Can't get stat on %d", fd); pr_perror("Can't get stat on %d", fd);
return -1; return -1;
} }
...@@ -439,6 +441,7 @@ static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdse ...@@ -439,6 +441,7 @@ static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdse
int *fds, int nr_fds) int *fds, int nr_fds)
{ {
int *lfds; int *lfds;
char *flags;
int i, ret = -1; int i, ret = -1;
pr_info("\n"); pr_info("\n");
...@@ -449,20 +452,27 @@ static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdse ...@@ -449,20 +452,27 @@ static int dump_task_files_seized(struct parasite_ctl *ctl, const struct cr_fdse
if (!lfds) if (!lfds)
goto err; goto err;
ret = parasite_drain_fds_seized(ctl, fds, lfds, nr_fds); flags = xmalloc(PARASITE_MAX_FDS * sizeof(char));
if (!flags)
goto err1;
ret = parasite_drain_fds_seized(ctl, fds, lfds, nr_fds, flags);
if (ret) if (ret)
goto err; goto err2;
for (i = 0; i < nr_fds; i++) { for (i = 0; i < nr_fds; i++) {
ret = dump_one_file(ctl->pid, fds[i], lfds[i], cr_fdset); ret = dump_one_file(ctl->pid, fds[i], lfds[i], flags[i], cr_fdset);
close(lfds[i]); close(lfds[i]);
if (ret) if (ret)
goto err; goto err2;
} }
pr_info("----------------------------------------\n"); pr_info("----------------------------------------\n");
err: err2:
xfree(flags);
err1:
xfree(lfds); xfree(lfds);
err:
return ret; return ret;
} }
......
...@@ -83,8 +83,8 @@ void show_files(int fd_files, struct cr_options *o) ...@@ -83,8 +83,8 @@ void show_files(int fd_files, struct cr_options *o)
if (ret <= 0) if (ret <= 0)
goto out; goto out;
pr_msg("type: %5s fd: %5d id: %8x", pr_msg("type: %5s fd: %5d id: %8x flags %x",
fdtype2s(e.type), e.fd, e.id); fdtype2s(e.type), e.fd, e.id, e.flags);
pr_msg("\n"); pr_msg("\n");
} }
......
...@@ -172,6 +172,7 @@ static int collect_fd(int pid, struct fdinfo_entry *e) ...@@ -172,6 +172,7 @@ static int collect_fd(int pid, struct fdinfo_entry *e)
le->pid = pid; le->pid = pid;
le->fd = e->fd; le->fd = e->fd;
le->flags = e->flags;
futex_init(&le->real_pid); futex_init(&le->real_pid);
fdesc = find_file_desc(e); fdesc = find_file_desc(e);
...@@ -344,6 +345,8 @@ static int open_fd(int pid, struct fdinfo_entry *fe, ...@@ -344,6 +345,8 @@ static int open_fd(int pid, struct fdinfo_entry *fe,
if (reopen_fd_as(fe->fd, tmp)) if (reopen_fd_as(fe->fd, tmp))
return -1; return -1;
fcntl(tmp, F_SETFD, fe->flags);
sock = socket(PF_UNIX, SOCK_DGRAM, 0); sock = socket(PF_UNIX, SOCK_DGRAM, 0);
if (sock < 0) { if (sock < 0) {
pr_perror("Can't create socket"); pr_perror("Can't create socket");
...@@ -369,6 +372,8 @@ static int open_fd(int pid, struct fdinfo_entry *fe, ...@@ -369,6 +372,8 @@ static int open_fd(int pid, struct fdinfo_entry *fe,
return -1; return -1;
} }
fcntl(fle->fd, F_SETFD, fle->flags);
continue; continue;
} }
...@@ -402,7 +407,11 @@ static int receive_fd(int pid, struct fdinfo_entry *fe, struct file_desc *d) ...@@ -402,7 +407,11 @@ static int receive_fd(int pid, struct fdinfo_entry *fe, struct file_desc *d)
} }
close(fe->fd); close(fe->fd);
return reopen_fd_as(fe->fd, tmp); if (reopen_fd_as(fe->fd, tmp) < 0)
return -1;
fcntl(tmp, F_SETFD, fe->flags);
return 0;
} }
static int open_fdinfo(int pid, struct fdinfo_entry *fe, int *fdinfo_fd, int state) static int open_fdinfo(int pid, struct fdinfo_entry *fe, int *fdinfo_fd, int state)
......
...@@ -12,6 +12,7 @@ struct fd_parms { ...@@ -12,6 +12,7 @@ struct fd_parms {
unsigned long pos; unsigned long pos;
unsigned int flags; unsigned int flags;
unsigned int type; unsigned int type;
char fd_flags;
struct stat stat; struct stat stat;
u32 id; u32 id;
pid_t pid; pid_t pid;
...@@ -29,6 +30,7 @@ struct fdinfo_list_entry { ...@@ -29,6 +30,7 @@ struct fdinfo_list_entry {
struct list_head list; struct list_head list;
int fd; int fd;
int pid; int pid;
int flags;
futex_t real_pid; futex_t real_pid;
}; };
......
...@@ -58,6 +58,7 @@ struct reg_file_entry { ...@@ -58,6 +58,7 @@ struct reg_file_entry {
struct fdinfo_entry { struct fdinfo_entry {
u32 fd; u32 fd;
u8 type; u8 type;
u8 flags;
u32 id; u32 id;
} __packed; } __packed;
......
...@@ -41,7 +41,7 @@ struct parasite_dump_tid_addr; ...@@ -41,7 +41,7 @@ struct parasite_dump_tid_addr;
extern int parasite_dump_tid_addr_seized(struct parasite_ctl *ctl, extern int parasite_dump_tid_addr_seized(struct parasite_ctl *ctl,
pid_t pid, unsigned int **tid_add); pid_t pid, unsigned int **tid_add);
extern int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int nr_fds); extern int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int nr_fds, char *flags);
extern int parasite_cure_seized(struct parasite_ctl *ctl); extern int parasite_cure_seized(struct parasite_ctl *ctl);
extern struct parasite_ctl *parasite_infect_seized(pid_t pid, extern struct parasite_ctl *parasite_infect_seized(pid_t pid,
......
...@@ -547,7 +547,7 @@ out: ...@@ -547,7 +547,7 @@ out:
return ret; return ret;
} }
int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int nr_fds) int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int nr_fds, char *flags)
{ {
struct parasite_drain_fd *args; struct parasite_drain_fd *args;
parasite_status_t *st; parasite_status_t *st;
...@@ -583,7 +583,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int ...@@ -583,7 +583,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int
goto err; goto err;
} }
ret = recv_fds(sock, lfds, nr_fds, NULL); ret = recv_fds(sock, lfds, nr_fds, flags);
if (ret) { if (ret) {
pr_err("Can't retrieve FDs from socket\n"); pr_err("Can't retrieve FDs from socket\n");
goto err; goto err;
......
...@@ -373,7 +373,7 @@ static int drain_fds(struct parasite_drain_fd *args) ...@@ -373,7 +373,7 @@ static int drain_fds(struct parasite_drain_fd *args)
int ret; int ret;
ret = send_fds(tsock, &args->saddr, args->sun_len, ret = send_fds(tsock, &args->saddr, args->sun_len,
args->fds, args->nr_fds, false); args->fds, args->nr_fds, true);
if (ret) { if (ret) {
sys_write_msg("send_fds failed\n"); sys_write_msg("send_fds failed\n");
SET_PARASITE_RET(st, ret); SET_PARASITE_RET(st, ret);
......
...@@ -307,6 +307,7 @@ static int dump_one_inet(struct socket_desc *_sk, struct fd_parms *p, ...@@ -307,6 +307,7 @@ static int dump_one_inet(struct socket_desc *_sk, struct fd_parms *p,
fe.fd = p->fd; fe.fd = p->fd;
fe.type = FDINFO_INETSK; fe.type = FDINFO_INETSK;
fe.id = sk->sd.ino; fe.id = sk->sd.ino;
fe.flags = p->fd_flags;
if (write_img(fdset_fd(cr_fdset, CR_FD_FDINFO), &fe)) if (write_img(fdset_fd(cr_fdset, CR_FD_FDINFO), &fe))
goto err; goto err;
...@@ -378,6 +379,7 @@ static int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p, ...@@ -378,6 +379,7 @@ static int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
fe.fd = p->fd; fe.fd = p->fd;
fe.type = FDINFO_UNIXSK; fe.type = FDINFO_UNIXSK;
fe.id = sk->sd.ino; fe.id = sk->sd.ino;
fe.flags = p->fd_flags;
if (write_img(fdset_fd(cr_fdset, CR_FD_FDINFO), &fe)) if (write_img(fdset_fd(cr_fdset, CR_FD_FDINFO), &fe))
goto err; goto err;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment