Do not leak outside root dir fd into the child.

Also adds O_CLOEXEC to all open calls to be on the safe side.  In the
future, we should look into doing some sanity checks before execve like
Chromium's sandbox does:
https://code.google.com/p/chromium/codesearch#chromium/src/sandbox/linux/services/credentials.cc&l=320

If we want to further prevent people from shooting themselves in the
foot, we could also check that no fds are open, except for duping
/dev/null over 0, 1, and 2.

TEST=Built and tested that an fd to / is not leaked.

Bug: None
Change-Id: I41993a6aec9ce48bd34d191c3949f313ba80ca73
diff --git a/libminijail.c b/libminijail.c
index 1d90aef..bcbaed5 100644
--- a/libminijail.c
+++ b/libminijail.c
@@ -390,7 +390,7 @@
 
 void API minijail_namespace_enter_vfs(struct minijail *j, const char *ns_path)
 {
-	int ns_fd = open(ns_path, O_RDONLY);
+	int ns_fd = open(ns_path, O_RDONLY | O_CLOEXEC);
 	if (ns_fd < 0) {
 		pdie("failed to open namespace '%s'", ns_path);
 	}
@@ -418,7 +418,7 @@
 
 void API minijail_namespace_enter_net(struct minijail *j, const char *ns_path)
 {
-	int ns_fd = open(ns_path, O_RDONLY);
+	int ns_fd = open(ns_path, O_RDONLY | O_CLOEXEC);
 	if (ns_fd < 0) {
 		pdie("failed to open namespace '%s'", ns_path);
 	}
@@ -961,7 +961,7 @@
 		ret = snprintf(fname, sz, "/proc/%d/uid_map", j->initpid);
 		if (ret < 0 || (size_t)ret >= sz)
 			die("failed to write file name of uid_map");
-		fd = open(fname, O_WRONLY);
+		fd = open(fname, O_WRONLY | O_CLOEXEC);
 		if (fd < 0)
 			pdie("failed to open '%s'", fname);
 		len = strlen(j->uidmap);
@@ -973,7 +973,7 @@
 		ret = snprintf(fname, sz, "/proc/%d/gid_map", j->initpid);
 		if (ret < 0 || (size_t)ret >= sz)
 			die("failed to write file name of gid_map");
-		fd = open(fname, O_WRONLY);
+		fd = open(fname, O_WRONLY | O_CLOEXEC);
 		if (fd < 0)
 			pdie("failed to open '%s'", fname);
 		len = strlen(j->gidmap);
@@ -1085,10 +1085,10 @@
 	 * Keep the fd for both old and new root.
 	 * It will be used in fchdir later.
 	 */
-	oldroot = open("/", O_DIRECTORY | O_RDONLY);
+	oldroot = open("/", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
 	if (oldroot < 0)
 		pdie("failed to open / for fchdir");
-	newroot = open(j->chrootdir, O_DIRECTORY | O_RDONLY);
+	newroot = open(j->chrootdir, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
 	if (newroot < 0)
 		pdie("failed to open %s for fchdir", j->chrootdir);
 
@@ -1115,6 +1115,10 @@
 	/* Change back to the new root. */
 	if (fchdir(newroot))
 		return -errno;
+	if (close(oldroot))
+		return -errno;
+	if (close(newroot))
+		return -errno;
 	if (chroot("/"))
 		return -errno;
 	/* Set correct CWD for getcwd(3). */