diff options
author | jilles <jilles@FreeBSD.org> | 2009-11-29 22:33:59 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2009-11-29 22:33:59 +0000 |
commit | 171b4944c1b7aaf979f3823e9bdfcdae155cb5ba (patch) | |
tree | 81617e0dd9ce9709a051aa522582d76eb94cb5a5 /bin | |
parent | 170d197358ca5cca91353b7adc3914268bbb9f69 (diff) | |
download | FreeBSD-src-171b4944c1b7aaf979f3823e9bdfcdae155cb5ba.zip FreeBSD-src-171b4944c1b7aaf979f3823e9bdfcdae155cb5ba.tar.gz |
Fix some cases where file descriptors from redirections leak to programs.
- Redirecting fds that were not open before kept two copies of the
redirected file.
sh -c '{ :; } 7>/dev/null; fstat -p $$; true'
(both fd 7 and 10 remained open)
- File descriptors used to restore things after redirection were not
set close-on-exec, instead they were explicitly closed before executing
a program normally and before executing a shell procedure. The latter
must remain but the former is replaced by close-on-exec.
sh -c 'exec 7</; { exec fstat -p $$; } 7>/dev/null; true'
(fd 10 remained open)
The examples above are simpler than the testsuite because I do not want to
use fstat or procstat in the testsuite.
Diffstat (limited to 'bin')
-rw-r--r-- | bin/sh/eval.c | 1 | ||||
-rw-r--r-- | bin/sh/redir.c | 22 |
2 files changed, 7 insertions, 16 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 2bad138..f772456 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -883,7 +883,6 @@ cmddone: #ifdef DEBUG trputs("normal command: "); trargs(argv); #endif - clearredir(); redirect(cmd->ncmd.redirect, 0); for (sp = varlist.list ; sp ; sp = sp->next) setvareq(sp->text, VEXPORT|VSTACK); diff --git a/bin/sh/redir.c b/bin/sh/redir.c index 08878f6..2239b9f 100644 --- a/bin/sh/redir.c +++ b/bin/sh/redir.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #define EMPTY -2 /* marks an unused slot in redirtab */ +#define CLOSED -1 /* fd was not open before redir */ #define PIPESIZE 4096 /* amount of buffering in a pipe */ @@ -101,7 +102,6 @@ redirect(union node *redir, int flags) struct redirtab *sv = NULL; int i; int fd; - int try; char memory[10]; /* file descriptors to write to memory */ for (i = 10 ; --i >= 0 ; ) @@ -116,38 +116,30 @@ redirect(union node *redir, int flags) } for (n = redir ; n ; n = n->nfile.next) { fd = n->nfile.fd; - try = 0; if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && n->ndup.dupfd == fd) continue; /* redirect from/to same file descriptor */ if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { INTOFF; -again: if ((i = fcntl(fd, F_DUPFD, 10)) == -1) { switch (errno) { case EBADF: - if (!try) { - openredirect(n, memory); - try++; - goto again; - } - /* FALLTHROUGH*/ + i = CLOSED; + break; default: INTON; error("%d: %s", fd, strerror(errno)); break; } - } - if (!try) { - sv->renamed[fd] = i; - } + } else + (void)fcntl(i, F_SETFD, FD_CLOEXEC); + sv->renamed[fd] = i; INTON; } if (fd == 0) fd0_redirected++; - if (!try) - openredirect(n, memory); + openredirect(n, memory); } if (memory[1]) out1 = &memout; |