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.
This commit is contained in:
parent
d5abef39fb
commit
34b324060c
@ -883,7 +883,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
#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);
|
||||
|
@ -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;
|
||||
|
27
tools/regression/bin/sh/execution/redir1.0
Normal file
27
tools/regression/bin/sh/execution/redir1.0
Normal file
@ -0,0 +1,27 @@
|
||||
# $FreeBSD$
|
||||
trap ': $((brokenpipe+=1))' pipe
|
||||
|
||||
P=${TMPDIR:-/tmp}
|
||||
cd $P
|
||||
T=$(mktemp -d sh-test.XXXXXX)
|
||||
cd $T
|
||||
|
||||
brokenpipe=0
|
||||
mkfifo fifo1 fifo2
|
||||
read dummy >fifo2 <fifo1 &
|
||||
{
|
||||
exec 4>fifo2
|
||||
} 3<fifo2 # Formerly, sh would keep fd 3 and a duplicate of it open.
|
||||
echo dummy >fifo1
|
||||
if [ $brokenpipe -ne 0 ]; then
|
||||
rc=3
|
||||
fi
|
||||
wait
|
||||
echo dummy >&4
|
||||
if [ $brokenpipe -eq 1 ]; then
|
||||
: ${rc:=0}
|
||||
fi
|
||||
|
||||
rm fifo1 fifo2
|
||||
rmdir ${P}/${T}
|
||||
exit ${rc:-3}
|
29
tools/regression/bin/sh/execution/redir2.0
Normal file
29
tools/regression/bin/sh/execution/redir2.0
Normal file
@ -0,0 +1,29 @@
|
||||
# $FreeBSD$
|
||||
trap ': $((brokenpipe+=1))' pipe
|
||||
|
||||
P=${TMPDIR:-/tmp}
|
||||
cd $P
|
||||
T=$(mktemp -d sh-test.XXXXXX)
|
||||
cd $T
|
||||
|
||||
brokenpipe=0
|
||||
mkfifo fifo1 fifo2
|
||||
{
|
||||
{
|
||||
exec sh -c 'exec <fifo1; read dummy'
|
||||
} 7<&- # fifo2 should be kept open, but not passed to programs
|
||||
true
|
||||
} 7<fifo2 &
|
||||
|
||||
exec 4>fifo2
|
||||
exec 3>fifo1
|
||||
echo dummy >&4
|
||||
if [ $brokenpipe -eq 1 ]; then
|
||||
: ${rc:=0}
|
||||
fi
|
||||
echo dummy >&3
|
||||
wait
|
||||
|
||||
rm fifo1 fifo2
|
||||
rmdir ${P}/${T}
|
||||
exit ${rc:-3}
|
Loading…
Reference in New Issue
Block a user