PERFORCE change 219865 for review

Brooks Davis brooks at FreeBSD.org
Fri Nov 30 02:36:08 UTC 2012


http://p4web.freebsd.org/@@219865?ac=10

Change 219865 by brooks at brooks_zenith on 2012/11/30 02:35:07

	Convert the capsicum sandbox support in minifile to use an exec'd
	helper program in prepration for the creation of a CHERI sandbox.

Affected files ...

.. //depot/projects/ctsrd/cheribsd/src/ctsrd/minifile/Makefile#2 edit
.. //depot/projects/ctsrd/cheribsd/src/ctsrd/minifile/capsicum/Makefile#1 add
.. //depot/projects/ctsrd/cheribsd/src/ctsrd/minifile/capsicum/minifile-capsicum.c#1 add
.. //depot/projects/ctsrd/cheribsd/src/ctsrd/minifile/minifile.c#4 edit
.. //depot/projects/ctsrd/cheribsd/src/ctsrd/minifile/minifile.h#1 add

Differences ...

==== //depot/projects/ctsrd/cheribsd/src/ctsrd/minifile/Makefile#2 (text+ko) ====

@@ -1,6 +1,8 @@
 #	@(#)Makefile	8.1 (Berkeley) 5/31/93
 # $FreeBSD$
 
+SUBDIR+=	capsicum
+
 PROG=	minifile
 
 MAN=

==== //depot/projects/ctsrd/cheribsd/src/ctsrd/minifile/minifile.c#4 (text+ko) ====

@@ -9,13 +9,14 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <magic.h>
-#define _WITH_DPRINTF
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <vis.h>
 
+#include "minifile.h"
+
 enum _sbtype {
 	SB_NONE = 0,
 	SB_CAPSICUM,
@@ -31,22 +32,131 @@
 	errx(1, "usage: minifile [-s <sandbox type>] <file> ...\n");
 }
 
+/*
+ * prep_fds() moves the file descriptors in curfds around such that they
+ * are at the corresponding target fd values in preperation for an exec
+ * into a capsicum or similar sandbox.  All fd's above the largest value
+ * specified in the targetfds array are closed.  It is expected that the
+ * values will fall within the range (3 .. <nfds + 2>).  Otherwise an
+ * unpredictiable set of files may remain open and information leaks may
+ * result unless specifc descriptors were already placed in the other
+ * slots.  The programmer should seperately ensure that fds 0, 1, and 2
+ * are either the usual stdin, stdout, and stderror or fd's to /dev/null.
+ */
 int
