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