Create a new session for the jailed process.

This prevents the jailed process from using the TIOCSTI ioctl to push
characters into the parent process terminal's input buffer, therefore
escaping the jail.

To avoid messing with job control/signals in the non-interactive case
(i.e. when not started from the console), only do this if any of stdin,
stdout, or stderr are TTYs. Note that this bug only really affects
users who use 'minijail0' from the command line, which is not the case
for Android or Chrome OS.

Bug: 33073072
Bug: crbug.com/667493
Test: Use repro case from bug.
Change-Id: I7ab43ee8ba81110253809d98440ae572a01a6260
diff --git a/libminijail.c b/libminijail.c
index ad9afa8..79ec018 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -1961,15 +1961,19 @@
 	}
 
 	/*
-	 * Make the process group ID of this process equal to its PID, so that
-	 * both the Minijail process and the jailed process can be killed
-	 * together.
+	 * 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
+	 * from init) this ensures the parent process and the jailed process
+	 * can be killed together.
+	 * When the parent process is started from the console this ensures
+	 * the call to setsid(2) in the jailed process succeeds.
+	 *
 	 * Don't fail on EPERM, since setpgid(0, 0) can only EPERM when
 	 * the process is already a process group leader.
 	 */
 	if (setpgid(0 /* use calling PID */, 0 /* make PGID = PID */)) {
 		if (errno != EPERM) {
-			pdie("setpgid(0, 0)");
+			pdie("setpgid(0, 0) failed");
 		}
 	}
 
@@ -2219,6 +2223,19 @@
 			die("failed to set up stderr pipe");
 	}
 
+	/*
+	 * If any of stdin, stdout, or stderr are TTYs, create a new session.
+	 * This prevents the jailed process from using the TIOCSTI ioctl
+	 * to push characters into the parent process terminal's input buffer,
+	 * therefore escaping the jail.
+	 */
+	if (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) ||
+	    isatty(STDERR_FILENO)) {
+		if (setsid() < 0) {
+			pdie("setsid() failed");
+		}
+	}
+
 	/* If running an init program, let it decide when/how to mount /proc. */
 	if (pid_namespace && !do_init)
 		j->flags.remount_proc_ro = 0;