diff options
author | florian | 2013-10-29 17:59:47 +0000 |
---|---|---|
committer | Wynn Wolf Arbor | 2020-05-24 12:33:55 +0200 |
commit | 31d323c3f90e5d5665f43a76e7497bfb36b5cba7 (patch) | |
tree | 0e41e84c3bef6f5b1e5f7329d1df99fd234bad24 | |
parent | ae2ce6fc8e619b4ac5fd947994563410ef326756 (diff) | |
download | slowcgi-31d323c3f90e5d5665f43a76e7497bfb36b5cba7.tar.gz |
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@
-rw-r--r-- | slowcgi.c | 28 |
1 files changed, 26 insertions, 2 deletions
@@ -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 <dlg@openbsd.org> * Copyright (c) 2013 Florian Obser <florian@openbsd.org> @@ -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) |