1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-13 11:42:21 +00:00

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.
This commit is contained in:
Martijn Dekker 2022-07-20 06:34:47 +02:00
parent 1884f57a74
commit a43bb4f1bd

View file

@ -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)