[CRIU] [PATCH 2/4] join-ns: perform join_namespace according to join-ns opts
Dengguangxing
dengguangxing at huawei.com
Sun Apr 3 23:40:57 PDT 2016
Signed-off-by: Deng Guangxing <dengguangxing at huawei.com>
---
criu/cr-restore.c | 5 ++
criu/include/namespaces.h | 1 +
criu/namespaces.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 133 insertions(+)
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 027232b..1ea9949 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -1575,6 +1575,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;
+ }
+
if (restore_finish_stage(CR_STATE_RESTORE_NS) < 0)
goto err;
diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index 73ac327..a810cf3 100644
--- a/criu/include/namespaces.h
+++ b/criu/include/namespaces.h
@@ -122,6 +122,7 @@ extern gid_t userns_gid(gid_t gid);
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 join_namespaces();
extern int check_namespace_opts();
typedef int (*uns_call_t)(void *arg, int fd, pid_t pid);
diff --git a/criu/namespaces.c b/criu/namespaces.c
index 6994cf0..c7a5572 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -1515,6 +1515,133 @@ 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;
+
+ if (jn->ns_file == NULL) {
+ pr_perror("join-ns file is NULL");
+ return -1;
+ }
+
+ 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->ns_fd < 0) {
+ pr_perror("Invalid ns fd in join-ns");
+ return -1;
+ }
+
+ 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;
+ }
+
+ /* 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 (st.st_ino != self_st.st_ino) {
+ if (setns(jn->ns_fd, jn->nd->cflag)) {
+ pr_perror("Can't setns %s:%s",jn->nd->str, jn->ns_file);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int switch_user_join_ns(struct join_ns *jn) {
+ if (jn == NULL) {
+ return 0;
+ }
+
+ uid_t uid;
+ gid_t gid;
+
+ 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()
+{
+ 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 (!strncmp(jn->nd->str, "user", 5)) {
+ 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;
--
2.5.0
More information about the CRIU
mailing list