minijail: Add option to enter a new IPC namespace

Export this feature through the '-l' option to minijail0.

TEST=run minijail0 with the -l option, check that the executed program
is in a different ipc namesspace with /proc/self/ns/ipc.
BUG=b/25770648

Change-Id: Ia8f72cc59160fc736c8a58cb68d9894f9c92281c
Signed-off-by: Dylan Reid <dgreid@chromium.org>
diff --git a/libminijail.c b/libminijail.c
index 544651a..e3b7a65 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -91,6 +91,7 @@
 		int vfs:1;
 		int enter_vfs:1;
 		int pids:1;
+		int ipc:1;
 		int net:1;
 		int enter_net:1;
 		int userns:1;
@@ -301,6 +302,11 @@
 	j->flags.do_init = 1;
 }
 
+void API minijail_namespace_ipc(struct minijail *j)
+{
+	j->flags.ipc = 1;
+}
+
 void API minijail_namespace_net(struct minijail *j)
 {
 	j->flags.net = 1;
@@ -1125,6 +1131,10 @@
             pdie("mount(/, private)");
         }
 
+	if (j->flags.ipc && unshare(CLONE_NEWIPC)) {
+		pdie("unshare(ipc)");
+	}
+
 	if (j->flags.enter_net) {
 		if (setns(j->netns_fd, CLONE_NEWNET))
 			pdie("setns(CLONE_NEWNET)");
diff --git a/libminijail.h b/libminijail.h
index e7f24ce..9d92462 100644
--- a/libminijail.h
+++ b/libminijail.h
@@ -50,6 +50,7 @@
 void minijail_use_caps(struct minijail *j, uint64_t capmask);
 void minijail_namespace_vfs(struct minijail *j);
 void minijail_namespace_enter_vfs(struct minijail *j, const char *ns_path);
+void minijail_namespace_ipc(struct minijail *j);
 void minijail_namespace_net(struct minijail *j);
 void minijail_namespace_enter_net(struct minijail *j, const char *ns_path);
 /* Implies namespace_vfs and remount_proc_readonly.
diff --git a/minijail0.1 b/minijail0.1
index 1f3b126..122ecc5 100644
--- a/minijail0.1
+++ b/minijail0.1
@@ -49,6 +49,10 @@
 (Other direct numbers may be specified if minijail0 is not in sync with the
  host kernel or something like 32/64-bit compatibility issues exist.)
 .TP
+\fB-l\fR
+Run inside a new IPC namespace. This option makes the program's System V IPC
+namespace independent.
+.TP
 \fB-p\fR
 Run inside a new PID namespace. This option will make it impossible for the
 program to see or affect processes that are not its descendants. This implies
diff --git a/minijail0.c b/minijail0.c
index 68c9478..fb0b3b3 100644
--- a/minijail0.c
+++ b/minijail0.c
@@ -93,7 +93,7 @@
 {
 	size_t i;
 
-	printf("Usage: %s [-GhiInprsvtU] [-b <src>,<dest>[,<writeable>]] [-f <file>]"
+	printf("Usage: %s [-GhiInprsvtUl] [-b <src>,<dest>[,<writeable>]] [-f <file>]"
 	       "[-c <caps>] [-C <dir>] [-g <group>] [-S <file>] [-u <user>] "
 	       "[-k <src>,<dest>,<type>[,<flags>]] "
 	       "[-m \"<uid> <loweruid> <count>[,<uid> <loweruid> <count>]\"] "
@@ -116,6 +116,7 @@
 	       "  -i:         exit immediately after fork (do not act as init)\n"
 	       "              Not compatible with -p\n"
 	       "  -I:         run <program> as init (pid 1) inside a new pid namespace (implies -p)\n"
+	       "  -l:         enter new IPC namespace\n"
 	       "  -L:         report blocked syscalls to syslog when using seccomp filter.\n"
 	       "              Forces the following syscalls to be allowed:\n"
 	       "                  ", progn);
@@ -166,7 +167,7 @@
 	if (argc > 1 && argv[1][0] != '-')
 		return 1;
 	while ((opt = getopt(argc, argv,
-			     "u:g:sS:c:C:P:b:V:f:m:M:k:a:e::vrGhHinpLtIU"))
+			     "u:g:sS:c:C:P:b:V:f:m:M:k:a:e::vrGhHinplLtIU"))
 	       != -1) {
 		switch (opt) {
 		case 'u':
@@ -196,6 +197,9 @@
 			}
 			use_seccomp_filter = 1;
 			break;
+		case 'l':
+			minijail_namespace_ipc(j);
+			break;
 		case 'L':
 			minijail_log_seccomp_filter_failures(j);
 			break;