Commit 790ec469 authored by Dengguangxing's avatar Dengguangxing Committed by Pavel Emelyanov

join-ns: perform join_namespace according to join-ns opts

Signed-off-by: 's avatarDeng Guangxing <dengguangxing@huawei.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 2cf17cd8
......@@ -1220,6 +1220,11 @@ static int restore_task_with_children(void *_arg)
/* Restore root task */
if (current->parent == NULL) {
if (join_namespaces()) {
pr_perror("Join namespaces failed");
goto err;
}
pr_info("Calling restore_sid() for init\n");
restore_sid();
......
......@@ -146,6 +146,7 @@ extern int dump_user_ns(pid_t pid, int ns_id);
extern void free_userns_maps(void);
extern int join_ns_add(const char *type, char *ns_file, char *extra_opts);
extern int check_namespace_opts(void);
extern int join_namespaces(void);
typedef int (*uns_call_t)(void *arg, int fd, pid_t pid);
/*
......
......@@ -1516,6 +1516,126 @@ static int prepare_userns_creds()
return 0;
}
static int get_join_ns_fd(struct join_ns *jn)
{
int pid, fd;
char nsf[32];
char *pnsf;
pid = atoi(jn->ns_file);
if (pid > 0) {
snprintf(nsf, sizeof(nsf), "/proc/%d/ns/%s", pid, jn->nd->str);
pnsf = nsf;
} else {
pnsf = jn->ns_file;
}
fd = open(pnsf, O_RDONLY);
if (fd < 0) {
pr_perror("Can't open ns file: %s", pnsf);
return -1;
}
jn->ns_fd = fd;
return 0;
}
static int switch_join_ns(struct join_ns *jn)
{
struct stat st, self_st;
char buf[32];
if (jn->nd == &user_ns_desc) {
/* It is not permitted to use setns() to reenter the caller's current
* user namespace. This prevents a caller that has dropped capabilities
* from regaining those capabilities via a call to setns()
*/
if (fstat(jn->ns_fd, &st) == -1) {
pr_perror("Can't get ns file %s stat", jn->ns_file);
return -1;
}
snprintf(buf, sizeof(buf), "/proc/self/ns/%s", jn->nd->str);
if (stat(buf, &self_st) == -1) {
pr_perror("Can't get ns file %s stat", buf);
return -1;
}
if (st.st_ino == self_st.st_ino)
return 0;
}
if (setns(jn->ns_fd, jn->nd->cflag)) {
pr_perror("Failed to setns when join-ns %s:%s", jn->nd->str, jn->ns_file);
return -1;
}
return 0;
}
static int switch_user_join_ns(struct join_ns *jn)
{
uid_t uid;
gid_t gid;
if (jn == NULL)
return 0;
if (switch_join_ns(jn))
return -1;
if (jn->extra_opts.user_extra.uid == NULL)
uid = getuid();
else
uid = atoi(jn->extra_opts.user_extra.uid);
if (jn->extra_opts.user_extra.gid == NULL)
gid = getgid();
else
gid = atoi(jn->extra_opts.user_extra.gid);
/* FIXME:
* if err occurs in setuid/setgid, should we just alert or
* return an error
*/
if (setuid(uid)) {
pr_perror("setuid failed while joining userns");
return -1;
}
if (setgid(gid)) {
pr_perror("setgid failed while joining userns");
return -1;
}
return 0;
}
int join_namespaces(void)
{
struct join_ns *jn, *user_jn = NULL;
int ret = -1;
list_for_each_entry(jn, &opts.join_ns, list)
if (get_join_ns_fd(jn))
goto err_out;
list_for_each_entry(jn, &opts.join_ns, list)
if (jn->nd == &user_ns_desc) {
user_jn = jn;
} else {
if (switch_join_ns(jn))
goto err_out;
}
if (switch_user_join_ns(user_jn))
goto err_out;
ret = 0;
err_out:
list_for_each_entry(jn, &opts.join_ns, list)
close_safe(&jn->ns_fd);
return ret;
}
int prepare_namespace(struct pstree_item *item, unsigned long clone_flags)
{
pid_t pid = item->pid.virt;
......
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