diff --git a/SOURCES/ksh-1.0.10-blankline.patch b/SOURCES/ksh-1.0.10-blankline.patch new file mode 100644 index 0000000..3ec59b4 --- /dev/null +++ b/SOURCES/ksh-1.0.10-blankline.patch @@ -0,0 +1,194 @@ +From a1fcad4bf65fe26a3f9a386b63732ab151ce03ec Mon Sep 17 00:00:00 2001 +From: Martijn Dekker +Date: Thu, 5 Dec 2024 02:24:39 +0000 +Subject: [PATCH] vi: Fix recalling lines starting with whitespace (re: + 5eeeed06) + +@jghub reports: +> if for some reason a command is entered with leading whitespace, +> the leading whitespace is preserved in the history file (in +> ksh93u+, too). such commands can be recalled from history in 93u+ +> without problem, both, in vi and emacs mode. +> +> but in 93u+m such entries are simply ignored when using vi-mode +> (set -o vi), i.e. the k and j commands skip over such entries. +> emacs mode still works just fine. + +Analysis: the blankline() function in vi.c and emacs.c is used to +check for whitespace up to the cursor position. This is used for +tab completion and fullscreen editor invocation, where that is +okay, and for history recall, where that should be checking the +entire line instead. + +In emacs.c this was not really a problem because arrowing up (or +^P) positions the cursor to the end of the line anyway. But in vi, +arrowing up (or 'k') positions the cursor at the beginning. + +src/cmd/ksh93/edit/vi.c: +- Amend blankline() with an 'uptocursor' argument. If nonzero, it + checks the current line for whitespace up to the cursor position, + otherwise it checks the entire line. +- Pass uptocursor==0 to blankline() for history recall and 1 for + tab completion. + +src/cmd/ksh93/edit/emacs.c: +- Apply the same change here for consistency, even though it's + perhaps not really necessary. If ever a form of recall is added + that doesn't position the cursor at the end, then that won't + introduce this bug there. + +Thanks to @pghvlaans for input into the fix. +Resolves: https://github.com/ksh93/ksh/issues/799 +--- + src/cmd/ksh93/edit/emacs.c | 14 +++++++------- + src/cmd/ksh93/edit/vi.c | 16 ++++++++-------- + src/cmd/ksh93/tests/pty.sh | 12 ++++++++++++ + 3 files changed, 27 insertions(+), 15 deletions(-) + +diff --git a/src/cmd/ksh93/edit/emacs.c b/src/cmd/ksh93/edit/emacs.c +index 128e592..408f6e7 100644 +--- a/src/cmd/ksh93/edit/emacs.c ++++ b/src/cmd/ksh93/edit/emacs.c +@@ -178,7 +178,7 @@ static void search(Emacs_t*,genchar*,int); + static void setcursor(Emacs_t*,int, int); + static void show_info(Emacs_t*,const char*); + static void xcommands(Emacs_t*,int); +-static char blankline(Emacs_t*, genchar*); ++static int blankline(Emacs_t*, genchar*, int); + + int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + { +@@ -720,9 +720,9 @@ update: + cur = eol; + draw(ep,UPDATE); + /* skip blank lines when going up/down in history */ +- if(c==cntl('N') && hline != histlines && blankline(ep,out)) ++ if(c==cntl('N') && hline != histlines && blankline(ep,out,0)) + ed_ungetchar(ep->ed,cntl('N')); +- else if(c==cntl('P') && hline != hismin && blankline(ep,out)) ++ else if(c==cntl('P') && hline != hismin && blankline(ep,out,0)) + ed_ungetchar(ep->ed,cntl('P')); + continue; + } +@@ -1023,7 +1023,7 @@ static int escape(Emacs_t* ep,genchar *out,int count) + case '*': /* filename expansion */ + case '=': /* escape = - list all matching file names */ + { +- if(cur<1 || blankline(ep,out)) ++ if(cur<1 || blankline(ep,out,1)) + { + beep(); + return -1; +@@ -1312,7 +1312,7 @@ static void xcommands(Emacs_t *ep,int count) + case cntl('E'): /* invoke emacs on current command */ + if(eol>=0 && sh.hist_ptr) + { +- if(blankline(ep,drawbuff)) ++ if(blankline(ep,drawbuff,1)) + { + cur = 0; + eol = 1; +@@ -1785,11 +1785,11 @@ static int _isword(int c) + /* + * determine if the command line is blank (empty or all whitespace) + */ +-static char blankline(Emacs_t *ep, genchar *out) ++static int blankline(Emacs_t *ep, genchar *out, int uptocursor) + { + int x; + ep->mark = cur; +- for(x=0; x < cur; x++) ++ for(x=0; uptocursor ? (x < cur) : (x <= eol); x++) + { + #if SHOPT_MULTIBYTE + if(!iswspace((wchar_t)out[x])) +diff --git a/src/cmd/ksh93/edit/vi.c b/src/cmd/ksh93/edit/vi.c +index fac40ee..852613c 100644 +--- a/src/cmd/ksh93/edit/vi.c ++++ b/src/cmd/ksh93/edit/vi.c +@@ -176,7 +176,7 @@ typedef struct _vi_ + + static const char paren_chars[] = "([{)]}"; /* for % command */ + +-static char blankline(Vi_t*); ++static int blankline(Vi_t*, int); + static void cursor(Vi_t*, int); + static void del_line(Vi_t*,int); + static int getcount(Vi_t*,int); +@@ -667,9 +667,9 @@ static int cntlmode(Vi_t *vp) + } + #endif /* SHOPT_EDPREDICT */ + /* skip blank lines when going up/down in history */ +- if((c=='k' || c=='-') && curhline != histmin && blankline(vp)) ++ if((c=='k' || c=='-') && curhline != histmin && blankline(vp,0)) + ed_ungetchar(vp->ed,'k'); +- else if((c=='j' || c=='+') && curhline != histmax && blankline(vp)) ++ else if((c=='j' || c=='+') && curhline != histmax && blankline(vp,0)) + ed_ungetchar(vp->ed,'j'); + break; + +@@ -693,7 +693,7 @@ static int cntlmode(Vi_t *vp) + case 'v': + if(vp->repeat_set==0) + { +- if(blankline(vp) || cur_virt == INVALID) ++ if(blankline(vp,1) || cur_virt == INVALID) + { + cur_virt = 0; + last_virt = cur_virt; +@@ -1294,7 +1294,7 @@ static void getline(Vi_t* vp,int mode) + + case '\t': /** command completion **/ + { +- if(blankline(vp)) ++ if(blankline(vp,1)) + { + ed_ringbell(); + break; +@@ -2317,7 +2317,7 @@ addin: + case '\\': /** do file name completion in place **/ + case '=': /** list file name expansions **/ + { +- if(cur_virt == INVALID || blankline(vp)) ++ if(cur_virt == INVALID || blankline(vp,1)) + return BAD; + /* FALLTHROUGH */ + save_v(vp); +@@ -2673,10 +2673,10 @@ yankeol: + /* + * determine if the command line is blank (empty or all whitespace) + */ +-static char blankline(Vi_t *vp) ++static int blankline(Vi_t *vp, int uptocursor) + { + int x; +- for(x=0; x <= cur_virt; x++) ++ for(x=0; x <= (uptocursor ? cur_virt : last_virt); x++) + { + #if SHOPT_MULTIBYTE + if(!iswspace((wchar_t)virtual[x])) +diff --git a/src/cmd/ksh93/tests/pty.sh b/src/cmd/ksh93/tests/pty.sh +index b4f8e28..ea0c616 100755 +--- a/src/cmd/ksh93/tests/pty.sh ++++ b/src/cmd/ksh93/tests/pty.sh +@@ -1269,5 +1269,17 @@ w print Exit status $? + u ^Exit status 0\r\n$ + ! + ++((SHOPT_VSH)) && tst $LINENO <<"!" ++L 'k' skips over history entries starting with whitespace ++# https://github.com/ksh93/ksh/issues/799 ++ ++d 40 ++p :test-1: ++w true ++p :test-2: ++c \Ek ++r :test-2: true ++! ++ + # ====== + exit $((Errors<125?Errors:125)) +-- +2.49.0 + diff --git a/SOURCES/ksh-1.0.10-pjob.patch b/SOURCES/ksh-1.0.10-pjob.patch new file mode 100644 index 0000000..fca0dd4 --- /dev/null +++ b/SOURCES/ksh-1.0.10-pjob.patch @@ -0,0 +1,101 @@ +From 685f18d36e162c6f6baf44e1c2c8c762ee41466d Mon Sep 17 00:00:00 2001 +From: Vincent Mihalkovic +Date: Sat, 13 Jul 2024 23:45:07 +0200 +Subject: [PATCH] jobs: change p_job variable type from short to int (#763) + +This change addresses an issue where ksh has undefined behavior +when the number of jobs exceeds `2^15 - 1` (32767), which is the +maximum value for a `short`. The short integer overflow happened in +jobs.c, line 1210. +--- + src/cmd/ksh93/include/jobs.h | 5 +++-- + src/cmd/ksh93/sh/jobs.c | 11 ++++++----- + 2 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/src/cmd/ksh93/include/jobs.h b/src/cmd/ksh93/include/jobs.h +index 4ae48d70fb7a..758804118f30 100644 +--- a/src/cmd/ksh93/include/jobs.h ++++ b/src/cmd/ksh93/include/jobs.h +@@ -2,7 +2,7 @@ + * * + * This software is part of the ast package * + * Copyright (c) 1982-2011 AT&T Intellectual Property * +-* Copyright (c) 2020-2023 Contributors to ksh 93u+m * ++* Copyright (c) 2020-2024 Contributors to ksh 93u+m * + * and is licensed under the * + * Eclipse Public License, Version 2.0 * + * * +@@ -14,6 +14,7 @@ + * Martijn Dekker * + * Johnothan King * + * Anuradha Weeraman * ++* Vincent Mihalkovic * + * * + ***********************************************************************/ + #ifndef JOB_NFLAG +@@ -51,7 +52,7 @@ struct process + pid_t p_pid; /* process ID */ + pid_t p_pgrp; /* process group */ + pid_t p_fgrp; /* process group when stopped */ +- short p_job; /* job number of process */ ++ int p_job; /* job number of process */ + unsigned short p_exit; /* exit value or signal number */ + unsigned short p_exitmin; /* minimum exit value for xargs */ + unsigned short p_flag; /* flags - see below */ +diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c +index 871658256f15..86bbe5a9c949 100644 +--- a/src/cmd/ksh93/sh/jobs.c ++++ b/src/cmd/ksh93/sh/jobs.c +@@ -13,6 +13,7 @@ + * David Korn * + * Martijn Dekker * + * Johnothan King * ++* Vincent Mihalkovic * + * * + ***********************************************************************/ + /* +@@ -437,7 +438,7 @@ int job_reap(int sig) + pw->p_flag &= ~P_NOTIFY; + if(job.jobcontrol && pid==pw->p_fgrp && pid==tcgetpgrp(JOBTTY)) + { +- px = job_byjid((int)pw->p_job); ++ px = job_byjid(pw->p_job); + for(; px && (px->p_flag&P_DONE); px=px->p_nxtproc); + if(!px) + tcsetpgrp(JOBTTY,job.mypid); +@@ -1528,7 +1529,7 @@ int job_switch(struct process *pw,int bgflag) + { + const char *msg; + job_lock(); +- if(!pw || !(pw=job_byjid((int)pw->p_job))) ++ if(!pw || !(pw=job_byjid(pw->p_job))) + { + job_unlock(); + return 1; +@@ -1542,7 +1543,7 @@ int job_switch(struct process *pw,int bgflag) + } + if(bgflag=='b') + { +- sfprintf(outfile,"[%d]\t",(int)pw->p_job); ++ sfprintf(outfile,"[%d]\t",pw->p_job); + sh.bckpid = pw->p_pid; + pw->p_flag |= P_BG; + msg = "&"; +@@ -1623,7 +1624,7 @@ static struct process *job_unpost(struct process *pwtop,int notify) + sfprintf(sfstderr,"ksh: job line %4d: drop PID=%lld critical=%d PID=%d env=%u\n",__LINE__,(Sflong_t)sh.current_pid,job.in_critical,pwtop->p_pid,pwtop->p_env); + sfsync(sfstderr); + #endif /* DEBUG */ +- pwtop = pw = job_byjid((int)pwtop->p_job); ++ pwtop = pw = job_byjid(pwtop->p_job); + if(!pw) + return NULL; + #if SHOPT_BGX +@@ -1664,7 +1665,7 @@ static struct process *job_unpost(struct process *pwtop,int notify) + sfprintf(sfstderr,"ksh: job line %4d: free PID=%lld critical=%d job=%d\n",__LINE__,(Sflong_t)sh.current_pid,job.in_critical,pwtop->p_job); + sfsync(sfstderr); + #endif /* DEBUG */ +- job_free((int)pwtop->p_job); ++ job_free(pwtop->p_job); + return NULL; + } + diff --git a/SOURCES/ksh-1.0.10-sigpipe.patch b/SOURCES/ksh-1.0.10-sigpipe.patch new file mode 100644 index 0000000..b17b0cd --- /dev/null +++ b/SOURCES/ksh-1.0.10-sigpipe.patch @@ -0,0 +1,38 @@ +From bc56018765163a8059600f5205e9e2b1f4059873 Mon Sep 17 00:00:00 2001 +From: Martijn Dekker +Date: Sat, 20 Jul 2024 01:40:35 +0100 +Subject: [PATCH] Re-fix SIGPIPE subshell regression (re: 227c6379, 4df6d674) + +It was committed prematurely and still broken on most systems. + +src/cmd/ksh93/sh/fault.c: sh_done(): +- Revert changes. + +src/cmd/ksh93/sh/jobs.c: job_wait(): +- Do not set sh.chldexitsig in the first place if the signal is + SIGPIPE and we're in a real subshell. + +This workaround passes all the tests I can throw at it. + +Resolves: https://github.com/ksh93/ksh/issues/765 +--- + src/cmd/ksh93/sh/jobs.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c +index f8c4d5f..580dae0 100644 +--- a/src/cmd/ksh93/sh/jobs.c ++++ b/src/cmd/ksh93/sh/jobs.c +@@ -1447,7 +1447,8 @@ int job_wait(pid_t pid) + if(px->p_flag&P_SIGNALLED) + { + sh.exitval |= SH_EXITSIG; +- sh.chldexitsig = 1; ++ if(!(sh.realsubshell && px->p_exit==SIGPIPE)) ++ sh.chldexitsig = 1; + } + if(intr) + px->p_flag &= ~P_EXITSAVE; +-- +2.50.0 + diff --git a/SOURCES/ksh-1.0.11-segfault-sigwinch.patch b/SOURCES/ksh-1.0.11-segfault-sigwinch.patch new file mode 100644 index 0000000..a342475 --- /dev/null +++ b/SOURCES/ksh-1.0.11-segfault-sigwinch.patch @@ -0,0 +1,264 @@ +From b533bc2feb9a1b58b9cdb3a9f5bc94f4ff060a84 Mon Sep 17 00:00:00 2001 +From: Martijn Dekker +Date: Fri, 28 Mar 2025 02:59:46 +0000 +Subject: [PATCH] Fix segfault upon SIGWINCH after 'stty -echo' (re: 83630f9d) + +After disabling terminal echo (stty -echo), ksh either crashes or +writes garbage to the terminal upon resizing the terminal window. +This also affects the use of ksh for 'M-x shell' in emacs. + +Analysis: The ed_viread and ed_emacsread functions declare buffers +as local (automatic) variables that are destroyed when the function +exits, but other functions then access then using globally declared +pointers in structs of type Edit_t, Emacs_t and Vi_t. + +However, upon 'stty -echo', the terminal cannot be set to raw mode, +so the tty_raw call fails in these two functions. At this point, +they fall back to ed_read and return, never initialising those +pointers. But the SIGWINCH handling routine in edit.c calls redraw +routines that depend on those pointers being valid -- and crash. + +src/cmd/ksh93/edit/emacs.c: ed_emacsread(): +- Attempt to set raw mode before doing or initialising anything + else: move the tty_raw call and ed_read fallback to the start. + This avoids superfluous init and makes more sense. +- Before returning, reset all global pointers that point to this + function call's local variables to NULL. (To aid with this, use a + 'done' goto label and an 'r' variable for the return code.) This + ensures these pointers will be either valid or NULL, making + debugging easier, as well as allowing the code to check for this. + +src/cmd/ksh93/edit/vi.c: ed_viread(): +- Same changes as for emacs. + +src/cmd/ksh93/edit/edit.c: ed_read(): +- If e_prompt is NULL, that is now an indication that ed_emacsread + or ed_viread are not being used because the tty_raw call failed; + therefore, skip SIGWINCH handling, except for flushing the notify + buffer (see 667034ff). This fixes the crash. + +Thanks to @nickpapadonis for the report. +Resolves: https://github.com/ksh93/ksh/issues/827 +--- + src/cmd/ksh93/edit/edit.c | 22 ++++++++++++++++++---- + src/cmd/ksh93/edit/emacs.c | 27 ++++++++++++++++----------- + src/cmd/ksh93/edit/vi.c | 38 +++++++++++++++----------------------- + 3 files changed, 49 insertions(+), 38 deletions(-) + +diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c +index 1dcef1b..846c0d8 100644 +--- a/src/cmd/ksh93/edit/edit.c ++++ b/src/cmd/ksh93/edit/edit.c +@@ -690,6 +690,16 @@ static void ed_nputchar(Edit_t *ep, int n, int c) + } + #endif /* SHOPT_ESH || SHOPT_VSH */ + ++/* ++ * Show any buffered 'set -b' job notification(s) ++ */ ++static void flush_notifybuf(void) ++{ ++ char *cp; ++ if(sh.notifybuf && (cp = sfstruse(sh.notifybuf)) && *cp) ++ sfputr(sfstderr, cp, -1); ++} ++ + /* + * Do read, restart on interrupt unless SH_SIGSET or SH_SIGTRAP is set + * Use select(2) (via sfpkrd()) to wait for input if possible +@@ -729,7 +739,12 @@ int ed_read(void *context, int fd, char *buff, int size, int reedit) + if(sh.winch && sh_editor_active() && sh_isstate(SH_INTERACTIVE)) + { + int n, newsize; +- char *cp; ++ if(!ep->e_prompt) ++ { ++ /* ed_emacsread or ed_viread was unable to put the tty in raw mode */ ++ flush_notifybuf(); ++ goto skipwinch; ++ } + sh_winsize(NULL,&newsize); + ed_putchar(ep,'\r'); + /* +@@ -751,9 +766,7 @@ int ed_read(void *context, int fd, char *buff, int size, int reedit) + ed_putchar(ep,'\r'); + } + ed_flush(ep); +- /* show any buffered 'set -b' job notification(s) */ +- if(sh.notifybuf && (cp = sfstruse(sh.notifybuf)) && *cp) +- sfputr(sfstderr, cp, -1); ++ flush_notifybuf(); + /* update window size */ + ep->e_winsz = newsize-1; + if(ep->e_winsz < MINWINDOW) +@@ -777,6 +790,7 @@ int ed_read(void *context, int fd, char *buff, int size, int reedit) + emacs_redraw(ep->e_emacs); + #endif /* SHOPT_ESH && SHOPT_VSH */ + } ++ skipwinch: + #endif /* SHOPT_ESH || SHOPT_VSH */ + sh.winch = 0; + /* an interrupt that should be ignored */ +diff --git a/src/cmd/ksh93/edit/emacs.c b/src/cmd/ksh93/edit/emacs.c +index 1dd6023..128e592 100644 +--- a/src/cmd/ksh93/edit/emacs.c ++++ b/src/cmd/ksh93/edit/emacs.c +@@ -185,6 +185,7 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + Edit_t *ed = (Edit_t*)context; + int c; + int i; ++ int r = -1; /* return code */ + genchar *out; + int count; + Emacs_t *ep = ed->e_emacs; +@@ -194,6 +195,10 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + genchar *kptr; + char prompt[PRSIZE]; + genchar Screen[MAXLINE]; ++ /* Set raw mode */ ++ if(tty_raw(ERRIO,0) < 0) ++ return reedit ? reedit : ed_read(context, fd, buff, scend, 0); ++ /* Initialize some things */ + memset(Screen,0,sizeof(Screen)); + if(!ep) + { +@@ -206,10 +211,6 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + ep->screen = Screen; + ep->lastdraw = FINAL; + ep->ehist = 0; +- if(tty_raw(ERRIO,0) < 0) +- { +- return reedit ? reedit : ed_read(context,fd,buff,scend,0); +- } + raw = 1; + /* This mess in case the read system call fails */ + ed_setup(ep->ed,fd,reedit); +@@ -240,6 +241,7 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + } + ep->in_mult = hloff; /* save pos in last command */ + #endif /* ESH_NFIRST */ ++ /* Handle user interrupt, user quit, or EOF */ + i = sigsetjmp(env,0); + if (i !=0) + { +@@ -251,10 +253,8 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + } + tty_cooked(ERRIO); + if (i == UEOF) +- { +- return 0; /* EOF */ +- } +- return -1; /* some other error */ ++ r = 0; /* EOF */ ++ goto done; + } + out[reedit] = 0; + if(scend+plen > (MAXLINE-2)) +@@ -349,7 +349,8 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + case EOFCHAR: + ed_flush(ep->ed); + tty_cooked(ERRIO); +- return 0; ++ r = 0; ++ goto done; + #ifdef u370 + case cntl('S') : + case cntl('Q') : +@@ -754,8 +755,12 @@ process: + #endif /* SHOPT_MULTIBYTE */ + i = (int)strlen(buff); + if (i) +- return i; +- return -1; ++ r = i; ++done: ++ /* avoid leaving invalid pointers to destroyed automatic variables */ ++ Prompt = NULL; ++ drawbuff = ep->screen = ep->cursor = NULL; ++ return r; + } + + static void show_info(Emacs_t *ep,const char *str) +diff --git a/src/cmd/ksh93/edit/vi.c b/src/cmd/ksh93/edit/vi.c +index 0e878df..fac40ee 100644 +--- a/src/cmd/ksh93/edit/vi.c ++++ b/src/cmd/ksh93/edit/vi.c +@@ -208,6 +208,7 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit) + { + Edit_t *ed = (Edit_t*)context; + int i; /* general variable */ ++ int r = -1; /* return value */ + int term_char=0; /* read() termination character */ + Vi_t *vp = ed->e_vi; + char prompt[PRSIZE+2]; /* prompt */ +@@ -218,6 +219,10 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit) + int Globals[9]; /* local global variables */ + int esc_or_hang=0; /* or hangup */ + char cntl_char=0; /* TRUE if control character present */ ++ ++ if( tty_raw(ERRIO,0) < 0 ) ++ return reedit ? reedit : ed_read(context, fd, shbuf, nchar, 0); ++ + if(!vp) + { + ed->e_vi = vp = sh_newof(0,Vi_t,1,0); +@@ -232,16 +237,9 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit) + ed_setup(vp->ed,fd, reedit); + shbuf[reedit] = 0; + +- { +- /*** Set raw mode ***/ +- +- if(tty_raw(ERRIO,0) < 0 ) +- return reedit ? reedit : ed_read(context, fd, shbuf, nchar,0); +- i = last_virt-1; +- } +- + /*** Initialize some things ***/ + ++ i = last_virt-1; + virtual = (genchar*)shbuf; + #if SHOPT_MULTIBYTE + virtual = (genchar*)roundof((char*)virtual-(char*)0,sizeof(genchar)); +@@ -307,18 +305,9 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit) + } + virtual[0] = '\0'; + tty_cooked(ERRIO); +- +- switch(i) +- { +- case UEOF: +- /*** EOF ***/ +- return 0; +- +- case UINTR: +- /** interrupt **/ +- return -1; +- } +- return -1; ++ if (i == UEOF) ++ r = 0; /* EOF */ ++ goto done; + } + + /*** Get a line from the terminal ***/ +@@ -363,10 +352,13 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit) + if(vp->ed->nhlist) + ed_histlist(vp->ed,0); + #endif /* SHOPT_EDPREDICT */ +- return last_virt; ++ r = last_virt; + } +- else +- return -1; ++done: ++ /* avoid leaving invalid pointers to destroyed automatic variables */ ++ Prompt = NULL; ++ virtual = physical = window = vp->U_space = vp->u_space = NULL; ++ return r; + } + + +-- +2.49.0 + diff --git a/SOURCES/RHEL-112564.patch b/SOURCES/ksh-1.0.11-stty-noecho.patch similarity index 90% rename from SOURCES/RHEL-112564.patch rename to SOURCES/ksh-1.0.11-stty-noecho.patch index a14b7e7..2fe543e 100644 --- a/SOURCES/RHEL-112564.patch +++ b/SOURCES/ksh-1.0.11-stty-noecho.patch @@ -1,4 +1,4 @@ -From e8554b5131fc32b26a6a0b0ab5cf24839e30161a Mon Sep 17 00:00:00 2001 +From 4350174a5d4acabf78f97b28c6d0ae68ec703e78 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Sun, 30 Mar 2025 00:14:35 +0000 Subject: [PATCH] Fix 'stty -echo' in scripts (re: 41ebb55a) @@ -56,14 +56,14 @@ src/cmd/ksh93/sh/jobs.c: job_wait(): Resolves: https://github.com/ksh93/ksh/issues/836 --- - src/cmd/ksh93/sh/jobs.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) + src/cmd/ksh93/sh/jobs.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c -index be333b2..081e73a 100644 +index c65bc6e66094..513afb5582ab 100644 --- a/src/cmd/ksh93/sh/jobs.c +++ b/src/cmd/ksh93/sh/jobs.c -@@ -1492,9 +1492,9 @@ int job_wait(pid_t pid) +@@ -1420,9 +1420,9 @@ int job_wait(pid_t pid) kill(sh.current_pid,SIGTSTP); } } @@ -75,6 +75,3 @@ index be333b2..081e73a 100644 { if(pw->p_pgrp==0) pw->p_pgrp = pw->p_pid; --- -2.47.3 - diff --git a/SOURCES/ksh-1.0.12-security.patch b/SOURCES/ksh-1.0.12-security.patch new file mode 100644 index 0000000..d164312 --- /dev/null +++ b/SOURCES/ksh-1.0.12-security.patch @@ -0,0 +1,807 @@ +From 970812e39c236ff385e440ac6d458d196c237667 Mon Sep 17 00:00:00 2001 +From: Johnothan King +Date: Fri, 13 Jun 2025 16:29:15 -0700 +Subject: [PATCH] Fix arbitrary command execution/code injection bugs (#866) + +* Security patch part 1 + +Never use $SHELL or sh.shpath when executing shebang-less scripts + +- sh_ntfork(): Removed a misguided optimization that causes ksh to + run scripts without a shebang using the binary pointed to by + either $SHELL or sh.shpath. This has a few problems: + - The shell in sh.shpath or more disastrously in $SHELL has + no guarantee of being identical to the currently running + copy of ksh93 or even existing at all, so using either is + not only bogus, but potentially dangerous. + - The optimization has no ability to pass down the current + POSIX mode status to the script. + - It's only activated for virtual subshells, resulting in + arbitrarily different behavior depending on whether or + not we're in a virtual subshell. + - It does some weird stuff with /dev/fd that seems superfluous, + and also lacks any SHOPT_DEVFD if directive. (Additionally, + if it did have one, that stat(2) would likely become mere + dead code and a waste of context switches.) + +The optimization was probably intended to be used for running a +shebang-less script via posix_spawn, which is ostensibly faster +than fork. But this simply isn't possible without risking running +the shebang-less script in a shell environment different from +the current one. (If ksh were updated by the package manager +while ksh is still running, this optimization would cause the +script to run via the new version, rather than the currently +running older version.) The optimization is unfixable by design, +and as such must be removed to ensure correct behavior. + +* Security patch part 2 (re: bae02c39) + +rm setuid script code leading to arbitrary command execution + +Changes: +- Delete code for setuid scripts on "Solaris 2.5+" because it + allows for arbitrary command execution. One millisecond you think + you're launching ksh, the next you're at the mercy of a hijacker. + Example: + SHELL=/bin/ppmflash /bin/ksh -l /dev/fd/0 < <(true) + MANPATH: usage: MANPATH flashfactor [ppmfile] + flashfactor: 0.0 = original picture, 1.0 = total whiteout + The pathshell() code doesn't *seem* to be vulnerable to privilege + escalation, but who knows (cf. CVE-2019-14868; this might need its + own CVE 2025. Maybe pathshell() should be scrapped entirely???) +- Add fickle but functional regression test (you may need to pass + KSH=/bin/ksh or some such to get it to fail against vulnerable + versions of ksh). The test uses a login shell via the -l option, + but the bug *does not* need a login shell. See: + https://github.com/ksh93/ksh/issues/874#issue-3128739066 + Modify the execveat reproducer to pass along environ (which + could include a hijacked SHELL), and you're in for a BAD time. + +Maybe the deleted code (introduced sometime within the period of 1995 +and 1999) was relevant to some Solaris-specific use case or something. +Maybe the erasure even causes an incompatibility. But that code must +go; it's far too dangerous to execv whatever the hell pathshell gives +us during **init**. (Need I bring CVE-2019-14868 back to remembrance +again? This bug has similarities to that one.) + +FWIW, all of the regression tests in the ksh and modernish suites pass +with this patch applied. + +* Security patch part 3 + +Delete pathshell() and replace uses of it with safer equivalents + +This function is a dangerous attack vector that ought not remain +in the code base. The value returned by astconf() is doubtless +safer than what is returned by pathshell(). + +* Other changes + +The libast pathprog function and prog feature test are now unused, +and are removed. +--- + src/cmd/ksh93/include/shell.h | 3 - + src/cmd/ksh93/sh/init.c | 33 +-------- + src/cmd/ksh93/sh/main.c | 21 ------ + src/cmd/ksh93/sh/path.c | 2 - + src/cmd/ksh93/sh/xec.c | 20 ------ + src/cmd/ksh93/tests/basic.sh | 28 ++++++++ + src/lib/libast/Mamfile | 29 +------- + src/lib/libast/comp/omitted.c | 2 +- + src/lib/libast/comp/system.c | 48 ------------- + src/lib/libast/features/prog | 12 ---- + src/lib/libast/include/ast.h | 2 - + src/lib/libast/man/compat.3 | 1 - + src/lib/libast/man/path.3 | 13 ---- + src/lib/libast/man/proc.3 | 5 +- + src/lib/libast/misc/cmdarg.c | 2 +- + src/lib/libast/misc/procopen.c | 2 +- + src/lib/libast/path/pathprog.c | 124 -------------------------------- + src/lib/libast/path/pathshell.c | 115 ----------------------------- + 18 files changed, 37 insertions(+), 425 deletions(-) + delete mode 100644 src/lib/libast/comp/system.c + delete mode 100644 src/lib/libast/features/prog + delete mode 100644 src/lib/libast/path/pathprog.c + delete mode 100644 src/lib/libast/path/pathshell.c + +diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h +index 0613ceb..9a1b00e 100644 +--- a/src/cmd/ksh93/include/shell.h ++++ b/src/cmd/ksh93/include/shell.h +@@ -213,8 +213,6 @@ struct sh_scoped + char **otrapcom; /* save parent EXIT and signals for v=$(trap) */ + void *timetrap; + struct Ufunction *real_fun; /* current 'function name' function */ +- int repl_index; +- char *repl_arg; + }; + + struct limits +@@ -255,7 +253,6 @@ struct Shell_s + Namval_t *bltin_nodes; + Namval_t *bltin_cmds; + History_t *hist_ptr; +- char *shpath; + char *user; + char **sigmsg; + char **login_files; +diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c +index f4daaac..58c4e09 100644 +--- a/src/cmd/ksh93/sh/init.c ++++ b/src/cmd/ksh93/sh/init.c +@@ -1355,33 +1355,6 @@ Shell_t *sh_init(int argc,char *argv[], Shinit_f userinit) + } + sh.shlvl++; + nv_offattr(SHLVL,NV_IMPORT); +-#if SHOPT_SPAWN +- { +- /* +- * try to find the pathname for this interpreter +- * try using environment variable _ or argv[0] +- */ +- char *cp=nv_getval(L_ARGNOD); +- char buff[PATH_MAX+1]; +- sh.shpath = 0; +- if((n = pathprog(NULL, buff, sizeof(buff))) > 0 && n <= sizeof(buff)) +- sh.shpath = sh_strdup(buff); +- else if((cp && (sh_type(cp)&SH_TYPE_SH)) || (argc>0 && strchr(cp= *argv,'/'))) +- { +- if(*cp=='/') +- sh.shpath = sh_strdup(cp); +- else if(cp = nv_getval(PWDNOD)) +- { +- int offset = stktell(sh.stk); +- sfputr(sh.stk,cp,'/'); +- sfputr(sh.stk,argv[0],-1); +- pathcanon(stkptr(sh.stk,offset),PATH_DOTDOT); +- sh.shpath = sh_strdup(stkptr(sh.stk,offset)); +- stkseek(sh.stk,offset); +- } +- } +- } +-#endif + nv_putval(IFSNOD,(char*)e_sptbnl,NV_RDONLY); + astconfdisc(newconf); + #if SHOPT_TIMEOUT +@@ -1394,7 +1367,6 @@ Shell_t *sh_init(int argc,char *argv[], Shinit_f userinit) + #endif + if(argc>0) + { +- int dolv_index; + /* check for restricted shell */ + if(type&SH_TYPE_RESTRICTED) + sh_onoption(SH_RESTRICTED); +@@ -1406,10 +1378,7 @@ Shell_t *sh_init(int argc,char *argv[], Shinit_f userinit) + sh_done(0); + } + opt_info.disc = 0; +- dolv_index = (argc - 1) - sh.st.dolc; +- sh.st.dolv = argv + dolv_index; +- sh.st.repl_index = dolv_index; +- sh.st.repl_arg = argv[dolv_index]; ++ sh.st.dolv = argv + (argc - 1) - sh.st.dolc; + sh.st.dolv[0] = argv[0]; + if(sh.st.dolc < 1) + { +diff --git a/src/cmd/ksh93/sh/main.c b/src/cmd/ksh93/sh/main.c +index 38ae366..712310e 100644 +--- a/src/cmd/ksh93/sh/main.c ++++ b/src/cmd/ksh93/sh/main.c +@@ -247,33 +247,12 @@ int sh_main(int ac, char *av[], Shinit_f userinit) + /* open stream should have been passed into shell */ + if(strmatch(name,e_devfdNN)) + { +-#if !_WINIX +- char *cp; +- int type; +-#endif + fdin = (int)strtol(name+8, NULL, 10); + if(fstat(fdin,&statb)<0) + { + errormsg(SH_DICT,ERROR_system(1),e_open,name); + UNREACHABLE(); + } +-#if !_WINIX +- /* +- * try to undo effect of Solaris 2.5+ +- * change for argv for setuid scripts +- */ +- if(sh.st.repl_index > 0) +- av[sh.st.repl_index] = sh.st.repl_arg; +- if(((type = sh_type(cp = av[0])) & SH_TYPE_SH) && (name = nv_getval(L_ARGNOD)) && (!((type = sh_type(cp = name)) & SH_TYPE_SH))) +- { +- av[0] = (type & SH_TYPE_LOGIN) ? cp : path_basename(cp); +- /* exec to change $0 for ps */ +- execv(pathshell(),av); +- /* exec fails */ +- sh.st.dolv[0] = av[0]; +- fixargs(sh.st.dolv,1); +- } +-#endif + name = av[0]; + sh_offoption(SH_VERBOSE); + sh_offoption(SH_XTRACE); +diff --git a/src/cmd/ksh93/sh/path.c b/src/cmd/ksh93/sh/path.c +index 85f44b5..7728df0 100644 +--- a/src/cmd/ksh93/sh/path.c ++++ b/src/cmd/ksh93/sh/path.c +@@ -1195,8 +1195,6 @@ pid_t path_spawn(const char *opath,char **argv, char **envp, Pathcomp_t *libpath + errno = ENOEXEC; + if(spawn) + { +- if(sh.subshell) +- return -1; + do + { + if((pid=fork())>0) +diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c +index ca67142..003a93c 100644 +--- a/src/cmd/ksh93/sh/xec.c ++++ b/src/cmd/ksh93/sh/xec.c +@@ -3417,26 +3417,6 @@ static pid_t sh_ntfork(const Shnode_t *t,char *argv[],int *jobid,int topfd) + job_fork(-1); + jobfork = 1; + spawnpid = path_spawn(path,argv,arge,pp,(grp<<1)|1); +- if(spawnpid < 0 && errno==ENOEXEC) +- { +- char *devfd; +- int fd = open(path,O_RDONLY); +- argv[-1] = argv[0]; +- argv[0] = path; +- if(fd>=0) +- { +- struct stat statb; +- sfprintf(sh.strbuf,"/dev/fd/%d",fd); +- if(stat(devfd=sfstruse(sh.strbuf),&statb)>=0) +- argv[0] = devfd; +- } +- if(!sh.shpath) +- sh.shpath = pathshell(); +- spawnpid = path_spawn(sh.shpath,&argv[-1],arge,pp,(grp<<1)|1); +- if(fd>=0) +- close(fd); +- argv[0] = argv[-1]; +- } + fail: + if(jobfork && spawnpid<0) + job_fork(-2); +diff --git a/src/cmd/ksh93/tests/basic.sh b/src/cmd/ksh93/tests/basic.sh +index ea83b6b..0b02f7c 100755 +--- a/src/cmd/ksh93/tests/basic.sh ++++ b/src/cmd/ksh93/tests/basic.sh +@@ -1019,5 +1019,33 @@ do + done + unset testcode + ++# ====== ++# Hijacking ksh93 via $SHELL for arbitrary command execution during initialization. ++# https://github.com/ksh93/ksh/issues/874 ++bindir=$tmp/dir.$RANDOM/bin ++mkdir -p "$bindir" ++echo $'#!/bin/sh\necho "CODE INJECTION"' > "$bindir"/hijack_sh ++chmod +x "$bindir"/hijack_sh ++got=$(set +x; SHELL="$bindir"/hijack_sh "$SHELL" -l <(echo) 2>&1) ++[[ $got =~ "CODE INJECTION" ]] && err_exit 'ksh93 is vulnerable to being hijacked during init via $SHELL' \ ++ "(got $(printf %q "$got"))" ++ ++# Hijacking ksh93 shebang-less scripts for arbitrary command execution. ++# https://github.com/ksh93/ksh/pull/866 ++export bindir ++print 'echo GOOD' > "$bindir/dummy.sh" ++chmod +x "$bindir/dummy.sh" ++cp "$SHELL" "$bindir/hijack_sh" ++exp=$'GOOD\nGOOD' ++got=$("$bindir/hijack_sh" -c $'print $\'\#!/bin/sh\necho HIJACKED\' > "$bindir/hijack_shell" ++chmod +x "$bindir/hijack_shell" ++rm "$bindir/hijack_sh" ++cp "$bindir/hijack_shell" "$bindir/hijack_sh" ++("$bindir/dummy.sh"); "$bindir/dummy.sh"; :') ++rm -r "$bindir" ++unset bindir ++[[ $exp == $got ]] || err_exit 'ksh93 shebang-less scripts are vulnerable to being hijacked for arbitrary code execution' \ ++ "(exp $(printf %q "$exp"), got $(printf %q "$got"))" ++ + # ====== + exit $((Errors<125?Errors:125)) +diff --git a/src/lib/libast/Mamfile b/src/lib/libast/Mamfile +index 0a35576..047ab0c 100644 +--- a/src/lib/libast/Mamfile ++++ b/src/lib/libast/Mamfile +@@ -972,12 +972,6 @@ make install + done path/pathbin.c + exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c path/pathbin.c + done pathbin.o generated +- make pathshell.o +- make path/pathshell.c +- prev include/ast.h +- done path/pathshell.c +- exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c path/pathshell.c +- done pathshell.o generated + make pathcd.o + make path/pathcd.c + make include/stk.h implicit +@@ -988,17 +982,6 @@ make install + done path/pathcd.c + exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c path/pathcd.c + done pathcd.o generated +- make pathprog.o +- make path/pathprog.c +- make FEATURE/prog implicit +- prev features/prog +- exec - iffe ${IFFEFLAGS} -v -X ast -X std -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" run features/prog +- done FEATURE/prog generated +- prev include/ast_windows.h +- prev include/ast.h +- done path/pathprog.c +- exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c path/pathprog.c +- done pathprog.o generated + make ftwalk.o + make misc/ftwalk.c + make include/ftwalk.h implicit +@@ -2574,14 +2557,6 @@ make install + done comp/mount.c + exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c comp/mount.c + done mount.o generated +- make system.o +- make comp/system.c +- prev ast_map.h +- prev include/proc.h +- prev include/ast.h +- done comp/system.c +- exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c comp/system.c +- done system.o generated + make iblocks.o + make port/iblocks.c + prev include/ls.h +@@ -4425,9 +4400,9 @@ make install + exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Icomp -Iinclude -Istd -c vmalloc/vmgetmem.c + done vmgetmem.o generated + exec - ${AR} rc libast.a state.o opendir.o readdir.o rewinddir.o seekdir.o telldir.o getcwd.o fastfind.o hashalloc.o hashdump.o hashfree.o hashlast.o hashlook.o hashscan.o hashsize.o hashview.o hashwalk.o memhash.o memsum.o strhash.o strkey.o strsum.o stracmp.o strnacmp.o ccmap.o ccmapid.o ccnative.o chresc.o chrtoi.o +- exec - ${AR} rc libast.a streval.o strexpr.o strmatch.o strcopy.o modei.o modex.o strmode.o strlcat.o strlcpy.o strlook.o strncopy.o strsearch.o strpsearch.o stresc.o stropt.o strtape.o strpcmp.o strnpcmp.o strvcmp.o strnvcmp.o tok.o tokline.o tokscan.o pathaccess.o pathcat.o pathcanon.o pathcheck.o pathpath.o pathexists.o pathfind.o pathicase.o pathkey.o pathprobe.o pathrepl.o pathnative.o pathposix.o pathtemp.o pathtmp.o pathstat.o pathgetlink.o pathsetlink.o pathbin.o pathshell.o pathcd.o pathprog.o ftwalk.o ftwflags.o fts.o astintercept.o conformance.o getenv.o setenviron.o optget.o optjoin.o optesc.o optctx.o strsort.o struniq.o magic.o mime.o mimetype.o signal.o sigflag.o systrace.o error.o errorf.o errormsg.o errorx.o localeconv.o setlocale.o translate.o catopen.o iconv.o lc.o lctab.o mc.o base64.o recfmt.o recstr.o reclen.o fmtrec.o fmtbase.o fmtbuf.o fmtclock.o fmtdev.o fmtelapsed.o fmterror.o fmtesc.o fmtfmt.o fmtfs.o fmtident.o fmtint.o fmtip4.o fmtip6.o fmtls.o fmtmatch.o fmtmode.o fmtnum.o fmtperm.o fmtre.o fmttime.o ++ exec - ${AR} rc libast.a streval.o strexpr.o strmatch.o strcopy.o modei.o modex.o strmode.o strlcat.o strlcpy.o strlook.o strncopy.o strsearch.o strpsearch.o stresc.o stropt.o strtape.o strpcmp.o strnpcmp.o strvcmp.o strnvcmp.o tok.o tokline.o tokscan.o pathaccess.o pathcat.o pathcanon.o pathcheck.o pathpath.o pathexists.o pathfind.o pathicase.o pathkey.o pathprobe.o pathrepl.o pathnative.o pathposix.o pathtemp.o pathtmp.o pathstat.o pathgetlink.o pathsetlink.o pathbin.o pathcd.o ftwalk.o ftwflags.o fts.o astintercept.o conformance.o getenv.o setenviron.o optget.o optjoin.o optesc.o optctx.o strsort.o struniq.o magic.o mime.o mimetype.o signal.o sigflag.o systrace.o error.o errorf.o errormsg.o errorx.o localeconv.o setlocale.o translate.o catopen.o iconv.o lc.o lctab.o mc.o base64.o recfmt.o recstr.o reclen.o fmtrec.o fmtbase.o fmtbuf.o fmtclock.o fmtdev.o fmtelapsed.o fmterror.o fmtesc.o fmtfmt.o fmtfs.o fmtident.o fmtint.o fmtip4.o fmtip6.o fmtls.o fmtmatch.o fmtmode.o fmtnum.o fmtperm.o fmtre.o fmttime.o + exec - ${AR} rc libast.a fmtuid.o fmtgid.o fmtsignal.o fmtscale.o fmttmx.o fmttv.o fmtversion.o strelapsed.o strperm.o struid.o strgid.o strtoip4.o strtoip6.o stack.o stk.o swapget.o swapmem.o swapop.o swapput.o sigdata.o sigcrit.o sigunblock.o procopen.o procclose.o procrun.o procfree.o tmdate.o tmequiv.o tmfix.o tmfmt.o tmform.o tmgoff.o tminit.o tmleap.o tmlex.o tmlocale.o tmmake.o tmpoff.o tmscan.o tmsleep.o tmtime.o tmtype.o tmweek.o tmword.o tmzone.o tmxdate.o tmxduration.o tmxfmt.o tmxgettime.o tmxleap.o tmxmake.o tmxscan.o tmxsettime.o tmxsleep.o tmxtime.o tmxtouch.o tvcmp.o tvgettime.o tvsettime.o tvsleep.o tvtouch.o cmdarg.o vecargs.o vecfile.o vecfree.o vecload.o vecstring.o univdata.o touch.o mnt.o debug.o memccpy.o memchr.o memcmp.o memcpy.o memdup.o memmove.o memset.o mkdir.o mkfifo.o mknod.o rmdir.o remove.o rename.o link.o unlink.o strdup.o strchr.o strrchr.o strstr.o strtod.o strtold.o strtol.o strtoll.o strtoul.o strtoull.o strton.o strtonll.o strntod.o strntold.o strnton.o +- exec - ${AR} rc libast.a strntonll.o strntol.o strntoll.o strntoul.o strntoull.o strcasecmp.o strncasecmp.o strerror.o mktemp.o tmpnam.o fsync.o execlp.o execve.o execvp.o execvpe.o spawnveg.o killpg.o getlogin.o putenv.o setenv.o unsetenv.o lstat.o statvfs.o eaccess.o gross.o omitted.o readlink.o symlink.o getpgrp.o setpgid.o setsid.o fcntl.o open.o atexit.o getdents.o getwd.o dup2.o errno.o getgroups.o mount.o system.o iblocks.o modedata.o tmdata.o memfatal.o sfkeyprintf.o sfdcdio.o sfdcdos.o sfdcfilter.o sfdcseekable.o sfdcslow.o sfdcsubstr.o sfdctee.o sfdcunion.o sfdcmore.o sfdcprefix.o wc.o wc2utf8.o basename.o closelog.o dirname.o fmtmsglib.o fnmatch.o ftw.o getdate.o getsubopt.o glob.o nftw.o openlog.o re_comp.o resolvepath.o realpath.o regcmp.o regexp.o setlogmask.o strftime.o strptime.o swab.o syslog.o tempnam.o wordexp.o mktime.o regalloc.o regclass.o regcoll.o regcomp.o regcache.o regdecomp.o regerror.o regexec.o regfatal.o reginit.o ++ exec - ${AR} rc libast.a strntonll.o strntol.o strntoll.o strntoul.o strntoull.o strcasecmp.o strncasecmp.o strerror.o mktemp.o tmpnam.o fsync.o execlp.o execve.o execvp.o execvpe.o spawnveg.o killpg.o getlogin.o putenv.o setenv.o unsetenv.o lstat.o statvfs.o eaccess.o gross.o omitted.o readlink.o symlink.o getpgrp.o setpgid.o setsid.o fcntl.o open.o atexit.o getdents.o getwd.o dup2.o errno.o getgroups.o mount.o iblocks.o modedata.o tmdata.o memfatal.o sfkeyprintf.o sfdcdio.o sfdcdos.o sfdcfilter.o sfdcseekable.o sfdcslow.o sfdcsubstr.o sfdctee.o sfdcunion.o sfdcmore.o sfdcprefix.o wc.o wc2utf8.o basename.o closelog.o dirname.o fmtmsglib.o fnmatch.o ftw.o getdate.o getsubopt.o glob.o nftw.o openlog.o re_comp.o resolvepath.o realpath.o regcmp.o regexp.o setlogmask.o strftime.o strptime.o swab.o syslog.o tempnam.o wordexp.o mktime.o regalloc.o regclass.o regcoll.o regcomp.o regcache.o regdecomp.o regerror.o regexec.o regfatal.o reginit.o + exec - ${AR} rc libast.a regnexec.o regsubcomp.o regsubexec.o regsub.o regrecord.o regrexec.o regstat.o dtclose.o dtdisc.o dthash.o dtlist.o dtmethod.o dtopen.o dtstat.o dtstrhash.o dttree.o dtuser.o dtview.o dtwalk.o dtnew.o dtcomp.o sfclose.o sfclrlock.o sfdisc.o sfdlen.o sfexcept.o sfgetl.o sfgetu.o sfcvt.o sfecvt.o sffcvt.o sfextern.o sffilbuf.o sfflsbuf.o sfprints.o sfgetd.o sfgetr.o sfllen.o sfmode.o sfmove.o sfnew.o sfpkrd.o sfnotify.o sfnputc.o sfopen.o sfpeek.o sfpoll.o sfpool.o sfpopen.o sfprintf.o sfputd.o sfputl.o sfputr.o sfputu.o sfrd.o sfread.o sfreserve.o sfscanf.o sfseek.o sfset.o sfsetbuf.o sfsetfd.o sfsize.o sfsk.o sfstack.o sfstrtod.o sfsync.o sfswap.o sftable.o sftell.o sftmp.o sfungetc.o sfvprintf.o sfvscanf.o sfwr.o sfwrite.o sfpurge.o sfraise.o sfwalk.o sfgetm.o sfputm.o sfresize.o _sfclrerr.o _sfeof.o _sferror.o _sffileno.o _sfopen.o _sfstacked.o _sfvalue.o _sfgetc.o _sfgetl.o _sfgetl2.o _sfgetu.o _sfgetu2.o _sfdlen.o _sfllen.o _sfslen.o _sfulen.o _sfputc.o _sfputd.o _sfputl.o _sfputm.o + exec - ${AR} rc libast.a _sfputu.o clearerr.o fclose.o fdopen.o fflush.o fgetc.o fgetpos.o fgets.o fopen.o fprintf.o fpurge.o fputs.o fread.o freopen.o fscanf.o fseek.o fseeko.o fsetpos.o ftell.o ftello.o fwrite.o getw.o pclose.o popen.o printf.o putchar.o puts.o putw.o rewind.o scanf.o setbuf.o setbuffer.o setlinebuf.o setvbuf.o snprintf.o sprintf.o sscanf.o asprintf.o vasprintf.o tmpfile.o ungetc.o vfprintf.o vfscanf.o vprintf.o vscanf.o vsnprintf.o vsprintf.o vsscanf.o _doprnt.o _doscan.o _filbuf.o _flsbuf.o _stdopen.o _stdprintf.o _stdscanf.o _stdsprnt.o _stdvbuf.o _stdvsnprnt.o _stdvsprnt.o _stdvsscn.o fgetwc.o fwprintf.o putwchar.o vfwscanf.o wprintf.o fgetws.o fwscanf.o swprintf.o vswprintf.o wscanf.o fputwc.o getwc.o swscanf.o vswscanf.o fputws.o getwchar.o ungetwc.o vwprintf.o fwide.o putwc.o vfwprintf.o vwscanf.o stdio_c99.o fcloseall.o fmemopen.o getdelim.o getline.o frexp.o frexpl.o astcopy.o + exec - ${AR} rc libast.a astconf.o astdynamic.o astquery.o astwinsize.o conftab.o aststatic.o getopt.o getoptl.o aso.o asolock.o asometh.o asorelax.o aso-sem.o aso-fcntl.o vmbest.o vmclear.o vmclose.o vmdcheap.o vmdebug.o vmdisc.o vmlast.o vmopen.o vmpool.o vmprivate.o vmprofile.o vmregion.o vmsegment.o vmset.o vmstat.o vmstrdup.o vmtrace.o vmwalk.o vmmopen.o malloc.o vmgetmem.o +diff --git a/src/lib/libast/comp/omitted.c b/src/lib/libast/comp/omitted.c +index 447990d..3631d39 100644 +--- a/src/lib/libast/comp/omitted.c ++++ b/src/lib/libast/comp/omitted.c +@@ -504,7 +504,7 @@ runve(int mode, const char* path, char* const* argv, char* const* envv) + p = v; + *p++ = (char*)path; + *p++ = (char*)path; +- path = (const char*)pathshell(); ++ path = "/bin/sh.exe"; + if (*argv) + argv++; + while (*p++ = (char*)*argv++); +diff --git a/src/lib/libast/comp/system.c b/src/lib/libast/comp/system.c +deleted file mode 100644 +index 64fa7e7..0000000 +--- a/src/lib/libast/comp/system.c ++++ /dev/null +@@ -1,48 +0,0 @@ +-/*********************************************************************** +-* * +-* This software is part of the ast package * +-* Copyright (c) 1985-2011 AT&T Intellectual Property * +-* Copyright (c) 2020-2023 Contributors to ksh 93u+m * +-* and is licensed under the * +-* Eclipse Public License, Version 2.0 * +-* * +-* A copy of the License is available at * +-* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html * +-* (with md5 checksum 84283fa8859daf213bdda5a9f8d1be1d) * +-* * +-* Glenn Fowler * +-* David Korn * +-* Phong Vo * +-* Martijn Dekker * +-* Johnothan King * +-* * +-***********************************************************************/ +-/* +- * AST library system(3) +- */ +- +-#define system ______system +- +-#define _STDLIB_H_ 1 /* UWIN workaround */ +- +-#include +-#include +- +-#undef system +- +-#undef _def_map_ast +-#include +- +-extern int +-system(const char* cmd) +-{ +- char* sh[4]; +- +- if (!cmd) +- return !eaccess(pathshell(), X_OK); +- sh[0] = "sh"; +- sh[1] = "-c"; +- sh[2] = (char*)cmd; +- sh[3] = 0; +- return procrun(NULL, sh, 0); +-} +diff --git a/src/lib/libast/features/prog b/src/lib/libast/features/prog +deleted file mode 100644 +index 365ce88..0000000 +--- a/src/lib/libast/features/prog ++++ /dev/null +@@ -1,12 +0,0 @@ +-lib getexecname,_NSGetExecutablePath +- +-tst run{ +- for p in /proc/self/exe /proc/self/path/a.out +- do if test -e $p +- then echo "#define _PROC_PROG \"$p\"" +- break +- fi +- done +-}end +- +-_hdr_macho_o_dyld = hdr mach-o/dyld +diff --git a/src/lib/libast/include/ast.h b/src/lib/libast/include/ast.h +index 5ec170b..6271677 100644 +--- a/src/lib/libast/include/ast.h ++++ b/src/lib/libast/include/ast.h +@@ -373,11 +373,9 @@ extern char* pathpath_20100601(const char*, const char*, int, char*, size_t); + extern size_t pathposix(const char*, char*, size_t); + extern char* pathprobe(char*, char*, const char*, const char*, const char*, int); + extern char* pathprobe_20100601(const char*, const char*, const char*, int, char*, size_t, char*, size_t); +-extern size_t pathprog(const char*, char*, size_t); + extern char* pathrepl(char*, const char*, const char*); + extern char* pathrepl_20100601(char*, size_t, const char*, const char*); + extern int pathsetlink(const char*, const char*); +-extern char* pathshell(void); + extern char* pathtemp(char*, size_t, const char*, const char*, int*); + extern char* pathtmp(char*, const char*, const char*, int*); + extern char* setenviron(const char*); +diff --git a/src/lib/libast/man/compat.3 b/src/lib/libast/man/compat.3 +index 7baf287..47c344f 100644 +--- a/src/lib/libast/man/compat.3 ++++ b/src/lib/libast/man/compat.3 +@@ -77,7 +77,6 @@ double strtod(const char*, char**); + long strtol(const char*, char**, int); + int symlink(const char*, const char*); + long sysconf(int); +-int system(const char*); + char* tmpnam(char*); + int unlink(const char*); + int waitpid(pid_t, int*, int); +diff --git a/src/lib/libast/man/path.3 b/src/lib/libast/man/path.3 +index 8060763..b9fdacf 100644 +--- a/src/lib/libast/man/path.3 ++++ b/src/lib/libast/man/path.3 +@@ -57,7 +57,6 @@ char* pathpath(char* \fIpath\fP, const char* \fIp\fP, const char* \fIa\fP, i + char* pathprobe(char* \fIpath\fP, char* \fIattr\fP, const char* \fIlang\fP, const char* \fItool\fP, const char* \fIproc\fP, int \fIop\fP); + char* pathrepl(char* \fIpath\fP, const char* \fImatch\fP, const char* \fIreplace\fP); + int pathsetlink(const char* \fItext\fP, char* \fIname\fP); +-char* pathshell(void); + int pathstat(const char* \fIpath\fP, struct stat* \fIst\fP); + char* pathtemp(char* \fIpath\fP, const char* \fIdir\fP, const char* \fIpfx\fP); + .EE +@@ -361,18 +360,6 @@ above for weird + .IR universe (1) + interactions hidden by this routine. + .PP +-.L pathshell +-returns a pointer to the pathname for the shell for the current process. +-The +-.L SHELL +-environment variable is first consulted, but is rejected under suspicious +-ownership/setuid conditions of if it seems to point to +-.IR csh (1) ; +-otherwise +-.L confstr(_CS_SHELL,...) +-is used. +-A valid string is always returned. +-.PP + .L pathstat + first tries + .LI stat( path,st ) +diff --git a/src/lib/libast/man/proc.3 b/src/lib/libast/man/proc.3 +index a338130..9aa66e9 100644 +--- a/src/lib/libast/man/proc.3 ++++ b/src/lib/libast/man/proc.3 +@@ -80,8 +80,9 @@ If + .I command + is + .L 0 +-then the current shell is used (see +-.IR pathshell (3)). ++then the shell returned by ++.IR astconf (3) ++is used. + If + .I envv + is not +diff --git a/src/lib/libast/misc/cmdarg.c b/src/lib/libast/misc/cmdarg.c +index bb4a4e3..6f8b24f 100644 +--- a/src/lib/libast/misc/cmdarg.c ++++ b/src/lib/libast/misc/cmdarg.c +@@ -128,7 +128,7 @@ cmdopen_20120411(char** argv, int argmax, int size, const char* argpat, Cmddisc_ + x = ARG_MAX; + if (size <= 0 || size > x) + size = x; +- sh = pathshell(); ++ sh = astconf("SH", NULL, NULL); + m = n + (argc + 4) * sizeof(char**) + strlen(sh) + 1; + m = roundof(m, sizeof(char**)); + if (size < m) +diff --git a/src/lib/libast/misc/procopen.c b/src/lib/libast/misc/procopen.c +index 444f612..7482fcf 100644 +--- a/src/lib/libast/misc/procopen.c ++++ b/src/lib/libast/misc/procopen.c +@@ -722,7 +722,7 @@ procopen(const char* cmd, char** argv, char** envv, long* modv, int flags) + *p = path; + *--p = "sh"; + } +- strcpy(env + 2, (flags & PROC_PARANOID) ? astconf("SH", NULL, NULL) : pathshell()); ++ strcpy(env + 2, astconf("SH", NULL, NULL)); + if (forked || (flags & PROC_OVERLAY)) + execve(env + 2, p, environ); + #if _use_spawnveg +diff --git a/src/lib/libast/path/pathprog.c b/src/lib/libast/path/pathprog.c +deleted file mode 100644 +index 09a6148..0000000 +--- a/src/lib/libast/path/pathprog.c ++++ /dev/null +@@ -1,124 +0,0 @@ +-/*********************************************************************** +-* * +-* This software is part of the ast package * +-* Copyright (c) 1985-2012 AT&T Intellectual Property * +-* Copyright (c) 2020-2023 Contributors to ksh 93u+m * +-* and is licensed under the * +-* Eclipse Public License, Version 2.0 * +-* * +-* A copy of the License is available at * +-* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html * +-* (with md5 checksum 84283fa8859daf213bdda5a9f8d1be1d) * +-* * +-* Glenn Fowler * +-* David Korn * +-* Phong Vo * +-* Martijn Dekker * +-* * +-***********************************************************************/ +-/* +- * Glenn Fowler +- * AT&T Research +- * +- * return the full path of the current program in path +- * command!=0 is used as a default +- */ +- +-#include +- +-#if _WINIX +-#include +-#include +-#endif +- +-#include "FEATURE/prog" +- +-#if _hdr_macho_o_dyld && _lib__NSGetExecutablePath +-#include +-#else +-#undef _lib__NSGetExecutablePath +-#endif +- +-static size_t +-prog(const char* command, char* path, size_t size) +-{ +- ssize_t n; +- char* s; +-#if _WINIX +- char* t; +- char* e; +- int c; +- int q; +-#endif +-#if _lib__NSGetExecutablePath +- uint32_t z; +-#endif +- +-#ifdef _PROC_PROG +- if ((n = readlink(_PROC_PROG, path, size)) > 0 && *path == '/') +- { +- if (n < size) +- path[n] = 0; +- return n; +- } +-#endif +-#if _lib_getexecname +- if ((s = (char*)getexecname()) && *s == '/') +- goto found; +-#endif +-#if _lib__NSGetExecutablePath +- z = size; +- if (!_NSGetExecutablePath(path, &z) && *path == '/') +- return strlen(path); +-#endif +-#if _WINIX +- if (s = GetCommandLine()) +- { +- n = 0; +- q = 0; +- t = path; +- e = path + size - 1; +- while (c = *s++) +- { +- if (c == q) +- q = 0; +- else if (!q && c == '"') +- q = c; +- else if (!q && isspace(c)) +- break; +- else if (t < e) +- *t++ = c == '\\' ? '/' : c; +- else +- n++; +- } +- if (t < e) +- *t = 0; +- return (t - path) + n; +- } +-#endif +- if (command) +- { +- s = (char*)command; +- goto found; +- } +- return 0; +- found: +- n = strlen(s); +- if (n < size) +- memcpy(path, s, n + 1); +- return n; +-} +- +-size_t +-pathprog(const char* command, char* path, size_t size) +-{ +- char* rel; +- ssize_t n; +- +- if ((n = prog(command, path, size)) > 0 && n < size && *path != '/' && (rel = strdup(path))) +- { +- n = pathpath(rel, NULL, PATH_REGULAR|PATH_EXECUTE, path, size) ? strlen(path) : 0; +- free(rel); +- } +- return n; +-} +diff --git a/src/lib/libast/path/pathshell.c b/src/lib/libast/path/pathshell.c +deleted file mode 100644 +index 7537c53..0000000 +--- a/src/lib/libast/path/pathshell.c ++++ /dev/null +@@ -1,115 +0,0 @@ +-/*********************************************************************** +-* * +-* This software is part of the ast package * +-* Copyright (c) 1985-2011 AT&T Intellectual Property * +-* Copyright (c) 2020-2023 Contributors to ksh 93u+m * +-* and is licensed under the * +-* Eclipse Public License, Version 2.0 * +-* * +-* A copy of the License is available at * +-* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html * +-* (with md5 checksum 84283fa8859daf213bdda5a9f8d1be1d) * +-* * +-* Glenn Fowler * +-* David Korn * +-* Phong Vo * +-* Martijn Dekker * +-* Johnothan King * +-* * +-***********************************************************************/ +-/* +- * G. S. Fowler +- * D. G. Korn +- * AT&T Bell Laboratories +- * +- * shell library support +- */ +- +-#include +-#include +- +-/* +- * return pointer to the full path name of the shell +- * +- * SHELL is read from the environment and must start with / +- * +- * if setuid or setgid then the executable and its containing +- * directory must not be owned by the real user/group +- * +- * root/administrator has its own test +- * +- * astconf("SH",NULL,NULL) is returned by default +- * +- * NOTE: csh is rejected because the bsh/csh differentiation is +- * not done for `csh script arg ...' +- */ +- +-#ifdef _WINIX +-# define EXE "?(.exe)" +-#else +-# define EXE +-#endif +- +-char* +-pathshell(void) +-{ +- char* sh; +- int ru; +- int eu; +- int rg; +- int eg; +- struct stat st; +- +- static char* val; +- +- if ((sh = getenv("SHELL")) && *sh == '/' && strmatch(sh, "*/(sh|*[!cC]sh)*([[:digit:]])?(-+([.[:alnum:]]))" EXE)) +- { +- if (!(ru = getuid()) || !eaccess("/bin", W_OK)) +- { +- if (stat(sh, &st)) +- goto defshell; +- if (ru != st.st_uid && !strmatch(sh, "?(/usr)?(/local)/?([ls])bin/?([[:lower:]])sh" EXE)) +- goto defshell; +- } +- else +- { +- eu = geteuid(); +- rg = getgid(); +- eg = getegid(); +- if (ru != eu || rg != eg) +- { +- char* s; +- char dir[PATH_MAX]; +- +- s = sh; +- for (;;) +- { +- if (stat(s, &st)) +- goto defshell; +- if (ru != eu && st.st_uid == ru) +- goto defshell; +- if (rg != eg && st.st_gid == rg) +- goto defshell; +- if (s != sh) +- break; +- if (strlen(s) >= sizeof(dir)) +- goto defshell; +- strcpy(dir, s); +- if (!(s = strrchr(dir, '/'))) +- break; +- *s = 0; +- s = dir; +- } +- } +- } +- return sh; +- } +- defshell: +- if (!(sh = val)) +- { +- if (!*(sh = astconf("SH", NULL, NULL)) || *sh != '/' || eaccess(sh, X_OK) || !(sh = strdup(sh))) +- sh = "/bin/sh"; +- val = sh; +- } +- return sh; +-} +-- +2.50.1 + diff --git a/SOURCES/ksh-1.0.9-no-TERM-env-segfault.patch b/SOURCES/ksh-1.0.9-no-TERM-env-segfault.patch new file mode 100644 index 0000000..53fc1f3 --- /dev/null +++ b/SOURCES/ksh-1.0.9-no-TERM-env-segfault.patch @@ -0,0 +1,59 @@ +From 26eec44e33ed4a48cb7ba34706d96387385d1980 Mon Sep 17 00:00:00 2001 +From: Johnothan King +Date: Thu, 22 Feb 2024 15:26:57 -0800 +Subject: [PATCH] Fix segfault on starting ksh with no TERM env var (#723) + +This commit fixes a crash that prevented ksh from starting up in +single user mode on DragonFlyBSD and NetBSD. + +src/cmd/ksh93/edit/edit.c: +- Make sure the np node for $TERM is not null before checking for + an export attribute. + +Co-authored-by: Martijn Dekker +Resolves: https://github.com/ksh93/ksh/issues/722 +--- + src/cmd/ksh93/edit/edit.c | 2 +- + src/cmd/ksh93/tests/pty.sh | 14 ++++++++++++++ + 2 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c +index 32e1e83..0ac54ba 100644 +--- a/src/cmd/ksh93/edit/edit.c ++++ b/src/cmd/ksh93/edit/edit.c +@@ -614,7 +614,7 @@ void ed_setup(Edit_t *ep, int fd, int reedit) + static char *oldterm; + Namval_t *np = nv_search("TERM",sh.var_tree,0); + char *term = NULL; +- if(nv_isattr(np,NV_EXPORT)) ++ if(np && nv_isattr(np,NV_EXPORT)) + term = nv_getval(np); + if(!term) + term = ""; +diff --git a/src/cmd/ksh93/tests/pty.sh b/src/cmd/ksh93/tests/pty.sh +index 5dbdf6c..b4f8e28 100755 +--- a/src/cmd/ksh93/tests/pty.sh ++++ b/src/cmd/ksh93/tests/pty.sh +@@ -1255,5 +1255,19 @@ w _ksh_93u_m_cmdcompl\t + r :test-2: _ksh_93u_m_cmdcomplete_test_ \r\n$ + ! + ++((multiline && (SHOPT_VSH || SHOPT_ESH))) && TERM=vt100 tst $LINENO <<"!" ++L crash when TERM is undefined ++# https://github.com/ksh93/ksh/issues/722 ++ ++d 40 ++p :test-1: ++w unset TERM ++p :test-2: ++w "$SHELL" ++p :test-3: ++w print Exit status $? ++u ^Exit status 0\r\n$ ++! ++ + # ====== + exit $((Errors<125?Errors:125)) +-- +2.49.0 + diff --git a/SPECS/ksh.spec b/SPECS/ksh.spec index 9b39dcf..fb3e6e0 100644 --- a/SPECS/ksh.spec +++ b/SPECS/ksh.spec @@ -4,7 +4,7 @@ URL: http://www.kornshell.com/ License: EPL-1.0 Epoch: 3 Version: 1.0.6 -Release: 7%{?dist}.2 +Release: 14%{?dist} Source0: https://github.com/ksh93/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz Source1: kshcomp.conf Source2: kshrc.rhs @@ -35,9 +35,30 @@ Patch6: ksh-1.0.11-SHLVL.patch #upstream commit: https://github.com/ksh93/ksh/commit/5def43983de3ecfa38c805c02a1f0d6f1581160c Patch7: ksh-1.0.11-redir.patch +#upstream commit: https://github.com/ksh93/ksh/commit/6668c3eb0bdc48335120e7c48590ab46af0ef0f3 +Patch8: ksh-1.0.10-pjob.patch + +#upstream commit: https://github.com/ksh93/ksh/commit/b15f63284bcd656729be61be6434376876be5bfc +#upstream commit: https://github.com/ksh93/ksh/commit/5e3a169785139809f1f733314f5660769c86d10c (test fix) +Patch9: ksh-1.0.9-no-TERM-env-segfault.patch + +# upstream commit: https://github.com/ksh93/ksh/commit/4350174a5d4acabf78f97b28c6d0ae68ec703e78 +Patch10: ksh-1.0.11-stty-noecho.patch + # upstream commit: https://github.com/ksh93/ksh/commit/96d73c08a2786806f3def1fda66641b81e0af988 -Patch8: ksh-1.0.11-ssh-multibyte-long-paste.patch -Patch9: RHEL-112564.patch +Patch11: ksh-1.0.11-ssh-multibyte-long-paste.patch + +# upstream commit: https://github.com/ksh93/ksh/commit/9f03b3bdb577ce74be3122d533c02830e3038e54 +Patch12: ksh-1.0.11-segfault-sigwinch.patch + +# upstream commit: https://github.com/ksh93/ksh/commit/a1fcad4bf65fe26a3f9a386b63732ab151ce03ec +Patch13: ksh-1.0.10-blankline.patch + +# upstream commit: https://github.com/ksh93/ksh/commit/bc56018765163a8059600f5205e9e2b1f4059873 +Patch14: ksh-1.0.10-sigpipe.patch + +# https://github.com/ksh93/ksh/commit/970812e39c236ff385e440ac6d458d196c237667 +Patch15: ksh-1.0.12-security.patch Conflicts: pdksh Requires: coreutils, diffutils @@ -160,13 +181,37 @@ fi %config(noreplace) %{_sysconfdir}/binfmt.d/kshcomp.conf %changelog -* Wed Oct 01 2025 RHEL Packaging Agent - 3:1.0.6-7.2 -- Fix 'stty -echo' in scripts -- Resolves: RHEL-112564 +* Wed Aug 06 2025 Vincent Mihalkovic - 3:1.0.6-14 +- Fix arbitrary command execution/code injection bugs + Resolves: RHEL-99063 -* Tue Apr 22 2025 Vincent Mihalkovic - 3:1.0.6-7 +* Wed Jul 09 2025 Vincent Mihalkovic - 3:1.0.6-13 +- Fix SIGPIPE subshell regression + Resolves: RHEL-92646 + +* Mon Jun 02 2025 Vincent Mihalkovic - 3:1.0.6-12 +- Fix recalling lines starting with whitespace + Resolves: RHEL-74464 + +* Mon May 19 2025 Vincent Mihalkovic - 3:1.0.6-11 +- Fix segfault upon SIGWINCH after 'stty -echo' + Resolves: RHEL-91097 + +* Wed Apr 16 2025 Vincent Mihalkovic - 3:1.0.6-10 - Fix long multibyte characters paste issue via ssh - Resolves: RHEL-87336 + Resolves: RHEL-87561 + +* Mon Mar 31 2025 Vincent Mihalkovic - 3:1.0.6-9 +- Fix 'stty -echo' in scripts + Resolves: RHEL-83043 + +* Sat Mar 29 2025 Vincent Mihalkovic - 3:1.0.6-8 +- Fix segfault on starting ksh with no TERM env var + Resolves: RHEL-83283 + +* Mon Feb 17 2025 Vincent Mihalkovic - 3:1.0.6-7 +- Change p_job variable type from short to int + Resolves: RHEL-64299 * Wed Jan 22 2025 Vincent Mihalkovic - 3:1.0.6-6 - Add forking workaround for block stdout redir