Skip to content

Commit

Permalink
Fix subshell file descriptor leak
Browse files Browse the repository at this point in the history
A file descriptor (at least 3, can't reproduce for 4 and up) opened
with 'exec' or 'redirect' in a virtual/non-forked subshell survived
that subshell after exiting it:

    $ ksh -c '(redirect 3>&1); echo bug >&3'
    bug

src/cmd/ksh93/sh/io.c:
- Apply a patch from OpenSUSE (ksh93-redirectleak.dif). Source:
  https://build.opensuse.org/package/show/openSUSE:Leap:42.3:Update/ksh

src/cmd/ksh93/tests/io.sh:
- Add regression test.

Thanks to Marc Wilson for flagging this up.
  • Loading branch information
McDutchie committed Jul 21, 2020
1 parent 0c96f97 commit db72f41
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 0 deletions.
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ Any uppercase BUG_* names are modernish shell bug IDs.
- If a shell function and a built-in command by the same name exist,
'whence -a' and 'type -a' now report both.

- Fixed a bug that caused file descriptors opened with 'redirect' or 'exec'
to survive a subshell environment after exiting it.

2020-07-19:

- Fixed a crash that occured in the '.' command when using kshdb.
Expand Down
10 changes: 10 additions & 0 deletions src/cmd/ksh93/sh/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1422,7 +1422,17 @@ int sh_redirect(Shell_t *shp,struct ionod *iop, int flag)
sh_iosave(shp,fn,indx,tname?fname:(trunc?Empty:0));
}
else if(sh_subsavefd(fn))
{
if(fd==fn)
{
if((r=sh_fcntl(fd,F_DUPFD,10)) > 0)
{
fd = r;
sh_close(fn);
}
}
sh_iosave(shp,fn,indx|IOSUBSHELL,tname?fname:0);
}
}
if(fd<0)
{
Expand Down
10 changes: 10 additions & 0 deletions src/cmd/ksh93/tests/io.sh
Original file line number Diff line number Diff line change
Expand Up @@ -567,5 +567,15 @@ result=$("$SHELL" -ic 'echo >(true) >/dev/null' 2>&1)
"$SHELL" -c 'true 9>&20000000000000000000' 2> /dev/null
[[ $? == 1 ]] || err_exit "Out of range file descriptors cause redirections to segfault"
# ======
# A file descriptor opened with 'exec' or 'redirect' leaked out of a subshell.
exec 3>&- # close FD 3 just in case
(exec 3>"$tmp/fdleak.txt")
{ echo bug >&3; } 2>/dev/null
if [[ -s "$tmp/fdleak.txt" ]]
then exec 3>&-
err_exit "Open file descriptor leaks out of subshell"
fi
# ======
exit $((Errors<125?Errors:125))

0 comments on commit db72f41

Please sign in to comment.