Skip to content

Commit

Permalink
Fork in case of negative pwdfd while inside of cd(1)
Browse files Browse the repository at this point in the history
Preempting a fork is now unnecessary, as cd can just fork if it knows
the current pwdfd is invalid.
  • Loading branch information
JohnoKing committed Dec 18, 2024
1 parent d1b5ffd commit cc8872d
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/cmd/ksh93/bltins/cd_pwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ int b_cd(int argc, char *argv[],Shbltin_t *context)
* If sh_subshell() in subshell.c cannot use fchdir(2) to restore the PWD using a saved file descriptor,
* we must fork any virtual subshell now to avoid the possibility of ending up in the wrong PWD on exit.
*/
if(sh.subshell && !sh.subshare && !test_inode(sh.pwd,e_dot))
if(sh.subshell && !sh.subshare && (!sh_validate_subpwdfd() || !test_inode(sh.pwd,e_dot)))
sh_subfork();
/*
* Do $CDPATH processing, except if the path is absolute or the first component is '.' or '..'
Expand Down
1 change: 1 addition & 0 deletions src/cmd/ksh93/include/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ extern void sh_subjobcheck(pid_t);
extern int sh_subsavefd(int);
extern void sh_subtmpfile(void);
extern void sh_pwdupdate(int);
extern int sh_validate_subpwdfd(void);
extern char *sh_substitute(const char*,const char*,char*);
extern void sh_timetraps(void);
extern const char *_sh_translate(const char*);
Expand Down
12 changes: 10 additions & 2 deletions src/cmd/ksh93/sh/subshell.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,16 @@ void sh_pwdupdate(int fd)
sh.pwdfd = fd;
}

/*
* Check if the parent shell has a valid PWD fd to return to.
* Only for use by cd inside of virtual subshells.
*/
int sh_validate_subpwdfd(void)
{
struct subshell *sp = subshell_data;
return sp->pwdfd > 0;
}

/*
* Run command tree <t> in a virtual subshell
* If comsub is not null, then output will be placed in temp file (or buffer)
Expand Down Expand Up @@ -597,8 +607,6 @@ Sfio_t *sh_subshell(Shnode_t *t, volatile int flags, int comsub)
if(sh.savesig < 0)
{
sh.savesig = 0;
if(sp->pwdfd < 0 && !sh.subshare) /* if we don't have a file descriptor to our PWD ... */
sh_subfork(); /* ...we have to fork, as we cannot fchdir back to it. */
/* Virtual subshells are not safe to suspend (^Z, SIGTSTP) in the interactive main shell. */
if(sh_isstate(SH_INTERACTIVE))
{
Expand Down

0 comments on commit cc8872d

Please sign in to comment.