1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-13 03:32:24 +00:00

Fix infinite loop when posix_spawn fails (re: 0863a8eb) (#468)

This commit fixes an infinite loop introduced in commit 0863a8eb
that caused ksh to enter an infinite loop if posix_spawn failed
to start a new process after setting the terminal process group.
Reproducer (warning: it will cause ksh to crash Wayland sessions
and drives up CPU usage by a ton):

   $ /tmp/this/file/does/not/exist
   /usr/bin/ksh: /tmp/this/file/does/not/exist: not found
   $ <Press enter>
   (ksh now prints $PS1 in a loop until killed with SIGKILL)

The first bug fixed is the infinite loop that occurs when
posix_spawn fails to execute a command. This was fixed by setting
the terminal process group to the main interactive shell.

The second bug fixed is related to the signal handling of the
SIGTTIN, SIGTTOU and SIGTSTP signals. In sh_ntfork() these signals
are set to their default signal handlers (SIG_DFL) before running
a command. The signal handlers were only restored to SIG_IGN
(ignore signal) when sh_ntfork() successfully ran a command.
This could cause a SIGTTOU lockup under strace when a command
failed to execute in an interactive shell, while also being one
cause of the infinite loop.

src/cmd/ksh93/sh/xec.c: sh_ntfork():
- Restore the terminal process group if posix_spawn failed to
  launch a new process. This is necessary because posix_spawn will
  set the terminal process group before it attempts to run a
  command and doesn't restore it on failure.
This commit is contained in:
Johnothan King 2022-02-23 07:11:24 -08:00 committed by Martijn Dekker
parent 2e5fd4d4c1
commit bb3527aea5
2 changed files with 34 additions and 11 deletions

9
NEWS
View file

@ -3,12 +3,19 @@ For full details, see the git log at: https://github.com/ksh93/ksh/tree/1.0
Any uppercase BUG_* names are modernish shell bug IDs.
2022-08-23:
2022-02-23:
- When reading input from the keyboard, ksh now turns off nonblocking I/O
mode for standard input if a previously ran program left it on, so that
interactive programs that expect it to be off work properly.
- Fixed a regression introduced on 2022-02-02 that caused interactive shells
to enter an infinite loop when a command failed to execute on Linux
systems with version 2.35 of glibc.
- Fixed a SIGTTOU lockup that could cause ksh to freeze under strace(1) after
a command failed to execute in an interactive shell.
2022-02-18:
- Fixed a regression introduced on 2021-04-11 that caused the += operator in

View file

@ -3598,19 +3598,35 @@ static pid_t sh_ntfork(const Shnode_t *t,char *argv[],int *jobid,int flag)
fail:
if(jobfork && spawnpid<0)
job_fork(-2);
if(spawnpid == -1) switch(errno=sh.path_err)
if(spawnpid == -1)
{
case ENOENT:
errormsg(SH_DICT,ERROR_exit(ERROR_NOENT),e_found+4);
UNREACHABLE();
#if _use_ntfork_tcpgrp
if(jobwasset)
{
signal(SIGTTIN,SIG_IGN);
signal(SIGTTOU,SIG_IGN);
if(sh_isstate(SH_INTERACTIVE))
signal(SIGTSTP,SIG_IGN);
else
signal(SIGTSTP,SIG_DFL);
}
if(job.jobcontrol)
tcsetpgrp(job.fd,sh.pid);
#endif /* _use_ntfork_tcpgrp */
switch(errno=sh.path_err)
{
case ENOENT:
errormsg(SH_DICT,ERROR_exit(ERROR_NOENT),e_found+4);
UNREACHABLE();
#ifdef ENAMETOOLONG
case ENAMETOOLONG:
errormsg(SH_DICT,ERROR_exit(ERROR_NOENT),e_toolong+4);
UNREACHABLE();
case ENAMETOOLONG:
errormsg(SH_DICT,ERROR_exit(ERROR_NOENT),e_toolong+4);
UNREACHABLE();
#endif
default:
errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec+4);
UNREACHABLE();
default:
errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec+4);
UNREACHABLE();
}
}
job_unlock();
}