Add minijail_fork
Provide a method to fork and jail a child process. This is useful for
users that would normally call fork followed by minijail_enter in the
child. However this allows for user and pid namespaces to be set up by
the clone call in minijail_run_internal.
Change-Id: Ib7dc11e7c783eda93b899ef4b782846061d113d4
Signed-off-by: Dylan Reid <dgreid@chromium.org>
diff --git a/libminijail.c b/libminijail.c
index a38e89b..f2a937b 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -2052,14 +2052,17 @@
/*
* Structure that specifies how to start a minijail.
*
- * filename - The program to exec in the child.
- * argv - Arguments for the child program.
+ * filename - The program to exec in the child. Required if `exec_in_child` = 1.
+ * argv - Arguments for the child program. Required if `exec_in_child` = 1.
* use_preload - If true use LD_PRELOAD.
+ * exec_in_child - If true, run `filename`. Otherwise, the child will return to
+ * the caller.
*/
struct minijail_run_config {
const char *filename;
char *const *argv;
int use_preload;
+ int exec_in_child;
};
/*
@@ -2089,6 +2092,7 @@
.filename = filename,
.argv = argv,
.use_preload = true,
+ .exec_in_child = true,
};
struct minijail_run_status status = {};
return minijail_run_internal(j, &config, &status);
@@ -2101,6 +2105,7 @@
.filename = filename,
.argv = argv,
.use_preload = true,
+ .exec_in_child = true,
};
struct minijail_run_status status = {
.pchild_pid = pchild_pid,
@@ -2115,6 +2120,7 @@
.filename = filename,
.argv = argv,
.use_preload = true,
+ .exec_in_child = true,
};
struct minijail_run_status status = {
.pstdin_fd = pstdin_fd,
@@ -2130,6 +2136,7 @@
.filename = filename,
.argv = argv,
.use_preload = true,
+ .exec_in_child = true,
};
struct minijail_run_status status = {
.pstdin_fd = pstdin_fd,
@@ -2147,6 +2154,7 @@
.filename = filename,
.argv = argv,
.use_preload = false,
+ .exec_in_child = true,
};
struct minijail_run_status status = {};
return minijail_run_internal(j, &config, &status);
@@ -2164,6 +2172,7 @@
.filename = filename,
.argv = argv,
.use_preload = false,
+ .exec_in_child = true,
};
struct minijail_run_status status = {
.pstdin_fd = pstdin_fd,
@@ -2174,6 +2183,13 @@
return minijail_run_internal(j, &config, &status);
}
+pid_t API minijail_fork(struct minijail *j)
+{
+ struct minijail_run_config config = {};
+ struct minijail_run_status status = {};
+ return minijail_run_internal(j, &config, &status);
+}
+
static int minijail_run_internal(struct minijail *j,
const struct minijail_run_config *config,
struct minijail_run_status *status_out)
@@ -2197,6 +2213,11 @@
int use_preload = config->use_preload;
if (use_preload) {
+ if (j->hooks_head != NULL)
+ die("Minijail hooks are not supported with LD_PRELOAD");
+ if (!config->exec_in_child)
+ die("minijail_fork is not supported with LD_PRELOAD");
+
oldenv = getenv(kLdPreloadEnvVar);
if (oldenv) {
oldenv_copy = strdup(oldenv);
@@ -2216,10 +2237,6 @@
}
}
- if (use_preload && j->hooks_head != NULL) {
- die("Minijail hooks are not supported with LD_PRELOAD");
- }
-
/*
* Make the process group ID of this process equal to its PID.
* In the non-interactive case (e.g. when the parent process is started
@@ -2413,6 +2430,12 @@
*status_out->pstderr_fd =
setup_pipe_end(stderr_fds, 0 /* read end */);
+ /*
+ * If forking return the child pid, in the normal exec case
+ * return 0 for success.
+ */
+ if (!config->exec_in_child)
+ return child_pid;
return 0;
}
/* Child process. */
@@ -2530,10 +2553,15 @@
*/
j->flags.pids = 0;
}
- /* Jail this process, then execve(2) the target. */
+
+ /*
+ * Jail this process.
+ * If forking, return.
+ * If not, execve(2) the target.
+ */
minijail_enter(j);
- if (pid_namespace && do_init) {
+ if (config->exec_in_child && pid_namespace && do_init) {
/*
* pid namespace: this process will become init inside the new
* namespace. We don't want all programs we might exec to have
@@ -2558,6 +2586,9 @@
run_hooks_or_die(j, MINIJAIL_HOOK_EVENT_PRE_EXECVE);
+ if (!config->exec_in_child)
+ return 0;
+
/*
* If we aren't pid-namespaced, or the jailed program asked to be init:
* calling process