Module Name: src Committed By: yamt Date: Thu Jun 27 23:22:04 UTC 2013
Modified Files: src/bin/sh: eval.c redir.c Log Message: fix descriptor leaks. PR/47805 this fix was taken from FreeBSD SVN rev 199953 (Jilles Tjoelker) ------------------------------------------------------------------------ r199953 | jilles | 2009-11-30 07:33:59 +0900 (Mon, 30 Nov 2009) | 16 lines 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. To generate a diff of this commit: cvs rdiff -u -r1.106 -r1.107 src/bin/sh/eval.c cvs rdiff -u -r1.34 -r1.35 src/bin/sh/redir.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/bin/sh/eval.c diff -u src/bin/sh/eval.c:1.106 src/bin/sh/eval.c:1.107 --- src/bin/sh/eval.c:1.106 Sat Mar 2 22:02:32 2013 +++ src/bin/sh/eval.c Thu Jun 27 23:22:04 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: eval.c,v 1.106 2013/03/02 22:02:32 christos Exp $ */ +/* $NetBSD: eval.c,v 1.107 2013/06/27 23:22:04 yamt Exp $ */ /*- * Copyright (c) 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; #else -__RCSID("$NetBSD: eval.c,v 1.106 2013/03/02 22:02:32 christos Exp $"); +__RCSID("$NetBSD: eval.c,v 1.107 2013/06/27 23:22:04 yamt Exp $"); #endif #endif /* not lint */ @@ -1053,7 +1053,6 @@ normal_fork: #ifdef DEBUG trputs("normal command: "); trargs(argv); #endif - clearredir(vforked); redirect(cmd->ncmd.redirect, vforked ? REDIR_VFORK : 0); if (!vforked) for (sp = varlist.list ; sp ; sp = sp->next) Index: src/bin/sh/redir.c diff -u src/bin/sh/redir.c:1.34 src/bin/sh/redir.c:1.35 --- src/bin/sh/redir.c:1.34 Wed Jun 12 01:36:52 2013 +++ src/bin/sh/redir.c Thu Jun 27 23:22:04 2013 @@ -1,4 +1,4 @@ -/* $NetBSD: redir.c,v 1.34 2013/06/12 01:36:52 yamt Exp $ */ +/* $NetBSD: redir.c,v 1.35 2013/06/27 23:22:04 yamt Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95"; #else -__RCSID("$NetBSD: redir.c,v 1.34 2013/06/12 01:36:52 yamt Exp $"); +__RCSID("$NetBSD: redir.c,v 1.35 2013/06/27 23:22:04 yamt Exp $"); #endif #endif /* not lint */ @@ -67,6 +67,7 @@ __RCSID("$NetBSD: redir.c,v 1.34 2013/06 #define EMPTY -2 /* marks an unused slot in redirtab */ +#define CLOSED -1 /* fd was not open before redir */ #ifndef PIPE_BUF # define PIPESIZE 4096 /* amount of buffering in a pipe */ #else @@ -109,7 +110,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 ; ) @@ -127,41 +127,32 @@ 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, flags); - try++; - goto again; - } - /* FALLTHROUGH*/ + i = CLOSED; + break; default: INTON; error("%d: %s", fd, strerror(errno)); /* NOTREACHED */ } - } - if (!try) { - sv->renamed[fd] = i; - close(fd); - } + } else + (void)fcntl(i, F_SETFD, FD_CLOEXEC); + sv->renamed[fd] = i; INTON; } else { close(fd); } if (fd == 0) fd0_redirected++; - if (!try) - openredirect(n, memory, flags); + openredirect(n, memory, flags); } if (memory[1]) out1 = &memout;