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_unittest.cc b/libminijail_unittest.cc
index d07ee4a..3ee0ab9 100644
--- a/libminijail_unittest.cc
+++ b/libminijail_unittest.cc
@@ -21,6 +21,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 #include <gtest/gtest.h>
 
@@ -273,6 +274,34 @@
   close(dev_null);
 }
 
+TEST(Test, test_minijail_fork) {
+  pid_t mj_fork_ret;
+  int status;
+  int pipe_fds[2];
+  ssize_t pid_size = sizeof(mj_fork_ret);
+
+  struct minijail *j = minijail_new();
+
+  ASSERT_EQ(pipe(pipe_fds), 0);
+
+  mj_fork_ret = minijail_fork(j);
+  ASSERT_GE(mj_fork_ret, 0);
+  if (mj_fork_ret == 0) {
+    pid_t pid_in_parent;
+    // Wait for the parent to tell us the pid in the parent namespace.
+    EXPECT_EQ(read(pipe_fds[0], &pid_in_parent, pid_size), pid_size);
+    EXPECT_EQ(pid_in_parent, getpid());
+    exit(0);
+  }
+
+  EXPECT_EQ(write(pipe_fds[1], &mj_fork_ret, pid_size), pid_size);
+  waitpid(mj_fork_ret, &status, 0);
+  ASSERT_TRUE(WIFEXITED(status));
+  EXPECT_EQ(WEXITSTATUS(status), 0);
+
+  minijail_destroy(j);
+}
+
 static int early_exit(void* payload) {
   exit(static_cast<int>(reinterpret_cast<intptr_t>(payload)));
 }