Minijail: allow writing to the child process' standard input.
BUG=chromium-os:33983
TEST=libminijail_unittest
TEST=security_Minijail0
Change-Id: Ic2373127b3bca6a4a4a05ffcbc48b486cb5eb4a6
Reviewed-on: https://gerrit.chromium.org/gerrit/31779
Tested-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
Reviewed-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
Commit-Ready: Jorge Lucangeli Obes <jorgelo@chromium.org>
diff --git a/libminijail.c b/libminijail.c
index fdf6f29..bf8c163 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -835,15 +835,29 @@
int API minijail_run(struct minijail *j, const char *filename,
char *const argv[])
{
- return minijail_run_pid(j, filename, argv, NULL);
+ return minijail_run_pid_pipe(j, filename, argv, NULL, NULL);
}
int API minijail_run_pid(struct minijail *j, const char *filename,
char *const argv[], pid_t *pchild_pid)
{
+ return minijail_run_pid_pipe(j, filename, argv, pchild_pid, NULL);
+}
+
+int API minijail_run_pipe(struct minijail *j, const char *filename,
+ char *const argv[], int *pstdin_fd)
+{
+ return minijail_run_pid_pipe(j, filename, argv, NULL, pstdin_fd);
+}
+
+int API minijail_run_pid_pipe(struct minijail *j, const char *filename,
+ char *const argv[], pid_t *pchild_pid,
+ int *pstdin_fd)
+{
char *oldenv, *oldenv_copy = NULL;
pid_t child_pid;
int pipe_fds[2];
+ int stdin_fds[2];
int ret;
/* We need to remember this across the minijail_preexec() call. */
int pid_namespace = j->flags.pids;
@@ -865,6 +879,15 @@
if (setup_pipe(pipe_fds))
return -EFAULT;
+ /*
+ * If we want to write to the child process' standard input,
+ * create the pipe(2) now.
+ */
+ if (pstdin_fd) {
+ if (pipe(stdin_fds))
+ return -EFAULT;
+ }
+
/* Use sys_clone() if and only if we're creating a pid namespace.
*
* tl;dr: WARNING: do not mix pid namespaces and multithreading.
@@ -924,7 +947,10 @@
unsetenv(kLdPreloadEnvVar);
}
unsetenv(kFdEnvVar);
+
j->initpid = child_pid;
+
+ /* Send marshalled minijail. */
close(pipe_fds[0]); /* read endpoint */
ret = minijail_to_fd(j, pipe_fds[1]);
close(pipe_fds[1]); /* write endpoint */
@@ -932,12 +958,34 @@
kill(j->initpid, SIGKILL);
die("failed to send marshalled minijail");
}
+
if (pchild_pid)
*pchild_pid = child_pid;
+
+ /*
+ * If we want to write to the child process' standard input,
+ * set up the write end of the pipe.
+ */
+ if (pstdin_fd) {
+ close(stdin_fds[0]); /* read endpoint */
+ *pstdin_fd = stdin_fds[1];
+ }
+
return 0;
}
free(oldenv_copy);
+ /*
+ * If we want to write to the jailed process' standard input,
+ * set up the read end of the pipe.
+ */
+ if (pstdin_fd) {
+ close(stdin_fds[1]); /* write endpoint */
+ /* dup2(2) the read end of the pipe into stdin. */
+ if (dup2(stdin_fds[0], 0))
+ die("failed to set up stdin pipe");
+ }
+
/* Drop everything that cannot be inherited across execve. */
minijail_preexec(j);
/* Jail this process and its descendants... */