summaryrefslogtreecommitdiffstats
path: root/bin/sh/redir.c
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2009-11-29 22:33:59 +0000
committerjilles <jilles@FreeBSD.org>2009-11-29 22:33:59 +0000
commit171b4944c1b7aaf979f3823e9bdfcdae155cb5ba (patch)
tree81617e0dd9ce9709a051aa522582d76eb94cb5a5 /bin/sh/redir.c
parent170d197358ca5cca91353b7adc3914268bbb9f69 (diff)
downloadFreeBSD-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/sh/redir.c')
-rw-r--r--bin/sh/redir.c22
1 files changed, 7 insertions, 15 deletions
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;
OpenPOWER on IntegriCloud