Finish the fd reassignment fixes from 1.43 and 1.45 ... if we are moving

a fd to an unspecified high fd number, we certainly do not want to hand
that high fd off to other processes after an exec, so always set close-on-exec
on the result (even if lack of fd's means no fd alteration happens.)
This will (eventually) allow some other code that sets close-on-exec to
be removed, but for now, doing it twice won't hurt.   Also, in a N>&M
type redirection, do not set close-on-exec if we don't want it.

OK christos@
This commit is contained in:
kre 2016-05-09 20:50:08 +00:00
parent 183536927f
commit 07ee700a7e
4 changed files with 40 additions and 29 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: eval.c,v 1.122 2016/05/03 13:47:58 kre Exp $ */ /* $NetBSD: eval.c,v 1.123 2016/05/09 20:50:08 kre Exp $ */
/*- /*-
* Copyright (c) 1993 * Copyright (c) 1993
@ -37,7 +37,7 @@
#if 0 #if 0
static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
#else #else
__RCSID("$NetBSD: eval.c,v 1.122 2016/05/03 13:47:58 kre Exp $"); __RCSID("$NetBSD: eval.c,v 1.123 2016/05/09 20:50:08 kre Exp $");
#endif #endif
#endif /* not lint */ #endif /* not lint */
@ -86,11 +86,6 @@ __RCSID("$NetBSD: eval.c,v 1.122 2016/05/03 13:47:58 kre Exp $");
#endif #endif
/* flags in argument to evaltree */
#define EV_EXIT 01 /* exit after evaluating tree */
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
#define EV_BACKCMD 04 /* command executing within back quotes */
STATIC enum skipstate evalskip; /* != SKIPNONE if we are skipping commands */ STATIC enum skipstate evalskip; /* != SKIPNONE if we are skipping commands */
STATIC int skipcount; /* number of levels to skip */ STATIC int skipcount; /* number of levels to skip */
STATIC int loopnest; /* current loop nesting level */ STATIC int loopnest; /* current loop nesting level */
@ -224,7 +219,7 @@ evalstring(char *s, int flag)
while ((n = parsecmd(0)) != NEOF) { while ((n = parsecmd(0)) != NEOF) {
TRACE(("evalstring: "); showtree(n)); TRACE(("evalstring: "); showtree(n));
if (nflag == 0) if (nflag == 0)
evaltree(n, flag); evaltree(n, flag | EV_MORE);
popstackmark(&smark); popstackmark(&smark);
} }
popfile(); popfile();
@ -262,19 +257,20 @@ evaltree(union node *n, int flags)
#endif #endif
switch (n->type) { switch (n->type) {
case NSEMI: case NSEMI:
evaltree(n->nbinary.ch1, flags & EV_TESTED); evaltree(n->nbinary.ch1, (flags & EV_TESTED) |
(n->nbinary.ch2 ? EV_MORE : 0));
if (nflag || evalskip) if (nflag || evalskip)
goto out; goto out;
evaltree(n->nbinary.ch2, flags); evaltree(n->nbinary.ch2, flags);
break; break;
case NAND: case NAND:
evaltree(n->nbinary.ch1, EV_TESTED); evaltree(n->nbinary.ch1, EV_TESTED | EV_MORE);
if (nflag || evalskip || exitstatus != 0) if (nflag || evalskip || exitstatus != 0)
goto out; goto out;
evaltree(n->nbinary.ch2, flags); evaltree(n->nbinary.ch2, flags);
break; break;
case NOR: case NOR:
evaltree(n->nbinary.ch1, EV_TESTED); evaltree(n->nbinary.ch1, EV_TESTED | EV_MORE);
if (nflag || evalskip || exitstatus == 0) if (nflag || evalskip || exitstatus == 0)
goto out; goto out;
evaltree(n->nbinary.ch2, flags); evaltree(n->nbinary.ch2, flags);
@ -286,14 +282,14 @@ evaltree(union node *n, int flags)
popredir(); popredir();
break; break;
case NSUBSHELL: case NSUBSHELL:
evalsubshell(n, flags); evalsubshell(n, flags & ~EV_MORE);
do_etest = !(flags & EV_TESTED); do_etest = !(flags & EV_TESTED);
break; break;
case NBACKGND: case NBACKGND:
evalsubshell(n, flags); evalsubshell(n, flags & ~EV_MORE);
break; break;
case NIF: { case NIF: {
evaltree(n->nif.test, EV_TESTED); evaltree(n->nif.test, EV_TESTED | EV_MORE);
if (nflag || evalskip) if (nflag || evalskip)
goto out; goto out;
if (exitstatus == 0) if (exitstatus == 0)
@ -319,7 +315,7 @@ evaltree(union node *n, int flags)
exitstatus = 0; exitstatus = 0;
break; break;
case NNOT: case NNOT:
evaltree(n->nnot.com, EV_TESTED); evaltree(n->nnot.com, (flags & EV_MORE) | EV_TESTED);
exitstatus = !exitstatus; exitstatus = !exitstatus;
break; break;
case NPIPE: case NPIPE:
@ -365,7 +361,7 @@ evalloop(union node *n, int flags)
TRACE(("evalloop done\n")); TRACE(("evalloop done\n"));
for (;;) { for (;;) {
evaltree(n->nbinary.ch1, EV_TESTED); evaltree(n->nbinary.ch1, EV_TESTED | EV_MORE);
if (nflag) if (nflag)
break; break;
if (evalskip) { if (evalskip) {
@ -384,7 +380,7 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
if (exitstatus == 0) if (exitstatus == 0)
break; break;
} }
evaltree(n->nbinary.ch2, flags & EV_TESTED); evaltree(n->nbinary.ch2, flags & (EV_TESTED | EV_MORE));
status = exitstatus; status = exitstatus;
if (evalskip) if (evalskip)
goto skipping; goto skipping;
@ -418,7 +414,7 @@ evalfor(union node *n, int flags)
loopnest++; loopnest++;
for (sp = arglist.list ; sp ; sp = sp->next) { for (sp = arglist.list ; sp ; sp = sp->next) {
setvar(n->nfor.var, sp->text, 0); setvar(n->nfor.var, sp->text, 0);
evaltree(n->nfor.body, flags & EV_TESTED); evaltree(n->nfor.body, flags & (EV_TESTED | EV_MORE));
status = exitstatus; status = exitstatus;
if (nflag) if (nflag)
break; break;
@ -886,6 +882,8 @@ evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
INTOFF; INTOFF;
jp = makejob(cmd, 1); jp = makejob(cmd, 1);
mode = cmd->ncmd.backgnd; mode = cmd->ncmd.backgnd;
if (mode)
flags &= ~EV_MORE;
if (flags & EV_BACKCMD) { if (flags & EV_BACKCMD) {
mode = FORK_NOJOB; mode = FORK_NOJOB;
if (sh_pipe(pip) < 0) if (sh_pipe(pip) < 0)
@ -972,7 +970,7 @@ normal_fork:
#ifdef DEBUG #ifdef DEBUG
trputs("Shell function: "); trargs(argv); trputs("Shell function: "); trargs(argv);
#endif #endif
redirect(cmd->ncmd.redirect, REDIR_PUSH); redirect(cmd->ncmd.redirect, flags & EV_MORE ? REDIR_PUSH : 0);
saveparam = shellparam; saveparam = shellparam;
shellparam.malloc = 0; shellparam.malloc = 0;
shellparam.reset = 1; shellparam.reset = 1;
@ -1010,7 +1008,8 @@ normal_fork:
freeparam(&shellparam); freeparam(&shellparam);
shellparam = saveparam; shellparam = saveparam;
handler = savehandler; handler = savehandler;
popredir(); if (flags & EV_MORE)
popredir();
INTON; INTON;
if (evalskip == SKIPFUNC) { if (evalskip == SKIPFUNC) {
evalskip = SKIPNONE; evalskip = SKIPNONE;

View File

@ -1,4 +1,4 @@
/* $NetBSD: eval.h,v 1.16 2014/05/31 14:42:18 christos Exp $ */ /* $NetBSD: eval.h,v 1.17 2016/05/09 20:50:08 kre Exp $ */
/*- /*-
* Copyright (c) 1991, 1993 * Copyright (c) 1991, 1993
@ -71,3 +71,9 @@ void stop_skipping(void); /* reset internal skipping state to SKIPNONE */
* Only for use by reset() in init.c! * Only for use by reset() in init.c!
*/ */
void reset_eval(void); void reset_eval(void);
/* flags in argument to evaltree */
#define EV_EXIT 0x01 /* exit after evaluating tree */
#define EV_TESTED 0x02 /* exit status is checked; ignore -e flag */
#define EV_BACKCMD 0x04 /* command executing within back quotes */
#define EV_MORE 0x08 /* more commands in this sub-shell */

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.64 2016/03/31 16:16:35 christos Exp $ */ /* $NetBSD: main.c,v 1.65 2016/05/09 20:50:08 kre Exp $ */
/*- /*-
* Copyright (c) 1991, 1993 * Copyright (c) 1991, 1993
@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1991, 1993\
#if 0 #if 0
static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95"; static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95";
#else #else
__RCSID("$NetBSD: main.c,v 1.64 2016/03/31 16:16:35 christos Exp $"); __RCSID("$NetBSD: main.c,v 1.65 2016/05/09 20:50:08 kre Exp $");
#endif #endif
#endif /* not lint */ #endif /* not lint */
@ -282,7 +282,7 @@ cmdloop(int top)
} else if (n != NULL && nflag == 0) { } else if (n != NULL && nflag == 0) {
job_warning = (job_warning == 2) ? 1 : 0; job_warning = (job_warning == 2) ? 1 : 0;
numeof = 0; numeof = 0;
evaltree(n, 0); evaltree(n, EV_MORE);
} }
popstackmark(&smark); popstackmark(&smark);
setstackmark(&smark); setstackmark(&smark);

View File

@ -1,4 +1,4 @@
/* $NetBSD: redir.c,v 1.45 2016/05/08 20:14:27 kre Exp $ */ /* $NetBSD: redir.c,v 1.46 2016/05/09 20:50:08 kre Exp $ */
/*- /*-
* Copyright (c) 1991, 1993 * Copyright (c) 1991, 1993
@ -37,7 +37,7 @@
#if 0 #if 0
static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95"; static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
#else #else
__RCSID("$NetBSD: redir.c,v 1.45 2016/05/08 20:14:27 kre Exp $"); __RCSID("$NetBSD: redir.c,v 1.46 2016/05/09 20:50:08 kre Exp $");
#endif #endif
#endif /* not lint */ #endif /* not lint */
@ -302,8 +302,8 @@ openredirect(union node *redir, char memory[10], int flags)
memory[redir->ndup.dupfd]) memory[redir->ndup.dupfd])
memory[fd] = 1; memory[fd] = 1;
else else
copyfd(redir->ndup.dupfd, fd, 1, copyfd(redir->ndup.dupfd, fd, 1, (flags &
(flags & REDIR_PUSH) != 0); (REDIR_PUSH|REDIR_KEEP)) == REDIR_PUSH);
} else } else
close(fd); close(fd);
INTON; INTON;
@ -514,7 +514,7 @@ to_upper_fd(int fd)
if (big_sh_fd < 10) if (big_sh_fd < 10)
find_big_fd(); find_big_fd();
do { do {
i = fcntl(fd, F_DUPFD, big_sh_fd); i = fcntl(fd, F_DUPFD_CLOEXEC, big_sh_fd);
if (i >= 0) { if (i >= 0) {
if (fd != i) if (fd != i)
close(fd); close(fd);
@ -525,5 +525,11 @@ to_upper_fd(int fd)
find_big_fd(); find_big_fd();
} while (big_sh_fd > 10); } while (big_sh_fd > 10);
/*
* If we wamted to move this fd to some random high number
* we certainly do not intend to pass it through exec, even
* if the reassignment failed.
*/
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
return fd; return fd;
} }