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

trap: fix use after free (#446)

This commit adds a fix for the trap command, backported from a fork
of ksh2020: https://github.com/l0stman/ksh/commit/2033375f

src/cmd/ksh93/sh/jobs.c: job_chldtrap():
- Fixed a use after free bug in the for loop. The string pointed to
  by sh.st.trapcom[SIGCHLD] may be freed from memory after
  sh_trap(), so it must be reobtained each time sh_trap() is called
  from within the for loop.
This commit is contained in:
Johnothan King 2022-02-04 18:29:23 -08:00 committed by Martijn Dekker
parent 8e72608c1c
commit fb696ecfae
4 changed files with 14 additions and 5 deletions

5
NEWS
View file

@ -9,6 +9,11 @@ Any uppercase BUG_* names are modernish shell bug IDs.
values. Previously, arithmetic $((var=1)) or conditional ${var:=value}
assignments were not exported even with allexport on.
- Fixed a memory leak that could occur when using traps.
- Fixed a use after free issue that could occur when modifying or setting
a SIGCHLD trap.
2022-02-01:
- Upon invocation, the interactive shell no longer leaves the user without

View file

@ -170,7 +170,7 @@ extern int job_post(pid_t,pid_t);
extern void *job_subsave(void);
extern void job_subrestore(void*);
#if SHOPT_BGX
extern void job_chldtrap(const char*,int);
extern void job_chldtrap(int);
#endif /* SHOPT_BGX */
#ifdef JOBS
extern void job_init(int);

View file

@ -350,6 +350,8 @@ void sh_sigreset(register int mode)
}
}
if(sh.st.trapcom[0] && sh.st.trapcom[0] != Empty)
free(sh.st.trapcom[0]);
sh.st.trapcom[0] = 0;
if(mode)
sh.st.trapmax = 0;
@ -411,7 +413,7 @@ void sh_chktrap(void)
sh_timetraps();
#if SHOPT_BGX
if((sh.sigflag[SIGCHLD]&SH_SIGTRAP) && sh.st.trapcom[SIGCHLD])
job_chldtrap(sh.st.trapcom[SIGCHLD],1);
job_chldtrap(1);
#endif /* SHOPT_BGX */
while(--sig>=0)
{

View file

@ -219,7 +219,7 @@ static struct back_save bck;
typedef int (*Waitevent_f)(int,long,int);
#if SHOPT_BGX
void job_chldtrap(const char *trap, int unpost)
void job_chldtrap(int unpost)
{
register struct process *pw,*pwnext;
pid_t bckpid;
@ -240,7 +240,9 @@ void job_chldtrap(const char *trap, int unpost)
sh.savexit = pw->p_exit;
if(pw->p_flag&P_SIGNALLED)
sh.savexit |= SH_EXITSIG;
sh_trap(trap,0);
/* The trap handler for SIGCHLD may change after sh_trap() because of
'trap - CHLD', so it's obtained for each iteration of the loop. */
sh_trap(sh.st.trapcom[SIGCHLD],0);
if(pw->p_pid==bckpid && unpost)
job_unpost(pw,0);
sh.savexit = oldexit;
@ -434,7 +436,7 @@ int job_reap(register int sig)
{
sh.sigflag[SIGCHLD] |= SH_SIGTRAP;
if(sig==0)
job_chldtrap(sh.st.trapcom[SIGCHLD],0);
job_chldtrap(0);
else
sh.trapnote |= SH_SIGTRAP;
}