mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 22:35:33 +00:00
userns: check that all namespaces were created from a target userns
We enter into the target userns and try to enter in other namespaces. The "enter" operation requires CAP_SYS_ADMIN in a user namespace, where a taget namespace was created. Now if one or more namespaces were created in another userns, criu stops dumping and return an error. I want to find someone, who uses this configuration. In this case restore will be more complicated. Current version covers containers needs. Signed-off-by: Andrey Vagin <avagin@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
committed by
Pavel Emelyanov
parent
f290444655
commit
b414318c4b
52
namespaces.c
52
namespaces.c
@@ -598,12 +598,64 @@ int collect_user_namespaces(bool for_dump)
|
|||||||
return walk_namespaces(&net_ns_desc, collect_user_ns, NULL);
|
return walk_namespaces(&net_ns_desc, collect_user_ns, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_user_ns(int pid)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
pid_t chld;
|
||||||
|
|
||||||
|
chld = fork();
|
||||||
|
if (chld == -1) {
|
||||||
|
pr_perror("Unable to fork a process\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chld == 0) {
|
||||||
|
/*
|
||||||
|
* Check that we are able to enter into other namespaces
|
||||||
|
* from the target userns namespace. This signs that these
|
||||||
|
* namespaces were created from the target userns.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (switch_ns(pid, &user_ns_desc, NULL))
|
||||||
|
exit(-1);
|
||||||
|
|
||||||
|
if ((root_ns_mask & CLONE_NEWNET) &&
|
||||||
|
switch_ns(pid, &net_ns_desc, NULL))
|
||||||
|
exit(-1);
|
||||||
|
if ((root_ns_mask & CLONE_NEWUTS) &&
|
||||||
|
switch_ns(pid, &uts_ns_desc, NULL))
|
||||||
|
exit(-1);
|
||||||
|
if ((root_ns_mask & CLONE_NEWIPC) &&
|
||||||
|
switch_ns(pid, &ipc_ns_desc, NULL))
|
||||||
|
exit(-1);
|
||||||
|
if ((root_ns_mask & CLONE_NEWNS) &&
|
||||||
|
switch_ns(pid, &mnt_ns_desc, NULL))
|
||||||
|
exit(-1);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitpid(chld, &status, 0) != chld) {
|
||||||
|
pr_perror("Unable to wait the %d process", pid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
pr_err("One or more namespaces doesn't belong to the target user namespace\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int dump_user_ns(pid_t pid, int ns_id)
|
int dump_user_ns(pid_t pid, int ns_id)
|
||||||
{
|
{
|
||||||
int ret, exit_code = -1;
|
int ret, exit_code = -1;
|
||||||
UsernsEntry *e = &userns_entry;
|
UsernsEntry *e = &userns_entry;
|
||||||
struct cr_img *img;
|
struct cr_img *img;
|
||||||
|
|
||||||
|
if (check_user_ns(pid))
|
||||||
|
return -1;
|
||||||
|
|
||||||
ret = parse_id_map(pid, "uid_map", &e->uid_map);
|
ret = parse_id_map(pid, "uid_map", &e->uid_map);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
Reference in New Issue
Block a user