PERFORCE change 214311 for review

Brooks Davis brooks at FreeBSD.org
Thu Jul 12 22:52:51 UTC 2012


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

Change 214311 by brooks at brooks_ecr_current on 2012/07/12 22:52:42

	Add a -f option to fork and monitor a child.  When the child exits with
	error 99 show a dialog box indicating that the program was exploited.

Affected files ...

.. //depot/projects/ctsrd/beribsd/src/ctsrd/browser/browser.c#11 edit

Differences ...

==== //depot/projects/ctsrd/beribsd/src/ctsrd/browser/browser.c#11 (text+ko) ====

@@ -45,6 +45,8 @@
 #include <fnmatch.h>
 #include <libutil.h>
 #include <magic.h>
+#include <poll.h>
+#include <signal.h>
 #define _WITH_DPRINTF
 #include <stdio.h>
 #include <stdlib.h>
@@ -179,13 +181,17 @@
 static u_int32_t	*bgimage;
 static u_int32_t	*icons;
 static magic_t		 magic;
+static int		 zombies_waiting = 0;
 
 static void
 usage(void)
 {
 	
-	printf("usage:	browser <dir> <tty>\n");
-	printf("	browser -T <dir>\n");
+	printf("usage:	browser [-f] <dir> <tty>\n");
+	printf("	browser [-f] -T <dir>\n");
+	printf("\n");
+	printf("	-f	Fork and monitor a child instance\n");
+	printf("	-T	Don't open a tty\n");
 	exit(1);
 }
 
@@ -211,6 +217,118 @@
 }
 
 static void
+handle_sigchld(int sig __unused)
+{
+	
+	zombies_waiting = 1;
+}
+
+static void
+writeall(int fd, const char *buf, ssize_t len)
+{
+	ssize_t wlen = 0, n;
+	
+	while (wlen != len) {
+		n = write(fd, buf + wlen, len - wlen);
+		if (n < 0) {
+			syslog(LOG_ALERT, "write failed: %s", strerror(errno));
+			err(1, "write");
+		}
+		wlen += n;
+	}
+}
+
+static void
+fork_child(void)
+{
+	int pmaster, pslave, status;
+	ssize_t rlen;
+	pid_t pid;
+	struct sigaction act;
+	struct pollfd pfd[1];
+	char buf[1024];
+
+restart:
+	if (openpty(&pmaster, &pslave, NULL, NULL, NULL) == -1)
+		err(1, "openpty");
+	pid = fork();
+	if (pid < 0)
+		err(1, "fork()");
+	else if (pid == 0) {
+		close(pmaster);
+		if (login_tty(pslave) < 0) {
+			syslog(LOG_ALERT, "login_tty failed in child: %s", strerror(errno));
+			err(1, "tty_login");
+		}
+		/* return to begin normal processing */
+		return;
+	}
+
+	memset (&act, 0, sizeof(act));
+	act.sa_handler = handle_sigchld;
+
+	if (sigaction(SIGCHLD, &act, 0))
+		err(1, "sigacation");
+
+	close(pslave);
+	/*
+	 * We poll for data from the child's pty.  Don't bother looking for
+	 * tty input since the child couldn't do anything with it.
+	 */
+	pfd[0].fd = pmaster;
+	pfd[0].events = POLLIN;
+	for (;;) {
+		if (poll(pfd, 2, INFTIM) < 0) {
+			if (errno == EINTR)
+				continue;
+			syslog(LOG_ALERT, "poll failed with %s",
+			    strerror(errno));
+			err(1, "poll");
+		}
+		if (zombies_waiting) {
+			printf("zombie!\n");
+			wait4(pid, &status, 0, NULL);
+			if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
+				warnx("child exited with %d",
+				    WEXITSTATUS(status));
+				if (WEXITSTATUS(status) == 99) {
+					warnx("child was exploited");
+					fb_dialog(FBDT_PINCH2CLOSE, black,
+					    white, black,
+					    "Browser Exited", 
+"Browser vulnerability exploited\n"
+"\n"
+"Pinch to close dialog and restart"
+					    );
+				}
+			} else if(WIFSIGNALED(status)) {
+				warn("child killed by signal %d",
+				    WTERMSIG(status));
+			} else {
+				printf("child exited cleanly, exiting\n");
+				exit(0);
+			}
+			printf("child exited badly, restarting\n");
+			zombies_waiting = 0;
+			close(pmaster); /* XXX: should we drain it first? */
+			fb_fill_region(vwhite(128), 0, 0, fb_width, fb_height);
+			goto restart;
+		}
+		
+		if (pfd[0].revents & POLLIN) {
+			rlen = read(pmaster, buf, sizeof(buf));
+			if (rlen < 0) {
+				err(1, "read");
+			} else if (rlen > 0)
+				writeall(1, buf, rlen);
+		}
+	}
+
+	
+	
+}
+
+static void
 init_magic(void) {
 	magic = magic_open(MAGIC_MIME_TYPE);
 	if (magic == NULL)
@@ -262,8 +380,9 @@
 			exit(0);
 		} else {
 			close(pfd[1]);
-			if (wait4(pid, &status, 0, NULL) == -1)
-				err(1, "wait4()");
+			while (wait4(pid, &status, 0, NULL) == -1)
+				if (errno != EINTR)
+					err(1, "wait4()");
 			if (WIFEXITED(status) &&
 			    WEXITSTATUS(status) != 0) {
 				warnx("child exited with %d",
@@ -435,11 +554,11 @@
 get_action(void)
 {
 	struct tsstate *ts;
-	int action = -1, col, i, row;
+	int col, i, row;
 
 	printf("entering get_action\n");
 
-	while(action < 0) {
+	for (;;) {
 		ts = ts_poll();
 		printf("gesture = %x\n", ts->ts_gesture);
 		if (ts->ts_gesture == TSG_CLICK) {
@@ -594,10 +713,13 @@
 main(int argc, char *argv[])
 {
 	int ch, dfd;
-	int ttyflag = 1;
+	int ttyflag = 1, forkflag = 0;
 
-	while ((ch = getopt(argc, argv, "T")) != -1) {
+	while ((ch = getopt(argc, argv, "fT")) != -1) {
 		switch (ch) {
+		case 'f':
+			forkflag = 1;
+			break;
 		case 'T':
 			ttyflag = 0;
 			break;
@@ -608,14 +730,23 @@
 	argc -= optind;
 	argv += optind;
 
-	if (argc <= 0 && argc > 2)
+	if (argc <= 0 || argc > 2)
 		usage();
 
-	if (argc == 2)
-		init_tty(argv[1]);
-	init_magic();
+	if (argc == 2) {
+		if (ttyflag)
+			init_tty(argv[1]);
+		else
+			usage();
+	}
+
 	fb_init();
 	fb_load_syscons_font(NULL, "/usr/share/syscons/fonts/iso-8x16.fnt");
+
+	if (forkflag)
+		fork_child();
+
+	init_magic();
 	init_bgimage();
 
 	icons = malloc(sizeof(u_int32_t) * ICON_WH * 640);


More information about the p4-projects mailing list