Commit 903be413 authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by Andrei Vagin

seize: Make seize_wait_task() parse task status via callback

When seizeing task we need to parse /proc/pid/status for its
state, parent, signals and seccomp status.

In criu case we also parse other stuff in one go, so make
this parsing be a callback which criu will provide.
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 6e49bce7
...@@ -143,7 +143,7 @@ int cr_exec(int pid, char **opt) ...@@ -143,7 +143,7 @@ int cr_exec(int pid, char **opt)
* mess with creds in this use case anyway. * mess with creds in this use case anyway.
*/ */
prev_state = ret = seize_wait_task(pid, -1, &creds); prev_state = ret = seize_wait_task(pid, -1, parse_pid_status, &creds.s);
if (ret < 0) { if (ret < 0) {
pr_err("Can't seize task %d\n", pid); pr_err("Can't seize task %d\n", pid);
goto out; goto out;
......
...@@ -96,7 +96,7 @@ extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s); ...@@ -96,7 +96,7 @@ extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
extern unsigned int parse_pid_loginuid(pid_t pid, int *err, bool ignore_noent); extern unsigned int parse_pid_loginuid(pid_t pid, int *err, bool ignore_noent);
extern int parse_pid_oom_score_adj(pid_t pid, int *err); extern int parse_pid_oom_score_adj(pid_t pid, int *err);
extern int prepare_loginuid(unsigned int value, unsigned int loglevel); extern int prepare_loginuid(unsigned int value, unsigned int loglevel);
extern int parse_pid_status(pid_t pid, struct proc_status_creds *); extern int parse_pid_status(pid_t pid, struct seize_task_status *);
extern int parse_file_locks(void); extern int parse_file_locks(void);
extern int get_fd_mntid(int fd, int *mnt_id); extern int get_fd_mntid(int fd, int *mnt_id);
......
...@@ -70,10 +70,10 @@ struct seize_task_status { ...@@ -70,10 +70,10 @@ struct seize_task_status {
int seccomp_mode; int seccomp_mode;
}; };
struct proc_status_creds;
extern int seize_catch_task(pid_t pid); extern int seize_catch_task(pid_t pid);
extern int seize_wait_task(pid_t pid, pid_t ppid, struct proc_status_creds *creds); extern int seize_wait_task(pid_t pid, pid_t ppid,
int (*get_status)(int pid, struct seize_task_status *),
struct seize_task_status *st);
extern int suspend_seccomp(pid_t pid); extern int suspend_seccomp(pid_t pid);
extern int unseize_task(pid_t pid, int orig_state, int state); extern int unseize_task(pid_t pid, int orig_state, int state);
extern int ptrace_peek_area(pid_t pid, void *dst, void *addr, long bytes); extern int ptrace_peek_area(pid_t pid, void *dst, void *addr, long bytes);
......
...@@ -981,8 +981,9 @@ static int cap_parse(char *str, unsigned int *res) ...@@ -981,8 +981,9 @@ static int cap_parse(char *str, unsigned int *res)
return 0; return 0;
} }
int parse_pid_status(pid_t pid, struct proc_status_creds *cr) int parse_pid_status(pid_t pid, struct seize_task_status *ss)
{ {
struct proc_status_creds *cr = container_of(ss, struct proc_status_creds, s);
struct bfd f; struct bfd f;
int done = 0; int done = 0;
int ret = -1; int ret = -1;
......
...@@ -148,7 +148,9 @@ static int skip_sigstop(int pid, int nr_signals) ...@@ -148,7 +148,9 @@ static int skip_sigstop(int pid, int nr_signals)
* of it so the task would not know if it was saddled * of it so the task would not know if it was saddled
* up with someone else. * up with someone else.
*/ */
int seize_wait_task(pid_t pid, pid_t ppid, struct proc_status_creds *creds) int seize_wait_task(pid_t pid, pid_t ppid,
int (*get_status)(int pid, struct seize_task_status *),
struct seize_task_status *ss)
{ {
siginfo_t si; siginfo_t si;
int status, nr_sigstop; int status, nr_sigstop;
...@@ -175,17 +177,17 @@ try_again: ...@@ -175,17 +177,17 @@ try_again:
wait_errno = errno; wait_errno = errno;
} }
ret2 = parse_pid_status(pid, creds); ret2 = get_status(pid, ss);
if (ret2) if (ret2)
goto err; goto err;
if (ret < 0 || WIFEXITED(status) || WIFSIGNALED(status)) { if (ret < 0 || WIFEXITED(status) || WIFSIGNALED(status)) {
if (creds->s.state != 'Z') { if (ss->state != 'Z') {
if (pid == getpid()) if (pid == getpid())
pr_err("The criu itself is within dumped tree.\n"); pr_err("The criu itself is within dumped tree.\n");
else else
pr_err("Unseizable non-zombie %d found, state %c, err %d/%d\n", pr_err("Unseizable non-zombie %d found, state %c, err %d/%d\n",
pid, creds->s.state, ret, wait_errno); pid, ss->state, ret, wait_errno);
return -1; return -1;
} }
...@@ -195,9 +197,9 @@ try_again: ...@@ -195,9 +197,9 @@ try_again:
return TASK_DEAD; return TASK_DEAD;
} }
if ((ppid != -1) && (creds->s.ppid != ppid)) { if ((ppid != -1) && (ss->ppid != ppid)) {
pr_err("Task pid reused while suspending (%d: %d -> %d)\n", pr_err("Task pid reused while suspending (%d: %d -> %d)\n",
pid, ppid, creds->s.ppid); pid, ppid, ss->ppid);
goto err; goto err;
} }
...@@ -229,13 +231,13 @@ try_again: ...@@ -229,13 +231,13 @@ try_again:
goto try_again; goto try_again;
} }
if (creds->s.seccomp_mode != SECCOMP_MODE_DISABLED && suspend_seccomp(pid) < 0) if (ss->seccomp_mode != SECCOMP_MODE_DISABLED && suspend_seccomp(pid) < 0)
goto err; goto err;
nr_sigstop = 0; nr_sigstop = 0;
if (creds->s.sigpnd & (1 << (SIGSTOP - 1))) if (ss->sigpnd & (1 << (SIGSTOP - 1)))
nr_sigstop++; nr_sigstop++;
if (creds->s.shdpnd & (1 << (SIGSTOP - 1))) if (ss->shdpnd & (1 << (SIGSTOP - 1)))
nr_sigstop++; nr_sigstop++;
if (si.si_signo == SIGSTOP) if (si.si_signo == SIGSTOP)
nr_sigstop++; nr_sigstop++;
......
...@@ -488,7 +488,7 @@ static int collect_children(struct pstree_item *item) ...@@ -488,7 +488,7 @@ static int collect_children(struct pstree_item *item)
goto free; goto free;
} }
ret = seize_wait_task(pid, item->pid->real, creds); ret = seize_wait_task(pid, item->pid->real, parse_pid_status, &creds->s);
if (ret < 0) { if (ret < 0) {
/* /*
* Here is a race window between parse_children() and seize(), * Here is a race window between parse_children() and seize(),
...@@ -714,7 +714,7 @@ static int collect_threads(struct pstree_item *item) ...@@ -714,7 +714,7 @@ static int collect_threads(struct pstree_item *item)
if (!opts.freeze_cgroup && seize_catch_task(pid)) if (!opts.freeze_cgroup && seize_catch_task(pid))
continue; continue;
ret = seize_wait_task(pid, item_ppid(item), &t_creds); ret = seize_wait_task(pid, item_ppid(item), parse_pid_status, &t_creds.s);
if (ret < 0) { if (ret < 0) {
/* /*
* Here is a race window between parse_threads() and seize(), * Here is a race window between parse_threads() and seize(),
...@@ -853,7 +853,7 @@ int collect_pstree(void) ...@@ -853,7 +853,7 @@ int collect_pstree(void)
if (!creds) if (!creds)
goto err; goto err;
ret = seize_wait_task(pid, -1, creds); ret = seize_wait_task(pid, -1, parse_pid_status, &creds->s);
if (ret < 0) if (ret < 0)
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