From 18a7481e19779d6193f74a39326b071c4c428948 Mon Sep 17 00:00:00 2001 From: Toshaan Bharvani Date: Wed, 22 May 2024 14:06:46 +0200 Subject: [PATCH] update to 1.0.6 Signed-off-by: Toshaan Bharvani --- SOURCES/ksh-1.0.6-alarm-1.patch | 541 ++++++++++++++++++++++++ SOURCES/ksh-1.0.6-alarm-2.patch | 162 +++++++ SOURCES/ksh-1.0.7-history-trim.patch | 99 +++++ SOURCES/ksh-1.0.7-segfault-strdup.patch | 58 +++ SPECS/ksh.spec | 57 ++- 5 files changed, 900 insertions(+), 17 deletions(-) create mode 100644 SOURCES/ksh-1.0.6-alarm-1.patch create mode 100644 SOURCES/ksh-1.0.6-alarm-2.patch create mode 100644 SOURCES/ksh-1.0.7-history-trim.patch create mode 100644 SOURCES/ksh-1.0.7-segfault-strdup.patch diff --git a/SOURCES/ksh-1.0.6-alarm-1.patch b/SOURCES/ksh-1.0.6-alarm-1.patch new file mode 100644 index 0000000..7e18055 --- /dev/null +++ b/SOURCES/ksh-1.0.6-alarm-1.patch @@ -0,0 +1,541 @@ +diff --git a/src/cmd/ksh93/Mamfile b/src/cmd/ksh93/Mamfile +index f6e6ac8..9d72d87 100644 +--- a/src/cmd/ksh93/Mamfile ++++ b/src/cmd/ksh93/Mamfile +@@ -220,30 +220,18 @@ make install + done pmain.o generated + make libshell.a archive + prev shell.req +- make cd_pwd.o +- make bltins/cd_pwd.c +- make include/test.h implicit +- prev include/shtable.h implicit +- make include/defs.h implicit +- prev include/regress.h implicit dontcare +- prev include/shtable.h +- prev include/shell.h +- prev ${PACKAGE_ast_INCLUDE}/endian.h +- prev include/name.h +- prev include/argnod.h implicit +- prev ${PACKAGE_ast_INCLUDE}/cdt.h +- prev ${PACKAGE_ast_INCLUDE}/error.h +- prev ${PACKAGE_ast_INCLUDE}/sfio.h ++ make alarm.o ++ make bltins/alarm.c ++ make FEATURE/time implicit ++ prev features/time ++ exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/time ++ make ${PACKAGE_ast_INCLUDE}/times.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/ast_time.h implicit + prev ${PACKAGE_ast_INCLUDE}/ast.h +- done include/defs.h +- done include/test.h +- make ${PACKAGE_ast_INCLUDE}/ls.h implicit +- prev ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit dontcare +- prev ${PACKAGE_ast_INCLUDE}/ast_fs.h +- prev ${PACKAGE_ast_INCLUDE}/ast_std.h +- done ${PACKAGE_ast_INCLUDE}/ls.h ++ done ${PACKAGE_ast_INCLUDE}/times.h ++ done FEATURE/time generated + make include/builtins.h implicit +- prev include/shtable.h ++ prev include/shtable.h implicit + make FEATURE/dynamic implicit + prev features/dynamic + exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/dynamic +@@ -251,6 +239,36 @@ make install + done FEATURE/dynamic generated + prev ${PACKAGE_ast_INCLUDE}/option.h + done include/builtins.h ++ prev ${PACKAGE_ast_INCLUDE}/error.h ++ make include/defs.h implicit ++ prev include/regress.h implicit ++ prev include/shtable.h ++ prev include/shell.h ++ prev ${PACKAGE_ast_INCLUDE}/endian.h ++ prev include/name.h ++ prev include/argnod.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/cdt.h ++ prev FEATURE/externs ++ prev ${PACKAGE_ast_INCLUDE}/error.h ++ prev ${PACKAGE_ast_INCLUDE}/sfio.h ++ prev ${PACKAGE_ast_INCLUDE}/ast.h ++ done include/defs.h ++ prev shopt.h ++ done bltins/alarm.c ++ exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -DERROR_CONTEXT_T=Error_context_t -c bltins/alarm.c ++ done alarm.o generated ++ make cd_pwd.o ++ make bltins/cd_pwd.c ++ make include/test.h implicit ++ prev include/shtable.h ++ prev include/defs.h ++ done include/test.h ++ make ${PACKAGE_ast_INCLUDE}/ls.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/ast_fs.h ++ prev ${PACKAGE_ast_INCLUDE}/ast_std.h ++ done ${PACKAGE_ast_INCLUDE}/ls.h ++ prev include/builtins.h + prev include/name.h + make include/path.h implicit + make FEATURE/acct implicit +@@ -341,14 +359,7 @@ make install + make misc.o + make bltins/misc.c + prev ${PACKAGE_ast_INCLUDE}/times.h +- make FEATURE/time implicit +- prev features/time +- exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/time +- make ${PACKAGE_ast_INCLUDE}/times.h implicit +- prev ${PACKAGE_ast_INCLUDE}/ast_time.h implicit dontcare +- prev ${PACKAGE_ast_INCLUDE}/ast.h +- done ${PACKAGE_ast_INCLUDE}/times.h dontcare +- done FEATURE/time generated ++ prev FEATURE/time + prev FEATURE/locale + make include/jobs.h implicit + prev ${PACKAGE_ast_INCLUDE}/vmalloc.h +@@ -1175,7 +1186,7 @@ make install + done edit/hexpand.c + exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -DERROR_CONTEXT_T=Error_context_t -c edit/hexpand.c + done hexpand.o generated +- exec - ${AR} rc libshell.a cd_pwd.o cflow.o enum.o getopts.o hist.o misc.o mkservice.o print.o read.o sleep.o trap.o test.o typeset.o ulimit.o umask.o whence.o main.o nvdisc.o nvtype.o arith.o args.o array.o completion.o defs.o edit.o expand.o regress.o fault.o fcin.o ++ exec - ${AR} rc libshell.a alarm.o cd_pwd.o cflow.o enum.o getopts.o hist.o misc.o mkservice.o print.o read.o sleep.o trap.o test.o typeset.o ulimit.o umask.o whence.o main.o nvdisc.o nvtype.o arith.o args.o array.o completion.o defs.o edit.o expand.o regress.o fault.o fcin.o + exec - ${AR} rc libshell.a history.o init.o io.o jobs.o lex.o macro.o name.o nvtree.o parse.o path.o string.o streval.o subshell.o tdump.o timers.o trestore.o waitevent.o xec.o limits.o msg.o strdata.o testops.o keywords.o options.o signals.o aliases.o builtins.o variables.o lexstates.o emacs.o vi.o hexpand.o + exec - (ranlib libshell.a) >/dev/null 2>&1 || true + done libshell.a generated +diff --git a/src/cmd/ksh93/bltins/alarm.c b/src/cmd/ksh93/bltins/alarm.c +new file mode 100644 +index 0000000..f31bed7 +--- /dev/null ++++ b/src/cmd/ksh93/bltins/alarm.c +@@ -0,0 +1,277 @@ ++/*********************************************************************** ++* * ++* This software is part of the ast package * ++* Copyright (c) 1982-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) * ++* * ++* David Korn * ++* Martijn Dekker * ++* Johnothan King * ++* * ++***********************************************************************/ ++/* ++ * alarm [-r] [varname [+]when] ++ * ++ * David Korn ++ * AT&T Labs ++ * ++ */ ++ ++/* ++ * TODO: 2014 email from David Korn cited at : ++ * ++ * > I never documented the alarm builtin because it is problematic. The ++ * > problem is that traps can't safely be handled asynchronously. What should ++ * > happen is that the trap is marked for execution (sh.trapnote) and run after ++ * > the current command completes. The time trap should wake up the shell if ++ * > it is blocked and it should return and then handle the trap. ++ */ ++ ++#include "shopt.h" ++#include "defs.h" ++#include ++#include "builtins.h" ++#include "FEATURE/time" ++ ++#define R_FLAG 1 ++#define L_FLAG 2 ++ ++struct tevent ++{ ++ Namfun_t fun; ++ Namval_t *node; ++ Namval_t *action; ++ struct tevent *next; ++ long milli; ++ int flags; ++ void *timeout; ++}; ++ ++static const char ALARM[] = "alarm"; ++ ++static void trap_timeout(void*); ++ ++/* ++ * insert timeout item on current given list in sorted order ++ */ ++static void *time_add(struct tevent *item, void *list) ++{ ++ struct tevent *tp = (struct tevent*)list; ++ if(!tp || item->milli < tp->milli) ++ { ++ item->next = tp; ++ list = item; ++ } ++ else ++ { ++ while(tp->next && item->milli > tp->next->milli) ++ tp = tp->next; ++ item->next = tp->next; ++ tp->next = item; ++ } ++ tp = item; ++ tp->timeout = sh_timeradd(tp->milli,tp->flags&R_FLAG,trap_timeout,tp); ++ return list; ++} ++ ++/* ++ * delete timeout item from current given list, delete timer ++ */ ++static void *time_delete(struct tevent *item, void *list) ++{ ++ struct tevent *tp = (struct tevent*)list; ++ if(item==tp) ++ list = tp->next; ++ else ++ { ++ while(tp && tp->next != item) ++ tp = tp->next; ++ if(tp) ++ tp->next = item->next; ++ } ++ if(item->timeout) ++ sh_timerdel(item->timeout); ++ return list; ++} ++ ++static void print_alarms(void *list) ++{ ++ struct tevent *tp = (struct tevent*)list; ++ while(tp) ++ { ++ if(tp->timeout) ++ { ++ char *name = nv_name(tp->node); ++ if(tp->flags&R_FLAG) ++ { ++ double d = tp->milli; ++ sfprintf(sfstdout,e_alrm1,name,d/1000.); ++ } ++ else ++ sfprintf(sfstdout,e_alrm2,name,nv_getnum(tp->node)); ++ } ++ tp = tp->next; ++ } ++} ++ ++static void trap_timeout(void* handle) ++{ ++ struct tevent *tp = (struct tevent*)handle; ++ sh.trapnote |= SH_SIGALRM; ++ if(!(tp->flags&R_FLAG)) ++ tp->timeout = 0; ++ tp->flags |= L_FLAG; ++ sh.sigflag[SIGALRM] |= SH_SIGALRM; ++ if(sh_isstate(SH_TTYWAIT)) ++ sh_timetraps(); ++} ++ ++void sh_timetraps(void) ++{ ++ struct tevent *tp, *tpnext; ++ struct tevent *tptop; ++ while(1) ++ { ++ sh.sigflag[SIGALRM] &= ~SH_SIGALRM; ++ tptop= (struct tevent*)sh.st.timetrap; ++ for(tp=tptop;tp;tp=tpnext) ++ { ++ tpnext = tp->next; ++ if(tp->flags&L_FLAG) ++ { ++ tp->flags &= ~L_FLAG; ++ if(tp->action) ++ sh_fun(tp->action,tp->node,NULL); ++ tp->flags &= ~L_FLAG; ++ if(!tp->flags) ++ nv_unset(tp->node); ++ } ++ } ++ if(!(sh.sigflag[SIGALRM]&SH_SIGALRM)) ++ break; ++ } ++} ++ ++ ++/* ++ * This trap function catches "alarm" actions only ++ */ ++static char *setdisc(Namval_t *np, const char *event, Namval_t* action, Namfun_t *fp) ++{ ++ struct tevent *tp = (struct tevent*)fp; ++ if(!event) ++ return action ? Empty : (char*)ALARM; ++ if(strcmp(event,ALARM)!=0) ++ { ++ /* try the next level */ ++ return nv_setdisc(np, event, action, fp); ++ } ++ if(action==np) ++ action = tp->action; ++ else ++ tp->action = action; ++ return action ? (char*)action : Empty; ++} ++ ++/* ++ * catch assignments and set alarm traps ++ */ ++static void putval(Namval_t* np, const char* val, int flag, Namfun_t* fp) ++{ ++ struct tevent *tp = (struct tevent*)fp; ++ double d; ++ if(val) ++ { ++ double now; ++#ifdef timeofday ++ struct timeval tmp; ++ timeofday(&tmp); ++ now = tmp.tv_sec + 1.e-6*tmp.tv_usec; ++#else ++ now = (double)time(NULL); ++#endif /* timeofday */ ++ nv_putv(np,val,flag,fp); ++ d = nv_getnum(np); ++ if(*val=='+') ++ { ++ double x = d + now; ++ nv_putv(np,(char*)&x,NV_INTEGER|NV_DOUBLE,fp); ++ } ++ else ++ d -= now; ++ tp->milli = 1000*(d+.0005); ++ if(tp->timeout) ++ sh.st.timetrap = time_delete(tp,sh.st.timetrap); ++ if(tp->milli > 0) ++ sh.st.timetrap = time_add(tp,sh.st.timetrap); ++ } ++ else ++ { ++ tp = (struct tevent*)nv_stack(np, NULL); ++ sh.st.timetrap = time_delete(tp,sh.st.timetrap); ++ nv_unset(np); ++ free(fp); ++ } ++} ++ ++static const Namdisc_t alarmdisc = ++{ ++ sizeof(struct tevent), ++ putval, ++ 0, ++ 0, ++ setdisc, ++}; ++ ++int b_alarm(int argc,char *argv[],Shbltin_t *context) ++{ ++ int n,rflag=0; ++ Namval_t *np; ++ struct tevent *tp; ++ while (n = optget(argv, sh_optalarm)) switch (n) ++ { ++ case 'r': ++ rflag = R_FLAG; ++ break; ++ case ':': ++ errormsg(SH_DICT,2, "%s", opt_info.arg); ++ break; ++ case '?': ++ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); ++ UNREACHABLE(); ++ } ++ argc -= opt_info.index; ++ argv += opt_info.index; ++ if(error_info.errors) ++ { ++ errormsg(SH_DICT,ERROR_usage(2),optusage(NULL)); ++ UNREACHABLE(); ++ } ++ if(argc==0) ++ { ++ print_alarms(sh.st.timetrap); ++ return 0; ++ } ++ if(argc!=2) ++ { ++ errormsg(SH_DICT,ERROR_usage(2),optusage(NULL)); ++ UNREACHABLE(); ++ } ++ np = nv_open(argv[0],sh.var_tree,NV_NOARRAY|NV_VARNAME); ++ if(!nv_isnull(np)) ++ nv_unset(np); ++ nv_setattr(np, NV_DOUBLE); ++ tp = sh_newof(NULL,struct tevent,1,0); ++ tp->fun.disc = &alarmdisc; ++ tp->flags = rflag; ++ tp->node = np; ++ nv_stack(np,(Namfun_t*)tp); ++ nv_putval(np, argv[1], 0); ++ return 0; ++} +diff --git a/src/cmd/ksh93/bltins/sleep.c b/src/cmd/ksh93/bltins/sleep.c +index b34e62d..3bb55b1 100644 +--- a/src/cmd/ksh93/bltins/sleep.c ++++ b/src/cmd/ksh93/bltins/sleep.c +@@ -127,6 +127,8 @@ skip: + if(tloc < (now=time(NULL))) + break; + d = (double)(tloc-now); ++ if(sh.sigflag[SIGALRM]&SH_SIGTRAP) ++ sh_timetraps(); + } + return 0; + } +diff --git a/src/cmd/ksh93/data/builtins.c b/src/cmd/ksh93/data/builtins.c +index 760b7ce..22ea156 100644 +--- a/src/cmd/ksh93/data/builtins.c ++++ b/src/cmd/ksh93/data/builtins.c +@@ -116,6 +116,7 @@ const struct shtable3 shtab_builtins[] = + "pwd", NV_BLTIN|BLT_ENV, bltin(pwd), + "read", NV_BLTIN|BLT_ENV, bltin(read), + "sleep", NV_BLTIN, bltin(sleep), ++ "alarm", NV_BLTIN|BLT_ENV, bltin(alarm), + "times", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(times), + "ulimit", NV_BLTIN|BLT_ENV, bltin(ulimit), + "umask", NV_BLTIN|BLT_ENV, bltin(umask), +@@ -2170,6 +2171,8 @@ const char sh_optwhence[] = + ; + + ++const char e_alrm1[] = "alarm -r %s +%.3g\n"; ++const char e_alrm2[] = "alarm %s %.3f\n"; + const char e_baddisc[] = "%s: invalid discipline function"; + const char e_nofork[] = "cannot fork"; + const char e_nosignal[] = "%s: unknown signal name"; +diff --git a/src/cmd/ksh93/include/builtins.h b/src/cmd/ksh93/include/builtins.h +index 34c697c..f6b3f59 100644 +--- a/src/cmd/ksh93/include/builtins.h ++++ b/src/cmd/ksh93/include/builtins.h +@@ -115,6 +115,8 @@ extern int b_times(int, char*[],Shbltin_t*); + + extern short b_enum_nelem(Namfun_t*); + ++extern const char e_alrm1[]; ++extern const char e_alrm2[]; + extern const char e_badfun[]; + extern const char e_baddisc[]; + extern const char e_nofork[]; +diff --git a/src/cmd/ksh93/include/defs.h b/src/cmd/ksh93/include/defs.h +index 306ea7e..b5bfb67 100644 +--- a/src/cmd/ksh93/include/defs.h ++++ b/src/cmd/ksh93/include/defs.h +@@ -143,6 +143,7 @@ extern void sh_subjobcheck(pid_t); + extern int sh_subsavefd(int); + extern void sh_subtmpfile(void); + extern char *sh_substitute(const char*,const char*,char*); ++extern void sh_timetraps(void); + extern const char *_sh_translate(const char*); + extern int sh_trace(char*[],int); + extern void sh_trim(char*); +diff --git a/src/cmd/ksh93/include/fault.h b/src/cmd/ksh93/include/fault.h +index b57a0ab..7750f80 100644 +--- a/src/cmd/ksh93/include/fault.h ++++ b/src/cmd/ksh93/include/fault.h +@@ -58,6 +58,7 @@ typedef void (*SH_SIGTYPE)(int,void(*)(int)); + #define SH_SIGIGNORE 040 /* default is ignore signal */ + #define SH_SIGINTERACTIVE 0100 /* handle interactive specially */ + #define SH_SIGTSTP 0200 /* tstp signal received */ ++#define SH_SIGALRM 0200 /* timer alarm received */ + #define SH_SIGTERM SH_SIGOFF /* term signal received */ + #define SH_SIGRUNTIME 0400 /* runtime value */ + +diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h +index 57c402d..9794995 100644 +--- a/src/cmd/ksh93/include/shell.h ++++ b/src/cmd/ksh93/include/shell.h +@@ -211,6 +211,7 @@ struct sh_scoped + char **otrap; /* save parent pseudosignals for v=$(trap) */ + char **trapcom; /* EXIT and signals */ + 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; +diff --git a/src/cmd/ksh93/sh/fault.c b/src/cmd/ksh93/sh/fault.c +index 3409a6c..510bf56 100644 +--- a/src/cmd/ksh93/sh/fault.c ++++ b/src/cmd/ksh93/sh/fault.c +@@ -447,6 +447,8 @@ void sh_chktrap(void) + sh_exit(sh.exitval); + } + } ++ if(sh.sigflag[SIGALRM]&SH_SIGALRM) ++ sh_timetraps(); + #if SHOPT_BGX + if((sh.sigflag[SIGCHLD]&SH_SIGTRAP) && sh.st.trapcom[SIGCHLD]) + job_chldtrap(1); +diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c +index 116ae3b..be333b2 100644 +--- a/src/cmd/ksh93/sh/jobs.c ++++ b/src/cmd/ksh93/sh/jobs.c +@@ -1466,6 +1466,8 @@ int job_wait(pid_t pid) + continue; + if(nochild) + break; ++ if(sh.sigflag[SIGALRM]&SH_SIGTRAP) ++ sh_timetraps(); + if((intr && sh.trapnote) || (pid==1 && !intr)) + break; + } +diff --git a/src/cmd/ksh93/tests/builtins.sh b/src/cmd/ksh93/tests/builtins.sh +index 83b4086..92d2708 100755 +--- a/src/cmd/ksh93/tests/builtins.sh ++++ b/src/cmd/ksh93/tests/builtins.sh +@@ -1222,6 +1222,28 @@ function test_usage + done 3< <(builtin) + }; test_usage + ++# ====== ++# The 'alarm' builtin could make 'read' crash due to IFS table corruption caused by unsafe asynchronous execution. ++# https://bugzilla.redhat.com/1176670 ++if (builtin alarm) 2>/dev/null ++then got=$( { "$SHELL" -c ' ++ builtin alarm ++ alarm -r alarm_handler +.005 ++ i=0 ++ function alarm_handler.alarm ++ { ++ let "(++i) > 20" && exit ++ } ++ while :; do ++ echo cargo,odds and ends,jetsam,junk,wreckage,castoffs,sea-drift ++ done | while IFS="," read arg1 arg2 arg3 arg4 junk; do ++ : ++ done ++ '; } 2>&1) ++ ((!(e = $?))) || err_exit 'crash with alarm and IFS' \ ++ "(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))" ++fi ++ + # ====== + # Verify that the POSIX 'test' builtin exits with status 2 when given an invalid binary operator. + for operator in '===' ']]' +@@ -1581,7 +1603,7 @@ let Errors+=$? + # Most built-ins should handle --version + while IFS= read -r bltin <&3 + do case $bltin in +- echo | test | true | false | \[ | : | catclose | catgets | catopen | Dt* | _Dt* | X* | login | newgrp ) ++ alarm | echo | test | true | false | \[ | : | catclose | catgets | catopen | Dt* | _Dt* | X* | login | newgrp ) + continue ;; + fc | hist ) + ((SHOPT_SCRIPTONLY)) && continue ;; diff --git a/SOURCES/ksh-1.0.6-alarm-2.patch b/SOURCES/ksh-1.0.6-alarm-2.patch new file mode 100644 index 0000000..57d7ed1 --- /dev/null +++ b/SOURCES/ksh-1.0.6-alarm-2.patch @@ -0,0 +1,162 @@ +diff --git a/src/cmd/ksh93/Mamfile b/src/cmd/ksh93/Mamfile +index abc9ee1a5..d266f2178 100644 +--- a/src/cmd/ksh93/Mamfile ++++ b/src/cmd/ksh93/Mamfile +@@ -222,6 +222,10 @@ make install + prev shell.req + make alarm.o + make bltins/alarm.c ++ make include/io.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/sfio.h ++ prev ${PACKAGE_ast_INCLUDE}/ast.h ++ done include/io.h + make FEATURE/time implicit + prev features/time + exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/time +@@ -239,6 +243,22 @@ make install + done FEATURE/dynamic generated + prev ${PACKAGE_ast_INCLUDE}/option.h + done include/builtins.h ++ make include/shlex.h implicit ++ make include/lexstates.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/wctype.h ++ prev ${PACKAGE_ast_INCLUDE}/wchar.h ++ make FEATURE/locale implicit ++ prev features/locale ++ exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/locale ++ done FEATURE/locale generated ++ done include/lexstates.h ++ prev include/shtable.h ++ make include/shnodes.h implicit ++ prev include/argnod.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/ast.h ++ done include/shnodes.h ++ prev ${PACKAGE_ast_INCLUDE}/cdt.h ++ done include/shlex.h + prev ${PACKAGE_ast_INCLUDE}/error.h + make include/defs.h implicit + prev include/regress.h implicit +@@ -246,7 +266,7 @@ make install + prev include/shell.h + prev ${PACKAGE_ast_INCLUDE}/endian.h + prev include/name.h +- prev include/argnod.h implicit ++ prev include/argnod.h + prev ${PACKAGE_ast_INCLUDE}/cdt.h + prev FEATURE/externs + prev ${PACKAGE_ast_INCLUDE}/error.h +@@ -292,10 +312,7 @@ make install + make cflow.o + make bltins/cflow.c + prev include/builtins.h +- make include/shnodes.h implicit +- prev include/argnod.h +- prev ${PACKAGE_ast_INCLUDE}/ast.h +- done include/shnodes.h ++ prev include/shnodes.h + prev ${PACKAGE_ast_INCLUDE}/error.h + prev ${PACKAGE_ast_INCLUDE}/ast.h + prev include/defs.h +@@ -341,10 +358,7 @@ make install + done FEATURE/ttys generated + done include/terminal.h + prev ${PACKAGE_ast_INCLUDE}/sig.h +- make FEATURE/locale implicit +- prev features/locale +- exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/locale +- done FEATURE/locale generated ++ prev FEATURE/locale + make FEATURE/cmds implicit + prev features/cmds + exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/cmds +@@ -353,6 +367,7 @@ make install + prev include/builtins.h + prev include/history.h + prev include/name.h ++ prev include/io.h + make include/io.h implicit + prev ${PACKAGE_ast_INCLUDE}/sfio.h + prev ${PACKAGE_ast_INCLUDE}/ast.h +@@ -443,11 +458,7 @@ make install + prev include/builtins.h + prev include/name.h + prev include/io.h +- make include/lexstates.h implicit +- prev ${PACKAGE_ast_INCLUDE}/wctype.h +- prev ${PACKAGE_ast_INCLUDE}/wchar.h +- prev FEATURE/locale +- done include/lexstates.h ++ prev include/lexstates.h + prev include/variables.h + prev include/defs.h + prev ${PACKAGE_ast_INCLUDE}/error.h +@@ -545,12 +556,7 @@ make install + make whence.o + make bltins/whence.c + prev include/builtins.h +- make include/shlex.h implicit +- prev include/lexstates.h +- prev include/shtable.h +- prev include/shnodes.h +- prev ${PACKAGE_ast_INCLUDE}/cdt.h +- done include/shlex.h ++ prev include/shlex.h + prev include/path.h + prev include/name.h + prev include/shtable.h +diff --git a/src/cmd/ksh93/bltins/alarm.c b/src/cmd/ksh93/bltins/alarm.c +index f31bed711..63d4d6cbf 100644 +--- a/src/cmd/ksh93/bltins/alarm.c ++++ b/src/cmd/ksh93/bltins/alarm.c +@@ -23,21 +23,13 @@ + * + */ + +-/* +- * TODO: 2014 email from David Korn cited at : +- * +- * > I never documented the alarm builtin because it is problematic. The +- * > problem is that traps can't safely be handled asynchronously. What should +- * > happen is that the trap is marked for execution (sh.trapnote) and run after +- * > the current command completes. The time trap should wake up the shell if +- * > it is blocked and it should return and then handle the trap. +- */ +- + #include "shopt.h" + #include "defs.h" + #include ++#include + #include "builtins.h" + #include "FEATURE/time" ++#include "io.h" + + #define R_FLAG 1 + #define L_FLAG 2 +@@ -147,7 +139,26 @@ void sh_timetraps(void) + { + tp->flags &= ~L_FLAG; + if(tp->action) +- sh_fun(tp->action,tp->node,NULL); ++ { ++ /* Call the alarm discipline function. This may occur at any time including parse time, ++ * so save the lexer state and push/pop context to make sure we can restore it. */ ++ struct checkpt checkpoint; ++ int jmpval; ++ int savexit = sh.savexit; ++ Lex_t *lexp = (Lex_t*)sh.lex_context, savelex = *lexp; ++ sh_lexopen(lexp, 0); /* needs full init (0), not what it calls reinit (1) */ ++ sh_pushcontext(&checkpoint, 1); ++ jmpval = sigsetjmp(checkpoint.buff,0); ++ if(!jmpval) ++ sh_fun(tp->action,tp->node,NULL); ++ sh_popcontext(&checkpoint); ++ if(sh.topfd != checkpoint.topfd) ++ sh_iorestore(checkpoint.topfd,jmpval); ++ *lexp = savelex; ++ sh.savexit = savexit; /* avoid influencing $? */ ++ if(jmpval) ++ siglongjmp(*sh.jmplist,jmpval); ++ } + tp->flags &= ~L_FLAG; + if(!tp->flags) + nv_unset(tp->node); diff --git a/SOURCES/ksh-1.0.7-history-trim.patch b/SOURCES/ksh-1.0.7-history-trim.patch new file mode 100644 index 0000000..9b243e3 --- /dev/null +++ b/SOURCES/ksh-1.0.7-history-trim.patch @@ -0,0 +1,99 @@ +From 2075b2b96208ac8b989ca316dcdd674c3f488e2b Mon Sep 17 00:00:00 2001 +From: Martijn Dekker +Date: Thu, 28 Dec 2023 04:02:28 +0000 +Subject: [PATCH] Fix crash on failure to trim ~/.sh_history + +@vmihalko writes: +> We were able to reproduce an old issue mentioned in +> https://bugzilla.redhat.com/show_bug.cgi?id=1885399 using the +> latest version of ksh. The corresponding code has not changed +> much in the past few years. +> +> To provide further explanation, the problem arises when a user's +> .sh_history file grows to a size that triggers the hist_trim +> function, but the user lacks (after the creation of .sh_history) +> the necessary write permissions to their $HOME directory. As a +> result, ksh becomes stuck in a recursive loop between the +> sh_histinit(src/cmd/ksh93/edit/history.c#L203) function and the +> hist_trim(src/cmd/ksh93/edit/history.c#L417) function. +> +> Conditions for reproduction: +> +> 1. The size of the .sh_history file is larger than the HIST_MAX +> limit. (src/cmd/ksh93/edit/history.c, line 325) +> 2. .sh_history file has not been changed in the HIST_RECENT +> seconds (src/cmd/ksh93/edit/history.c, line 406) +> 3. The user does not have permission to write to the $HOME +> directory. + +src/cmd/ksh93/edit/history.c: hist_trim(): +- Print a warning and return if unlink(2) fails. The warning tells + the user to check the history file's parent directory is + writable. This is the best I realistically do for now, because + this function's basic method assumes a writable parent directory. +- The temp file fallback is deleted because it's fundamentally + flawed: it assumes the temp file is made on the same volume as + the history file and can simply be rename(2)'d in place. Even + on systems where this is the case, it doesn't appear to be + working correctly, but this is not worth looking into. + +Resolves: https://github.com/ksh93/ksh/issues/695 +--- + src/cmd/ksh93/edit/history.c | 34 ++++------------------------------ + 1 files changed, 4 insertions(+), 30 deletions(-) + +diff --git a/src/cmd/ksh93/edit/history.c b/src/cmd/ksh93/edit/history.c +index c49c23244d00..f3672bf6e220 100644 +--- a/src/cmd/ksh93/edit/history.c ++++ b/src/cmd/ksh93/edit/history.c +@@ -419,34 +419,13 @@ static History_t* hist_trim(History_t *hp, int n) + char *cp; + int incmd=1, c=0; + History_t *hist_new, *hist_old = hp; +- char *buff, *endbuff, *tmpname=0; ++ char *buff, *endbuff; + off_t oldp,newp; + struct stat statb; +- unlink(hist_old->histname); +- if(access(hist_old->histname,F_OK) >= 0) ++ if(unlink(hist_old->histname) < 0) + { +- /* The unlink can fail on Windows 95 */ +- int fd; +- char *last, *name=hist_old->histname; +- sh_close(sffileno(hist_old->histfp)); +- tmpname = (char*)sh_malloc(strlen(name)+14); +- if(last = strrchr(name,'/')) +- { +- *last = 0; +- pathtmp(tmpname,name,"hist",NULL); +- *last = '/'; +- } +- else +- pathtmp(tmpname,e_dot,"hist",NULL); +- if(rename(name,tmpname) < 0) +- { +- free(tmpname); +- tmpname = name; +- } +- fd = open(tmpname,O_RDONLY|O_cloexec); +- sfsetfd(hist_old->histfp,fd); +- if(tmpname==name) +- tmpname = 0; ++ errormsg(SH_DICT,ERROR_warn(0),"cannot trim history file %s; make sure parent directory is writable",hist_old->histname); ++ return hist_ptr = hist_old; + } + hist_ptr = 0; + if(fstat(sffileno(hist_old->histfp),&statb)>=0) +@@ -501,11 +480,6 @@ static History_t* hist_trim(History_t *hp, int n) + } + hist_cancel(hist_new); + sfclose(hist_old->histfp); +- if(tmpname) +- { +- unlink(tmpname); +- free(tmpname); +- } + free((char*)hist_old); + return hist_ptr = hist_new; + } diff --git a/SOURCES/ksh-1.0.7-segfault-strdup.patch b/SOURCES/ksh-1.0.7-segfault-strdup.patch new file mode 100644 index 0000000..d52f539 --- /dev/null +++ b/SOURCES/ksh-1.0.7-segfault-strdup.patch @@ -0,0 +1,58 @@ +From 9eb8532ccacf1cfdb7ba18f51eba68776852ef7c Mon Sep 17 00:00:00 2001 +From: Vincent Mihalkovic +Date: Thu, 8 Feb 2024 22:10:58 +0100 +Subject: [PATCH] Re-fix use of strdup on a NULL pointer (re: 9a9da2c2) (#718) + +Thank you @lzaoral for debugging this issue and creating this +reproducer: + +$ tty # check that the shell is connected to a pseudoterminal +/dev/pts/4 +$ mkdir /var/tmp/chroottest +$ dnf --releasever=39 --installroot=/var/tmp/chroottest install ksh +$ echo "/dev/udp/127.0.0.1/514;0;104" | + sudo tee /var/tmp/chroottest/etc/ksh_audit +$ sudo chroot /var/tmp/chroottest /bin/ksh -lic 'exit 0' +(ksh segfaults) + +Analysis: On Linux, ttyname(3)[*] may fail if: + +* EBADF Bad file descriptor. +* ENODEV fd refers to a slave pseudoterminal device but the + corresponding pathname could not be found [...]. +* ENOTTY fd does not refer to a terminal device. + +Calling isatty(3) before ttyname(3) only prevents the first and +third cases. + +src/cmd/ksh93/edit/history.c: sh_histinit(): +- To catch the second case, let's call ttyname(2) directly, check + for NULL and remove the redundant isatty() call. + +[*] https://man7.org/linux/man-pages/man3/ttyname.3.html +--- + src/cmd/ksh93/edit/history.c | 4 +++- + 1 files changed, 3 insertions(+), 1 deletions(-) + +diff --git a/src/cmd/ksh93/edit/history.c b/src/cmd/ksh93/edit/history.c +index a7b084e5c16f..25832a59265b 100644 +--- a/src/cmd/ksh93/edit/history.c ++++ b/src/cmd/ksh93/edit/history.c +@@ -15,6 +15,7 @@ + * Johnothan King * + * hyenias <58673227+hyenias@users.noreply.github.com> * + * Govind Kamat * ++* Vincent Mihalkovic * + * * + ***********************************************************************/ + /* +@@ -353,7 +354,8 @@ int sh_histinit(void) + if(fd>=0) + { + fcntl(fd,F_SETFD,FD_CLOEXEC); +- hp->tty = sh_strdup(isatty(2)?ttyname(2):"notty"); ++ const char* tty = ttyname(2); ++ hp->tty = sh_strdup(tty?tty:"notty"); + hp->auditfp = sfnew(NULL,NULL,-1,fd,SF_WRITE); + } + } diff --git a/SPECS/ksh.spec b/SPECS/ksh.spec index d305d2c..bad6c90 100644 --- a/SPECS/ksh.spec +++ b/SPECS/ksh.spec @@ -1,21 +1,30 @@ -%global verBetaPrefix 1.0.0 -%global verBetaSuffix 1 -%global verBetaFull %{verBetaPrefix}-beta.%{verBetaSuffix} - Name: ksh Summary: The Original ATT Korn Shell URL: http://www.kornshell.com/ License: EPL-1.0 Epoch: 3 -Version: %{verBetaPrefix}~beta.%{verBetaSuffix} -Release: 2%{?dist} -Source0: https://github.com/ksh93/%{name}/archive/v%{verBetaFull}/%{name}-%{verBetaFull}.tar.gz +Version: 1.0.6 +Release: 3%{?dist} +Source0: https://github.com/ksh93/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz Source1: kshcomp.conf Source2: kshrc.rhs Source3: dotkshrc -# temporary commenting out failing tests -Patch1: %{name}-%{verBetaFull}-regre-tests.patch +# The alarm builtin hase been temporarily removed from ksh in version 1.0.0. +# To prevent customer regressions we revert following upstream commits: +# https://github.com/ksh93/ksh/commit/4d50b69cbd5fce91d1f3c527dc170e192ceb4760 +# https://github.com/ksh93/ksh/commit/b369f40ded0ec7e8dd3d4a0e7226ccf037bb3400 +# https://github.com/ksh93/ksh/commit/3688842b7291db6fccdb44ff8e99ab8d4c1b2508 +Patch1: %{name}-1.0.6-alarm-1.patch +# alarm builtin was removed as it was unclear if it could ever be fixed +# alarm fixing patch from https://github.com/ksh93/ksh/issues/422#issuecomment-1581168550 +Patch2: %{name}-1.0.6-alarm-2.patch + +#https://github.com/ksh93/ksh/commit/2075b2b96208ac8b989ca316dcdd674c3f488e2b +Patch3: %{name}-1.0.7-history-trim.patch + +#upstream commit: https://github.com/ksh93/ksh/commit/9eb8532ccacf1cfdb7ba18f51eba68776852ef7c.patch +Patch4: ksh-1.0.7-segfault-strdup.patch Conflicts: pdksh Requires: coreutils, diffutils @@ -36,23 +45,20 @@ KornShell is a shell programming language, which is upward compatible with "sh" (the Bourne Shell). %prep -%autosetup -n %{name}-%{verBetaFull} -p1 +%autosetup -p1 #/dev/fd test does not work because of mock sed -i 's|ls /dev/fd|ls /proc/self/fd|' src/cmd/ksh93/features/options -# disable register for debugging -sed -i 1i"#define register" src/lib/libast/include/ast.h - %build -%set_build_flags XTRAFLAGS="" -for f in -Wno-unknown-pragmas -Wno-missing-braces -Wno-unused-result -Wno-return-type -Wno-int-to-pointer-cast -Wno-parentheses -Wno-unused -Wno-unused-but-set-variable -Wno-cpp -Wno-maybe-uninitialized -Wno-lto-type-mismatch -P +for f in -Wno-unknown-pragmas -Wno-missing-braces -Wno-unused-result -Wno-return-type -Wno-int-to-pointer-cast -Wno-parentheses -Wno-unused -Wno-unused-but-set-variable -Wno-cpp -Wno-maybe-uninitialized -Wno-lto-type-mismatch do $CC $f -E - /dev/null 2>&1 && XTRAFLAGS="$XTRAFLAGS $f" done -export CCFLAGS="$RPM_OPT_FLAGS $RPM_LD_FLAGS -fno-strict-aliasing $XTRAFLAGS" -./bin/package make -S +export CCFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing $XTRAFLAGS" +export LDFLAGS="$RPM_LD_FLAGS" +./bin/package make %install mkdir -p %{buildroot}{/bin,%{_bindir},%{_mandir}/man1} @@ -141,6 +147,23 @@ fi %config(noreplace) %{_sysconfdir}/binfmt.d/kshcomp.conf %changelog +* Sat Feb 10 2024 Vincent Mihalkovic - 3:1.0.6-3 +- Fix segfault in strdup + Resolves: RHEL-25019 + +* Wed Jan 03 2024 Vincent Mihalkovic - 3:1.0.6-2 +- Fix crash on failure to trim ~/.sh_history (#20345) + +* Mon Sep 18 2023 Vincent Mihalkovic - 3:1.0.6-1 +- Rebase to non-beta version, because upstream says it should to be used + https://github.com/ksh93/ksh/issues/667#issuecomment-1653665697 +- fix acl test case regression + Resolves: #2034188 + +* Tue Jun 27 2023 Vincent Mihalkovic - 3:1.0.0~beta.1-3 +- fix segfault when PWD is unset + Resolves: #2123066 + * Mon Aug 09 2021 Mohan Boddu - 3:1.0.0~beta.1-2 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags Related: rhbz#1991688