minijail: Add minijail_add_hook()

This allows callers to add hooks to be invoked at various events during
minijail setup. This is useful to e.g. setup SELinux contexts,
networking in the new namespace, and install other LSM-related stuff.

Bug: 63904978
Test: make tests

Change-Id: I3e773715ec1842db8071f5e993ee4bdcbe2d0082
diff --git a/libminijail_unittest.cc b/libminijail_unittest.cc
index d5ff6a8..caaa138 100644
--- a/libminijail_unittest.cc
+++ b/libminijail_unittest.cc
@@ -273,6 +273,41 @@
   close(dev_null);
 }
 
+static int early_exit(void* payload) {
+  exit(static_cast<int>(reinterpret_cast<intptr_t>(payload)));
+}
+
+TEST(Test, test_minijail_callback) {
+  pid_t pid;
+  int mj_run_ret;
+  int status;
+#if defined(__ANDROID__)
+  char filename[] = "/system/bin/cat";
+#else
+  char filename[] = "/bin/cat";
+#endif
+  char *argv[2];
+  int exit_code = 42;
+
+  struct minijail *j = minijail_new();
+
+  status =
+      minijail_add_hook(j, &early_exit, reinterpret_cast<void *>(exit_code),
+			MINIJAIL_HOOK_EVENT_PRE_DROP_CAPS);
+  EXPECT_EQ(status, 0);
+
+  argv[0] = filename;
+  argv[1] = NULL;
+  mj_run_ret = minijail_run_pid_pipes_no_preload(j, argv[0], argv, &pid, NULL,
+						 NULL, NULL);
+  EXPECT_EQ(mj_run_ret, 0);
+
+  status = minijail_wait(j);
+  EXPECT_EQ(status, exit_code);
+
+  minijail_destroy(j);
+}
+
 TEST(Test, parse_size) {
   size_t size;