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;

Reply via email to