Fix /dev/fd script redirection failure with iomovefd fd range

The original backport of upstream commit aa75399b (RHEL-146564) changed
sh_iomovefd(fd) to sh_iomovefd(fd,10), pushing script-open fds into the
>=10 internal range. On c8s, sh_iomovefd uses recursive dup() rather than
fcntl(F_DUPFD, minfd). dup() always returns the lowest available fd, so
reaching >=10 requires a chain of hops (3->4->5->...->10), each sensitive
to the fd table state at that moment. If another part of ksh opens or
closes an fd between hops, the chain lands somewhere unexpected. Upstream
avoids this with fcntl(F_DUPFD, 10), which jumps directly in one syscall.
This caused fd collisions with the 3-9 user-redirect range tracked by
shp->inuse_bits, resulting in "redirection failed [Bad file descriptor]"
under complex shell environments (set -x + PS4 command substitution +
module load).

Revert the minfd argument from 10 to 3 in path.c (path_opentype, exscript)
and main.c (fdin), restoring the original fd placement behavior while
preserving the /dev/fd $0 fix from RHEL-146564.

Resolves: RHEL-188169
This commit is contained in:
Vincent Mihalkovic 2026-08-11 15:24:52 +02:00
parent c016a5477f
commit 05db1c3657
2 changed files with 9 additions and 5 deletions

View File

@ -224,7 +224,7 @@ index 00a048b..079c2fd 100644
+ * keep that file descriptor closed.
+ */
+ if(fdin<=2)
+ fdin = sh_iomovefd(fdin,10);
+ fdin = sh_iomovefd(fdin,3);
}
shp->readscript = shp->shname;
}
@ -278,7 +278,7 @@ index 993bdfd..05cd956 100644
}
while( fd<0 && pp);
- if(fd>=0 && (fd = sh_iomovefd(fd)) > 0)
+ if(fd>=0 && (fd = sh_iomovefd(fd,10)) > 0)
+ if(fd>=0 && (fd = sh_iomovefd(fd,3)) > 0)
{
fcntl(fd,F_SETFD,FD_CLOEXEC);
shp->fdstatus[fd] |= IOCLEX;
@ -287,7 +287,7 @@ index 993bdfd..05cd956 100644
{
/* move <n> if n=0,1,2 */
- n = sh_iomovefd(n);
+ n = sh_iomovefd(n,10);
+ n = sh_iomovefd(n,3);
if(fstat(n,&statb)>=0 && !(statb.st_mode&(S_ISUID|S_ISGID)))
goto openok;
sh_close(n);
@ -296,7 +296,7 @@ index 993bdfd..05cd956 100644
errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,path);
#endif
- shp->infd = sh_iomovefd(shp->infd);
+ shp->infd = sh_iomovefd(shp->infd,10);
+ shp->infd = sh_iomovefd(shp->infd,3);
#if SHOPT_ACCT
sh_accbegin(path) ; /* reset accounting */
#endif /* SHOPT_ACCT */

View File

@ -6,7 +6,7 @@ Summary: The Original ATT Korn Shell
URL: http://www.kornshell.com/
License: EPL-1.0
Version: %{releasedate}
Release: 271%{?dist}
Release: 272%{?dist}
Source0: http://www.research.att.com/~gsf/download/tgz/ast-ksh.%{release_date}.tgz
Source1: http://www.research.att.com/~gsf/download/tgz/INIT.%{release_date}.tgz
Source2: kshcomp.conf
@ -424,6 +424,10 @@ fi
%config(noreplace) %{_sysconfdir}/binfmt.d/kshcomp.conf
%changelog
* Tue Aug 11 2026 Vincent Mihalkovic <vmihalko@redhat.com> - 20120801-272
- Fix /dev/fd script redirection failure with iomovefd fd range
Resolves: RHEL-188169
* Mon Feb 09 2026 Vincent Mihalkovic <vmihalko@redhat.com> - 20120801-271
- Fix $0 reporting /usr/bin/ksh instead of script name for /dev/fd scripts
Resolves: RHEL-92633