mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-29 13:28:27 +00:00
creds: fail to dump when creds in thread group don't match
Since we don't support dumping per-thread creds, let's at least fail to dump if the creds don't match. Signed-off-by: Tycho Andersen <tycho.andersen@canonical.com> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
f8502fc3d1
commit
e0b24e21d3
19
cr-dump.c
19
cr-dump.c
@ -674,10 +674,10 @@ static int dump_task_core_all(struct pstree_item *item,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (item->seccomp_mode != SECCOMP_MODE_DISABLED) {
|
if (item->creds->seccomp_mode != SECCOMP_MODE_DISABLED) {
|
||||||
pr_info("got seccomp mode %d for %d\n", item->seccomp_mode, item->pid.virt);
|
pr_info("got seccomp mode %d for %d\n", item->creds->seccomp_mode, item->pid.virt);
|
||||||
core->tc->has_seccomp_mode = true;
|
core->tc->has_seccomp_mode = true;
|
||||||
core->tc->seccomp_mode = item->seccomp_mode;
|
core->tc->seccomp_mode = item->creds->seccomp_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy((char *)core->tc->comm, stat->comm, TASK_COMM_LEN);
|
strncpy((char *)core->tc->comm, stat->comm, TASK_COMM_LEN);
|
||||||
@ -809,7 +809,7 @@ static int collect_children(struct pstree_item *item)
|
|||||||
goto free;
|
goto free;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = seize_task(pid, item->pid.real, &c->seccomp_mode);
|
ret = seize_task(pid, item->pid.real, &c->creds);
|
||||||
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(),
|
||||||
@ -921,14 +921,7 @@ static int collect_threads(struct pstree_item *item)
|
|||||||
pr_info("\tSeizing %d's %d thread\n",
|
pr_info("\tSeizing %d's %d thread\n",
|
||||||
item->pid.real, pid);
|
item->pid.real, pid);
|
||||||
|
|
||||||
/*
|
ret = seize_task(pid, item_ppid(item), &item->creds);
|
||||||
* FIXME: The NULL here is wrong; we really want to get the
|
|
||||||
* seccomp state of this thread, but we have nowhere to put it,
|
|
||||||
* so for now we ignore it. We should at least check to see
|
|
||||||
* that the seccomp state is the same for all threads; we'll do
|
|
||||||
* this in a future series.
|
|
||||||
*/
|
|
||||||
ret = seize_task(pid, item_ppid(item), NULL);
|
|
||||||
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(),
|
||||||
@ -1078,7 +1071,7 @@ static int collect_pstree(pid_t pid)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
root_item->pid.real = pid;
|
root_item->pid.real = pid;
|
||||||
ret = seize_task(pid, -1, &root_item->seccomp_mode);
|
ret = seize_task(pid, -1, &root_item->creds);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err;
|
goto err;
|
||||||
pr_info("Seized task %d, state %d\n", pid, ret);
|
pr_info("Seized task %d, state %d\n", pid, ret);
|
||||||
|
10
cr-exec.c
10
cr-exec.c
@ -117,6 +117,7 @@ int cr_exec(int pid, char **opt)
|
|||||||
struct parasite_ctl *ctl;
|
struct parasite_ctl *ctl;
|
||||||
struct vm_area_list vmas;
|
struct vm_area_list vmas;
|
||||||
int ret = -1, prev_state;
|
int ret = -1, prev_state;
|
||||||
|
struct proc_status_creds *creds;
|
||||||
|
|
||||||
if (!sys_name) {
|
if (!sys_name) {
|
||||||
pr_err("Syscall name required\n");
|
pr_err("Syscall name required\n");
|
||||||
@ -129,12 +130,19 @@ int cr_exec(int pid, char **opt)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_state = ret = seize_task(pid, -1, NULL);
|
prev_state = ret = seize_task(pid, -1, &creds);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't seize a task's threads here, and there is no reason to
|
||||||
|
* compare threads' creds in this use case anyway, so let's just free
|
||||||
|
* the creds.
|
||||||
|
*/
|
||||||
|
free(creds);
|
||||||
|
|
||||||
ret = collect_mappings(pid, &vmas);
|
ret = collect_mappings(pid, &vmas);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Can't collect vmas for %d\n", pid);
|
pr_err("Can't collect vmas for %d\n", pid);
|
||||||
|
@ -1062,7 +1062,7 @@ static inline int fork_with_pid(struct pstree_item *item)
|
|||||||
|
|
||||||
item->state = ca.core->tc->task_state;
|
item->state = ca.core->tc->task_state;
|
||||||
rsti(item)->cg_set = ca.core->tc->cg_set;
|
rsti(item)->cg_set = ca.core->tc->cg_set;
|
||||||
item->seccomp_mode = ca.core->tc->seccomp_mode;
|
item->has_seccomp = ca.core->tc->seccomp_mode != SECCOMP_MODE_DISABLED;
|
||||||
|
|
||||||
if (item->state == TASK_DEAD)
|
if (item->state == TASK_DEAD)
|
||||||
rsti(item->parent)->nr_zombies++;
|
rsti(item->parent)->nr_zombies++;
|
||||||
@ -1693,7 +1693,7 @@ static void finalize_restore(int status)
|
|||||||
* doing an munmap in the process, which may be blocked by
|
* doing an munmap in the process, which may be blocked by
|
||||||
* seccomp and cause the task to be killed.
|
* seccomp and cause the task to be killed.
|
||||||
*/
|
*/
|
||||||
if (item->seccomp_mode != SECCOMP_MODE_DISABLED && suspend_seccomp(pid) < 0)
|
if (item->has_seccomp && suspend_seccomp(pid) < 0)
|
||||||
pr_err("failed to suspend seccomp, restore will probably fail...\n");
|
pr_err("failed to suspend seccomp, restore will probably fail...\n");
|
||||||
|
|
||||||
ctl = parasite_prep_ctl(pid, NULL);
|
ctl = parasite_prep_ctl(pid, NULL);
|
||||||
|
@ -88,6 +88,8 @@ struct proc_status_creds {
|
|||||||
int seccomp_mode;
|
int seccomp_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool proc_status_creds_eq(struct proc_status_creds *o1, struct proc_status_creds *o2);
|
||||||
|
|
||||||
struct mount_info;
|
struct mount_info;
|
||||||
struct fstype {
|
struct fstype {
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -25,12 +25,16 @@ struct pstree_item {
|
|||||||
int state; /* TASK_XXX constants */
|
int state; /* TASK_XXX constants */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We keep the seccomp mode here temporarily between seizing and
|
* On restore, we set this flag when process has seccomp filters so
|
||||||
* dumping the task to avoid parsing /proc/pid/status twice. We also
|
* that we know to suspend them before we unmap the restorer blob.
|
||||||
* use it on restore to hold the seccomp mode so that we don't have to
|
|
||||||
* keep track of each task's core entry in the main criu process.
|
|
||||||
*/
|
*/
|
||||||
int seccomp_mode;
|
bool has_seccomp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We keep the creds here so that we can compare creds while seizing
|
||||||
|
* threads. Dumping tasks with different creds is not supported.
|
||||||
|
*/
|
||||||
|
struct proc_status_creds *creds;
|
||||||
|
|
||||||
int nr_threads; /* number of threads */
|
int nr_threads; /* number of threads */
|
||||||
struct pid *threads; /* array of threads */
|
struct pid *threads; /* array of threads */
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "proc_parse.h"
|
||||||
|
|
||||||
/* some constants for ptrace */
|
/* some constants for ptrace */
|
||||||
#ifndef PTRACE_SEIZE
|
#ifndef PTRACE_SEIZE
|
||||||
@ -66,7 +67,7 @@ struct ptrace_peeksiginfo_args {
|
|||||||
|
|
||||||
#define SI_EVENT(_si_code) (((_si_code) & 0xFFFF) >> 8)
|
#define SI_EVENT(_si_code) (((_si_code) & 0xFFFF) >> 8)
|
||||||
|
|
||||||
extern int seize_task(pid_t pid, pid_t ppid, int *seccomp_mode);
|
extern int seize_task(pid_t pid, pid_t ppid, struct proc_status_creds **creds);
|
||||||
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);
|
||||||
|
@ -2056,3 +2056,8 @@ int aufs_parse(struct mount_info *new)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool proc_status_creds_eq(struct proc_status_creds *o1, struct proc_status_creds *o2)
|
||||||
|
{
|
||||||
|
return memcmp(o1, o2, sizeof(struct proc_status_creds)) == 0;
|
||||||
|
}
|
||||||
|
22
ptrace.c
22
ptrace.c
@ -67,13 +67,18 @@ int suspend_seccomp(pid_t pid)
|
|||||||
* up with someone else.
|
* up with someone else.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int seize_task(pid_t pid, pid_t ppid, int *seccomp_mode)
|
int seize_task(pid_t pid, pid_t ppid, struct proc_status_creds **creds)
|
||||||
{
|
{
|
||||||
siginfo_t si;
|
siginfo_t si;
|
||||||
int status;
|
int status;
|
||||||
int ret, ret2, ptrace_errno, wait_errno = 0;
|
int ret, ret2, ptrace_errno, wait_errno = 0;
|
||||||
struct proc_status_creds cr;
|
struct proc_status_creds cr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For the comparison below, let's zero out any padding.
|
||||||
|
*/
|
||||||
|
memzero(&cr, sizeof(struct proc_status_creds));
|
||||||
|
|
||||||
ret = ptrace(PTRACE_SEIZE, pid, NULL, 0);
|
ret = ptrace(PTRACE_SEIZE, pid, NULL, 0);
|
||||||
ptrace_errno = errno;
|
ptrace_errno = errno;
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
@ -111,9 +116,6 @@ try_again:
|
|||||||
if (ret2)
|
if (ret2)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (seccomp_mode)
|
|
||||||
*seccomp_mode = cr.seccomp_mode;
|
|
||||||
|
|
||||||
if (!may_dump(&cr)) {
|
if (!may_dump(&cr)) {
|
||||||
pr_err("Check uid (pid: %d) failed\n", pid);
|
pr_err("Check uid (pid: %d) failed\n", pid);
|
||||||
goto err;
|
goto err;
|
||||||
@ -166,6 +168,18 @@ try_again:
|
|||||||
goto try_again;
|
goto try_again;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*creds == NULL) {
|
||||||
|
*creds = xzalloc(sizeof(struct proc_status_creds));
|
||||||
|
if (!*creds)
|
||||||
|
goto err_stop;
|
||||||
|
|
||||||
|
**creds = cr;
|
||||||
|
|
||||||
|
} else if (!proc_status_creds_eq(*creds, &cr)) {
|
||||||
|
pr_err("creds don't match %d %d\n", pid, ppid);
|
||||||
|
goto err_stop;
|
||||||
|
}
|
||||||
|
|
||||||
if (cr.seccomp_mode != SECCOMP_MODE_DISABLED && suspend_seccomp(pid) < 0)
|
if (cr.seccomp_mode != SECCOMP_MODE_DISABLED && suspend_seccomp(pid) < 0)
|
||||||
goto err_stop;
|
goto err_stop;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user