From 31d323c3f90e5d5665f43a76e7497bfb36b5cba7 Mon Sep 17 00:00:00 2001 From: florian Date: Tue, 29 Oct 2013 17:59:47 +0000 Subject: Fix a potential file descriptor overlap in exec_cgi() by making sure that file descriptors zero to two are always open when starting slowcgi. pointed out, with and looks good to deraadt@ --- slowcgi.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/slowcgi.c b/slowcgi.c index 8a9eed8..539b610 100644 --- a/slowcgi.c +++ b/slowcgi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: slowcgi.c,v 1.24 2013/10/23 15:29:21 florian Exp $ */ +/* $OpenBSD: slowcgi.c,v 1.25 2013/10/29 17:59:47 florian Exp $ */ /* * Copyright (c) 2013 David Gwynne * Copyright (c) 2013 Florian Obser @@ -253,7 +253,25 @@ main(int argc, char *argv[]) { extern char *__progname; struct passwd *pw; - int c; + struct stat sb; + int c, fd; + + /* + * Ensure we have fds 0-2 open so that we have no fd overlaps + * in exec_cgi() later. Just exit on error, we don't have enough + * fds open to output an error message anywhere. + */ + for (c=0; c < 3; c++) { + if (fstat(c, &sb) == -1) { + if ((fd = open("/dev/null", O_RDWR)) != -1) { + if (dup2(fd, c) == -1) + exit(1); + if (fd > c) + close(fd); + } else + exit(1); + } + } while ((c = getopt(argc, argv, "ds:")) != -1) { switch (c) { @@ -851,12 +869,18 @@ exec_cgi(struct request *c) close(s_in[0]); close(s_out[0]); close(s_err[0]); + if (dup2(s_in[1], STDIN_FILENO) == -1) _exit(1); if (dup2(s_out[1], STDOUT_FILENO) == -1) _exit(1); if (dup2(s_err[1], STDERR_FILENO) == -1) _exit(1); + + close(s_in[1]); + close(s_out[1]); + close(s_err[1]); + argv[0] = c->script_name; argv[1] = NULL; if ((env = calloc(c->env_count + 1, sizeof(char*))) == NULL) -- cgit v1.2.3-2-gb3c3