[Devel,CRIU,4/6] util: Implement clone_in_child_process() helper

Submitted by Kirill Tkhai on July 15, 2017, 1:50 p.m.

Details

Message ID 150012661461.9540.12408341046488101245.stgit@localhost.localdomain
State New
Series "Switch user_ns before mount binfmt_misc"
Headers show

Commit Message

Kirill Tkhai July 15, 2017, 1:50 p.m.
Clone with CLONE_VM|CLONE_VFORK and call desired function.
This helper is aimed to be used functions, which require
to drop their capabilities, say, enter to less permissive
user_ns.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/include/util.h |    1 +
 criu/util.c         |   30 ++++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/include/util.h b/criu/include/util.h
index 969867b2d..c6429ce24 100644
--- a/criu/include/util.h
+++ b/criu/include/util.h
@@ -294,6 +294,7 @@  int run_tcp_server(bool daemon_mode, int *ask, int cfd, int sk);
 int setup_tcp_client(char *addr);
 int cr_set_root(int fd, int *old_root);
 int cr_restore_root(int fd);
+int call_in_child_process(int (*fn)(void *), void *arg);
 
 #define LAST_PID_PATH		"sys/kernel/ns_last_pid"
 #define PID_MAX_PATH		"sys/kernel/pid_max"
diff --git a/criu/util.c b/criu/util.c
index 91f1ffe01..0fb2b46eb 100644
--- a/criu/util.c
+++ b/criu/util.c
@@ -48,6 +48,7 @@ 
 #include "namespaces.h"
 #include "criu-log.h"
 
+#include "clone-noasan.h"
 #include "cr_options.h"
 #include "servicefd.h"
 #include "cr-service.h"
@@ -1340,3 +1341,32 @@  int cr_restore_root(int root)
 
 	return ret;
 }
+
+int call_in_child_process(int (*fn)(void *), void *arg)
+{
+	int status, ret = -1;
+	pid_t pid;
+	/*
+	 * Parent freezes till child exit, so child may use the same stack.
+	 * No SIGCHLD flag, so it's not need to block signal.
+	 */
+	pid = clone_noasan(fn, CLONE_VFORK | CLONE_VM | CLONE_FILES |
+			   CLONE_IO | CLONE_SIGHAND | CLONE_SYSVSEM, arg);
+	if (pid == -1) {
+		pr_perror("Can't clone");
+		return -1;
+	}
+	errno = 0;
+	if (waitpid(pid, &status, __WALL) != pid || !WIFEXITED(status) || WEXITSTATUS(status)) {
+		pr_err("Can't wait or bad status: errno=%d, status=%d", errno, status);
+		goto out;
+	}
+	ret = 0;
+	/*
+	 * Child opened PROC_SELF for pid. If we create one more child
+	 * with the same pid later, it will try to reuse this /proc/self.
+	 */
+out:
+	close_pid_proc();
+	return ret;
+}