+prep_fds(int *curfds, int *targetfds, int nfds)
+{
+	int i, maxfd = -1, tmpfd;
+
+	/* Find the largest fd in either the current or target lists */
+	for (i = 0; i < nfds; i++)
+		if (maxfd < curfds[i])
+			maxfd = curfds[i];
+	for (i = 0; i < nfds; i++)
+		if (maxfd < targetfds[i])
+			maxfd = targetfds[i];
+
+	/* Move all the fds up above the largest one */
+	for (i = 0; i < nfds; i++) {
+		tmpfd = maxfd + 1 + i;
+		if (dup2(curfds[i], tmpfd) == -1)
+			return (-1);
+		close(curfds[i]);
+	}
+
+	/* Move them all into their assigned locations. */
+	for (i = 0; i < nfds; i++) {
+		tmpfd = maxfd + 1 + i;
+		if (dup2(tmpfd, targetfds[i]) == -1)
+			return (-1);
+		close(tmpfd);
+	}
+
+	/* Close everything above are new maximum descriptor */
+	maxfd = -1;
+	for (i = 0; i < nfds; i++)
+		if (maxfd < targetfds[i])
+			maxfd = targetfds[i];
+	closefrom(maxfd + 1);
+
+	return (0);
+}
+
+const char *
+capsicum_magic_descriptor(int mfd, int fd)
+{
+	int status;
+	pid_t pid;
+	ssize_t rlen;
+	static char buf[4096];
+	char *type, *ttype;
+	int pfd[2];
+	int curfds[3], targetfds[3];
+
+	if (pipe(pfd) == -1)
+		err(1, "pipe()");
+	pid = fork();
+	if (pid < 0)
+		err(1, "fork()");
+	else if (pid == 0) {
+		close(pfd[0]);
+		
+		/* XXX: use cap_new() to limit further */
+		curfds[0] = fd;
+		targetfds[0] = MINIFILE_FILE_FD;
+		curfds[1] = mfd;
+		targetfds[1] = MINIFILE_MAGIC_FD;
+		curfds[2] = pfd[1];
+		targetfds[2] = MINIFILE_OUT_FD;
+
+		if (prep_fds(curfds, targetfds, 3) == -1)
+			err(1, "pred_fds()");
+
+		execl("/usr/libexec/minifile-capsicum", "readpng", NULL);
+		err(1, "exec /usr/libexec/minifile-capsicum");
+	} else {
+		close(pfd[1]);
+		while (wait4(pid, &status, 0, NULL) == -1)
+			if (errno != EINTR)
+				err(1, "wait4()");
+		if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
+			warnx("child exited with %d", WEXITSTATUS(status));
+			close(pfd[0]);
+			type = "badmagic";
+		} else if(WIFSIGNALED(status)) {
+			warn("child killed by signal %d", WTERMSIG(status));
+			close(pfd[0]);
+			type = "badmagic";
+		} else {
+			rlen = read(pfd[0], buf, 128);
+			close(pfd[0]);
+			if (rlen == -1)
+				type = "read error";
+			else if (rlen == 0 || rlen == 1)
+				type = "unknown";
+			else {
+				/* Don't trust the result */
+				ttype = buf + rlen;
+				strvisx(ttype, buf, rlen, 0);
+				type = ttype;
+			}
+		}
+	}
+
+	return type;
+}
+
+int
 main(int argc, char **argv)
 {
 	char ch;
 	void *magicbuf;
 	const char *fname;
-	int mfd, fd, status;
-	ssize_t rlen;
-	pid_t pid;
+	int mfd, fd;
 	const char *type;
 	struct magic_set *magic;
 	struct stat sb;
-	char buf[4096], *ttype;
-	int pfd[2];
 
-
 	while ((ch = getopt(argc, argv, "s:")) != -1) {
 		switch(ch) {
 		case 's':
@@ -65,38 +175,41 @@
 	argc -= optind;
 	argv += optind;
 
-	magic = magic_open(MAGIC_MIME_TYPE);
-	if (magic == NULL)
-		errx(1, "magic_open()");
+	if (argc <= 0)
+		usage();
+
 	mfd = open(MAGIC_FILE, O_RDONLY);
 	if (mfd == -1) {
 		warn("open(%s)", MAGIC_FILE);
 		magic_close(magic);
 		exit(1);
 	}
-	if (fstat(mfd, &sb) == -1) {
-		warn("fstat(%s)", MAGIC_FILE);
-		magic_close(magic);
-		exit(1);
+
+	if (sbtype == SB_NONE) {
+		magic = magic_open(MAGIC_MIME_TYPE);
+		if (magic == NULL)
+			errx(1, "magic_open()");
+		if (fstat(mfd, &sb) == -1) {
+			warn("fstat(%s)", MAGIC_FILE);
+			magic_close(magic);
+			exit(1);
+		}
+		magicbuf = mmap(NULL, sb.st_size, PROT_READ|PROT_WRITE,
+		    MAP_PRIVATE, mfd, 0);
+		if (magicbuf == MAP_FAILED) {
+			warn("mmap(%s)", MAGIC_FILE);
+			magic_close(magic);
+			exit(1);
+		}
+		close(mfd);
+		if (magic_load_buffers(magic, &magicbuf, &sb.st_size, 1) ==
+		    -1) {
+			warnx("magic_load() %s", magic_error(magic));
+			magic_close(magic);
+			exit(1);
+		}
 	}
-	magicbuf = mmap(NULL, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
-	    mfd, 0);
-	if (magicbuf == MAP_FAILED) {
-		warn("mmap(%s)", MAGIC_FILE);
-		magic_close(magic);
-		exit(1);
-	}
-	close(mfd);
-	if (magic_load_buffers(magic, &magicbuf, &sb.st_size, 1) == -1) {
-		warnx("magic_load() %s", magic_error(magic));
-		magic_close(magic);
-		exit(1);
-	}
-
 
-	if (argc <= 0)
-		usage();
-
 	for (; argc >= 1; argc--, argv++) {
 		fname = argv[0];
 		fd = open(fname, O_RDONLY);
@@ -106,58 +219,12 @@
 		case SB_NONE:
 			type = magic_descriptor(magic, fd);
 			if (type == NULL)
-				errx(1, "magic_file(): %s",
-				    magic_error(magic));
+				errx(1, "magic_file(): %s", magic_error(magic));
 			break;
 		case SB_CAPSICUM:
-			if (pipe(pfd) == -1)
-				err(1, "pipe()");
-			pid = fork();
-			if (pid < 0)
-				err(1, "fork()");
-			else if (pid == 0) {
-				close(fd);
-				close(pfd[0]);
-				/* XXX: do more cleanup here */
-				cap_enter();
-				type = magic_descriptor(magic, fd);
-				if (type == NULL)
-					dprintf(pfd[1], "badmagic");
-				else
-					dprintf(pfd[1], "%s", type);
-				close(pfd[1]);
-				exit(0);
-			} else {
-				close(pfd[1]);
-				while (wait4(pid, &status, 0, NULL) == -1)
-					if (errno != EINTR)
-						err(1, "wait4()");
-				if (WIFEXITED(status) &&
-				    WEXITSTATUS(status) != 0) {
-					warnx("child exited with %d",
-					    WEXITSTATUS(status));
-					close(pfd[0]);
-					type = "badmagic";
-				} else if(WIFSIGNALED(status)) {
-					warn("child killed by signal %d",
-					    WTERMSIG(status));
-					close(pfd[0]);
-					type = "badmagic";
-				} else {
-					rlen = read(pfd[0], buf, 128);
-					close(pfd[0]);
-					if (rlen == -1)
-						type = "read error";
-					else if (rlen == 0 || rlen == 1)
-						type = "unknown";
-					else {
-						/* Don't trust the result */
-						ttype = buf + rlen;
-						strvisx(ttype, buf, rlen, 0);
-						type = ttype;
-					}
-				}
-			}
+			type = capsicum_magic_descriptor(mfd, fd);
+			if (type == NULL)
+				errx(1, "capsicum_magic_descriptor()");
 			break;
 		case SB_CHERI:
 			errx(1, "no cheri capability support yet");


More information about the p4-projects mailing list