[2/2] criu: restore -- Wait for userns being prepared before moving into cgroups

Submitted by Cyrill Gorcunov on April 20, 2016, 4:09 p.m.

Details

Message ID 1461168547-10802-3-git-send-email-gorcunov@virtuozzo.com
State Rejected
Series "criu: restore -- Wait for userns completion"
Headers show

Commit Message

Cyrill Gorcunov April 20, 2016, 4:09 p.m.
When user namespace are stepping in we should wait for their preparation
to complete before start using userns daemon (internally the kernel
checks for uids and if uids are not set -EINVAL will be returned
when usersn calls for sendmsg()).

Thus use completion and wait for uid maps being written first.

https://jira.sw.ru/browse/PSBM-46360

Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
---
 criu/cr-restore.c       | 25 ++++++++++++++++++-------
 criu/include/rst_info.h |  1 +
 2 files changed, 19 insertions(+), 7 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 4bce020..dbc11a8 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -1320,9 +1320,23 @@  static inline int fork_with_pid(struct pstree_item *item)
 
 
 	if (item == root_item) {
+		int retval = 0;
+
 		item->pid.real = ret;
 		pr_debug("PID: real %d virt %d\n",
 				item->pid.real, item->pid.virt);
+		if (root_ns_mask & CLONE_NEWUSER) {
+			/*
+			 * uid_map and gid_map must be filled from a parent user namespace.
+			 * prepare_userns_creds() must be called after filling mappings.
+			 */
+			retval = prepare_userns(item);
+			if (retval)
+				pr_err("Can't prepare userns");
+		}
+		complete(&task_entries->userns_completion);
+		if (retval)
+			kill(pid, SIGKILL);
 	}
 
 	if (opts.pidfile && root_item == item) {
@@ -1663,6 +1677,9 @@  static int restore_task_with_children(void *_arg)
 			goto err;
 	}
 
+	if (!current->parent)
+		wait_for_completion(&task_entries->userns_completion);
+
 	/*
 	 * Call this _before_ forking to optimize cgroups
 	 * restore -- if all tasks live in one set of cgroups
@@ -2074,13 +2091,6 @@  static int restore_root_task(struct pstree_item *init)
 		}
 	}
 
-	/*
-	 * uid_map and gid_map must be filled from a parent user namespace.
-	 * prepare_userns_creds() must be called after filling mappings.
-	 */
-	if ((root_ns_mask & CLONE_NEWUSER) && prepare_userns(init))
-		goto out_kill;
-
 	pr_info("Wait until namespaces are created\n");
 	ret = restore_wait_inprogress_tasks();
 	if (ret)
@@ -2262,6 +2272,7 @@  int prepare_task_entries(void)
 	atomic_set(&task_entries->nr_zombies, 0);
 	futex_set(&task_entries->start, CR_STATE_RESTORE_NS);
 	mutex_init(&task_entries->userns_sync_lock);
+	init_completion(&task_entries->userns_completion);
 
 	return 0;
 }
diff --git a/criu/include/rst_info.h b/criu/include/rst_info.h
index 562e2f0..8975095 100644
--- a/criu/include/rst_info.h
+++ b/criu/include/rst_info.h
@@ -12,6 +12,7 @@  struct task_entries {
 	futex_t start;
 	atomic_t cr_err;
 	mutex_t userns_sync_lock;
+	completion_t userns_completion;
 };
 
 struct fdt {