From a43bb4f1bdec71b7cb25da906ed13ece81c06582 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Wed, 20 Jul 2022 06:34:47 +0200 Subject: [PATCH] Simplify SHOPT_SPAWN procsub file descriptor leak fix (re: 6d63b57d) Before the fix, a file descriptor leak could occur on command not found because sh_ntfork() saves sh.topfd on function entry (as part of the sh_pushcontext() macro expansion) and uses that value to sh_iorestore(). Process substitution arguments will already have been processed by then and their file descriptors opened, so those were not closed on restore. To compensate, the committed fix added a second sh_iorestore() call using the topfd variable, in which sh_exec) saves the value of sh.topfd on its function entry. A more elegant fix is to pass that value to sh_ntfork() as an argument so its own sh_iorestore() call does the right thing. --- src/cmd/ksh93/sh/xec.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c index 1b1d4e330..ee19ab87e 100644 --- a/src/cmd/ksh93/sh/xec.c +++ b/src/cmd/ksh93/sh/xec.c @@ -65,7 +65,7 @@ extern int nice(int); #endif /* _lib_nice */ #if SHOPT_SPAWN - static pid_t sh_ntfork(const Shnode_t*,char*[],int*); + static pid_t sh_ntfork(const Shnode_t*,char*[],int*,int); #endif /* SHOPT_SPAWN */ static void sh_funct(Namval_t*, int, char*[], struct argnod*,int); @@ -1517,13 +1517,9 @@ int sh_exec(register const Shnode_t *t, int flags) if(com && !job.jobcontrol) #endif /* _use_ntfork_tcpgrp */ { - parent = sh_ntfork(t,com,&jobid); + parent = sh_ntfork(t,com,&jobid,topfd); if(parent<0) - { - if(sh.topfd > topfd) - sh_iorestore(topfd,0); /* prevent FD leak from 'not found' */ break; - } } else #endif /* SHOPT_SPAWN */ @@ -3389,7 +3385,7 @@ static void sigreset(int mode) * Incompatible with job control on interactive shells (job.jobcontrol) if * the system does not support posix_spawn_file_actions_addtcsetpgrp_np(). */ -static pid_t sh_ntfork(const Shnode_t *t,char *argv[],int *jobid) +static pid_t sh_ntfork(const Shnode_t *t,char *argv[],int *jobid,int topfd) { static pid_t spawnpid; struct checkpt *buffp = (struct checkpt*)stkalloc(sh.stk,sizeof(struct checkpt)); @@ -3559,8 +3555,8 @@ static pid_t sh_ntfork(const Shnode_t *t,char *argv[],int *jobid) if(jmpval==SH_JMPSCRIPT) nv_setlist(t->com.comset,NV_EXPORT|NV_IDENT|NV_ASSIGN,0); } - if(t->com.comio && (jmpval || spawnpid<=0)) - sh_iorestore(buffp->topfd,jmpval); + if(t->com.comio && (jmpval || spawnpid<=0) && sh.topfd > topfd) + sh_iorestore(topfd,jmpval); if(jmpval>SH_JMPCMD) siglongjmp(*sh.jmplist,jmpval); if(spawnpid>0)