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