import CS ksh-1.0.6-6.el9

This commit is contained in:
eabdullin 2025-03-11 07:33:27 +00:00
parent e5c95b5de9
commit 3c6614ca27
4 changed files with 369 additions and 1 deletions

View File

@ -0,0 +1,150 @@
From d381f5fd4f7fb068315fdf403d30f39452d59699 Mon Sep 17 00:00:00 2001
From: Martijn Dekker <martijn@inlv.org>
Date: Sun, 27 Oct 2024 01:34:38 +0000
Subject: [PATCH] Fix crash on 'exec' after 'unset SHLVL' (re: fa0f9796)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Vincent Mihalkovič (@vmihalko) reports:
> If the user unsets the SHLVL variable and later replaces the
> shell by executing a command, ksh will segfault.
>
> Reproducer
>
> # unset -v SHLVL
> # exec bash
> Segmaentation fault (core dumped)
>
> Reason
>
> The reason for this is that the SHLVL variable is getting
> decremented without any guard making sure it's still in the
> environment, see:
>
> src/cmd/ksh93/bltins/misc.c:
> 145: /* if the main shell is about to be replaced, decrease SHLVL
> to cancel out a subsequent increase */
> 146: if(!sh.realsubshell)
> 147: (*SHLVL->nvalue.ip)--;
This should be fixed so that SHLVL can be unset safely and lose its
special properties like other special variables do.
src/cmd/ksh93/sh/init.c,
src/cmd/ksh93/include/shell.h:
- Move the static 'shlvl' in init.c to the sh state struct, so that
'sh.shlvl' can be accessed from the entire ksh93 code base.
- Change its type from int to int32_t -- this is more correct as
nv_getval() uses this type to retrieve the value. In practice,
this makes no difference because sizeof(int) == sizeof(int32_t),
but this is not guaranteed by the standards.
src/cmd/ksh93/bltins/misc.c:
- Access sh.shlvl directly instead of dereferencing the SHLVL value
pointer, as this pointer is invalidated upon 'unset SHLVL'. This
fixes the bug.
Resolves: https://github.com/ksh93/ksh/issues/788
---
src/cmd/ksh93/bltins/misc.c | 2 +-
src/cmd/ksh93/include/shell.h | 1 +
src/cmd/ksh93/sh/init.c | 15 +++++++--------
src/cmd/ksh93/tests/variables.sh | 7 +++++++
4 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/src/cmd/ksh93/bltins/misc.c b/src/cmd/ksh93/bltins/misc.c
index 92b0183..808241f 100644
--- a/src/cmd/ksh93/bltins/misc.c
+++ b/src/cmd/ksh93/bltins/misc.c
@@ -147,7 +147,7 @@ int b_exec(int argc,char *argv[], Shbltin_t *context)
return 1;
/* if the main shell is about to be replaced, decrease SHLVL to cancel out a subsequent increase */
if(!sh.realsubshell)
- (*SHLVL->nvalue.ip)--;
+ sh.shlvl--;
/* force bad exec to terminate shell */
pp = (struct checkpt*)sh.jmplist;
pp->mode = SH_JMPEXIT;
diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h
index 58e2f2a..0613ceb 100644
--- a/src/cmd/ksh93/include/shell.h
+++ b/src/cmd/ksh93/include/shell.h
@@ -270,6 +270,7 @@ struct Shell_s
* Programs using libshell should not rely on them as they may change. */
int subshell; /* set for virtual subshell */
int realsubshell; /* ${.sh.subshell}, actual subshell level (including virtual and forked) */
+ int32_t shlvl; /* $SHLVL, non-subshell child shell level */
char shcomp; /* set when running shcomp */
unsigned char trapnote; /* set when trap/signal is pending */
struct sh_scoped st; /* scoped information */
diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c
index 15c0736..f4daaac 100644
--- a/src/cmd/ksh93/sh/init.c
+++ b/src/cmd/ksh93/sh/init.c
@@ -224,7 +224,6 @@ static Init_t *nv_init(void);
#if SHOPT_STATS
static void stat_init(void);
#endif
-static int shlvl;
static int rand_shift;
/*
@@ -1354,8 +1353,8 @@ Shell_t *sh_init(int argc,char *argv[], Shinit_f userinit)
sfprintf(sh.strbuf,"%s/.kshrc",nv_getval(HOME));
nv_putval(ENVNOD,sfstruse(sh.strbuf),NV_RDONLY);
}
- *SHLVL->nvalue.ip +=1;
- nv_offattr(SHLVL,NV_IMPORT);
+ sh.shlvl++;
+ nv_offattr(SHLVL,NV_IMPORT);
#if SHOPT_SPAWN
{
/*
@@ -1668,13 +1667,13 @@ int sh_reinit(char *argv[])
memset(sh.st.trapcom,0,(sh.st.trapmax+1)*sizeof(char*));
sh_sigreset(0);
/* increase SHLVL */
- if(!(SHLVL->nvalue.ip))
+ if(!(SHLVL->nvalue.lp))
{
- shlvl = 0;
- SHLVL->nvalue.ip = &shlvl;
+ sh.shlvl = 0;
+ SHLVL->nvalue.lp = &sh.shlvl;
nv_onattr(SHLVL,NV_INTEGER|NV_EXPORT|NV_NOFREE);
}
- *SHLVL->nvalue.ip +=1;
+ sh.shlvl++;
nv_offattr(SHLVL,NV_IMPORT);
sh.st.filename = sh_strdup(sh.lastarg);
nv_delete(NULL, NULL, 0);
@@ -1823,7 +1822,7 @@ static Init_t *nv_init(void)
sh.nvfun.last = (char*)&sh;
sh.nvfun.nofree = 1;
sh.var_base = sh.var_tree = sh_inittree(shtab_variables);
- SHLVL->nvalue.ip = &shlvl;
+ SHLVL->nvalue.lp = &sh.shlvl;
ip->IFS_init.hdr.disc = &IFS_disc;
ip->PATH_init.disc = &RESTRICTED_disc;
ip->PATH_init.nofree = 1;
diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh
index 7d2de08..08a0789 100755
--- a/src/cmd/ksh93/tests/variables.sh
+++ b/src/cmd/ksh93/tests/variables.sh
@@ -1609,5 +1609,12 @@ got=$(set +x; { "$SHELL" -c '
"(expected status 0, $(printf %q "$exp");" \
"got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))"
+# ======
+# exec after unset SHLVL
+# https://github.com/ksh93/ksh/issues/788
+{ "$SHELL" -c 'unset SHLVL; exec true'; } 2>/dev/null
+(((e=$?)==0)) || err_exit "crash after unsetting SHLVL" \
+ "(expected status 0, got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))"
+
# ======
exit $((Errors<125?Errors:125))
--
2.47.0

View File

@ -0,0 +1,118 @@
From 5def43983de3ecfa38c805c02a1f0d6f1581160c Mon Sep 17 00:00:00 2001
From: Martijn Dekker <martijn@inlv.org>
Date: Thu, 31 Oct 2024 20:56:54 +0000
Subject: [PATCH] Add forking workaround for block stdout redir (re: e373e8c1)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Reproducer:
ok=$({ true >&2; } >&2; echo OK); echo $ok
This should output "OK" but currently outputs nothing.
Looks like the sh_subfork() workaround must also be implemented for
the TSETIO case in sh_exec(), as that is where redirections for
blocks and compound commands are handled. This avoids inconsistent
behaviour that happens if sh_subfork() is called later for the
inside redirection.
src/cmd/ksh93/sh/xec.c: sh_exec(): case TSETIO:
- Also fork if standard output redirections attached to blocks are
executed within a non-subshare command substitution.
Thanks to Vincent Mihalkovič (@vmihalko) for the report.
Resolves: https://github.com/ksh93/ksh/issues/784
---
NEWS | 8 ++++++++
src/cmd/ksh93/include/version.h | 2 +-
src/cmd/ksh93/sh/xec.c | 15 ++++++++-------
src/cmd/ksh93/tests/io.sh | 32 +++++++++++++++++++++++++++++++-
4 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c
index 01b390d..ca67142 100644
--- a/src/cmd/ksh93/sh/xec.c
+++ b/src/cmd/ksh93/sh/xec.c
@@ -1682,21 +1682,22 @@ int sh_exec(const Shnode_t *t, int flags)
int jmpval, waitall = 0;
int simple = (t->fork.forktre->tre.tretyp&COMMSK)==TCOM;
struct checkpt *buffp = (struct checkpt*)stkalloc(sh.stk,sizeof(struct checkpt));
- if(sh.subshell && !sh.subshare && t->fork.forkio)
+ if(sh.subshell && !sh.subshare)
{
- /* Subshell forking workaround for https://github.com/ksh93/ksh/issues/161
- * Check each redirection for >&- or <&-
+ /* Subshell forking workaround for:
+ * https://github.com/ksh93/ksh/issues/161 (check each redirection for >&- or <&-)
+ * https://github.com/ksh93/ksh/issues/784 (check for stdout in a command substitution)
* TODO: find the elusive real fix */
- struct ionod *i = t->fork.forkio;
- do
+ struct ionod *i;
+ for (i = t->fork.forkio; i; i = i->ionxt)
{
- if((i->iofile & ~(IOUFD|IOPUT)) == (IOMOV|IORAW) && !strcmp(i->ioname,"-"))
- {
+ unsigned f = i->iofile;
+ if ((f & ~(IOUFD|IOPUT))==(IOMOV|IORAW) && !strcmp(i->ioname,"-") || (f & IOUFD)==1 && sh.comsub)
+ {
sh_subfork();
break;
}
}
- while(i = i->ionxt);
}
sh_pushcontext(buffp,SH_JMPIO);
if(type&FPIN)
diff --git a/src/cmd/ksh93/tests/io.sh b/src/cmd/ksh93/tests/io.sh
index 6f70dc1..861bf27 100755
--- a/src/cmd/ksh93/tests/io.sh
+++ b/src/cmd/ksh93/tests/io.sh
@@ -927,7 +927,6 @@ fi
# ======
# Command substitution hangs, writing infinite zero bytes, when redirecting standard output on a built-in that forks
# https://github.com/ksh93/ksh/issues/416
-exp='line'
"$SHELL" -c 'echo "$(ulimit -t unlimited >/dev/null 2>&1; echo "ok $$")"' >out 2>&1 &
pid=$!
(sleep 1; kill -9 "$pid") 2>/dev/null &
@@ -938,6 +937,37 @@ then kill "$!" # the sleep process
else err_exit "comsub hangs after fork with stdout redirection"
fi
+# https://github.com/ksh93/ksh/issues/416#issuecomment-1008866883
+exp='line'
+"$SHELL" -c 'alias foo=bar; echo $(alias foo >/dev/null; echo "$1")' "$0" "$exp" >out 2>&1 &
+pid=$!
+(sleep 1; kill -9 "$pid") 2>/dev/null &
+if wait "$pid" 2>/dev/null
+then kill "$!" # the sleep process
+ [[ $(<out) == "$exp" ]] || err_exit "comsub fails after stdout redirection" \
+ "(expected '$exp', got '$(<out)')"
+else err_exit "comsub hangs after stdout redirection"
+fi
+
+# same bug for compound/block commands: https://github.com/ksh93/ksh/issues/784
+exp=$'funA\nA'
+"$SHELL" -c '
+ BugFunction() {
+ { echo "funA" >&2; } >&2
+ echo A
+ }
+ Result=$(BugFunction)
+ echo $Result
+' >out 2>&1 &
+pid=$!
+(sleep 1; kill -9 "$pid") 2>/dev/null &
+if wait "$pid" 2>/dev/null
+then kill "$!" # the sleep process
+ [[ $(<out) == "$exp" ]] || err_exit "double redirection in command substitution" \
+ "(expected $(printf %q "$exp"), got $(printf %q "$(<out)"))"
+else err_exit "double redirection in command substitution causes shell hang"
+fi
+
# ======
# https://github.com/ksh93/ksh/issues/161
got=$(

View File

@ -0,0 +1,79 @@
diff --git a/src/cmd/ksh93/bltins/cflow.c b/src/cmd/ksh93/bltins/cflow.c
index b7cfd19..66e0f70 100644
--- a/src/cmd/ksh93/bltins/cflow.c
+++ b/src/cmd/ksh93/bltins/cflow.c
@@ -67,8 +67,12 @@ done:
{
long l = strtol(*argv, NULL, 10);
if(do_exit)
+ {
n = (int)(l & SH_EXITMASK); /* exit: apply bitmask before conversion to avoid undefined int overflow */
- else if((long)(n = (int)l) != l) /* return: convert to int and check for overflow (should be safe enough) */
+ if (sh.intrap)
+ sh.intrap_exit_n = 1;
+ }
+ else if((long)(n = (int)l) != l) /* return: convert to int and check for overflow (should be safe enough) */
{
errormsg(SH_DICT,ERROR_warn(0),"%s: out of range",*argv);
n = 128; /* overflow is undefined, so use a consistent status for this */
diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h
index 9794995..58e2f2a 100644
--- a/src/cmd/ksh93/include/shell.h
+++ b/src/cmd/ksh93/include/shell.h
@@ -308,6 +308,7 @@ struct Shell_s
int savesig;
unsigned char *sigflag; /* pointer to signal states */
char intrap;
+ char intrap_exit_n; /* set if 'exit n' within trap */
char forked;
char binscript;
char funload;
diff --git a/src/cmd/ksh93/sh/fault.c b/src/cmd/ksh93/sh/fault.c
index 510bf56..8222a9d 100644
--- a/src/cmd/ksh93/sh/fault.c
+++ b/src/cmd/ksh93/sh/fault.c
@@ -528,11 +528,7 @@ int sh_trap(const char *trap, int mode)
if(jmpval==SH_JMPSCRIPT)
indone=0;
else
- {
- if(jmpval==SH_JMPEXIT)
- savxit = sh.exitval;
jmpval=SH_JMPTRAP;
- }
}
sh_popcontext(&buff);
/* re-allow last-command exec optimisation unless the command we executed set a trap */
@@ -541,8 +537,10 @@ int sh_trap(const char *trap, int mode)
sh.intrap--;
sfsync(sh.outpool);
savxit_return = sh.exitval;
- if(jmpval!=SH_JMPEXIT && jmpval!=SH_JMPFUN)
- sh.exitval=savxit;
+ if(sh.intrap_exit_n)
+ sh.intrap_exit_n = 0;
+ else
+ sh.exitval = savxit;
stkset(sh.stk,savptr,staktop);
fcrestore(&savefc);
if(was_history)
diff --git a/src/cmd/ksh93/tests/return.sh b/src/cmd/ksh93/tests/return.sh
index 25e4c7a..8db197b 100755
--- a/src/cmd/ksh93/tests/return.sh
+++ b/src/cmd/ksh93/tests/return.sh
@@ -247,5 +247,15 @@ foo && err_exit "'exit' within { block; } with redirection does not preserve exi
foo() { false; (exit); }
foo && err_exit "'exit' within subshell does not preserve exit status"
+# ======
+# old AT&T bug reintroduced in v1.0.8 (commit aea99158)
+f() { true; return; }
+trap 'f; echo $? >out' USR1
+(exit 13)
+kill -s USR1 ${.sh.pid}
+trap - USR1
+unset -f f
+[[ $(<out) == 0 ]] || err_exit "default return status in traps is broken (expected 0, got $(<out))"
+
# ======
exit $((Errors<125?Errors:125))

View File

@ -4,7 +4,7 @@ URL: http://www.kornshell.com/
License: EPL-1.0
Epoch: 3
Version: 1.0.6
Release: 3%{?dist}
Release: 6%{?dist}
Source0: https://github.com/ksh93/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz
Source1: kshcomp.conf
Source2: kshrc.rhs
@ -26,6 +26,15 @@ 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
#upstream commit: https://github.com/ksh93/ksh/commit/428c0917f3043358c9b54cc137a5037d69b01ed4
Patch5: ksh-1.0.9-trap-return-status.patch
#upstream commit: https://github.com/ksh93/ksh/commit/caae9aa23e2851cadf55f858a8f38b9f0de74314
Patch6: ksh-1.0.11-SHLVL.patch
#upstream commit: https://github.com/ksh93/ksh/commit/5def43983de3ecfa38c805c02a1f0d6f1581160c
Patch7: ksh-1.0.11-redir.patch
Conflicts: pdksh
Requires: coreutils, diffutils
BuildRequires: gcc
@ -147,6 +156,18 @@ fi
%config(noreplace) %{_sysconfdir}/binfmt.d/kshcomp.conf
%changelog
* Wed Jan 22 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-6
- Add forking workaround for block stdout redir
Resolves: RHEL-55913
* Mon Jan 13 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-5
- Fix crash on 'exec' after 'unset SHLVL'
Resolves: RHEL-59656
* Tue Oct 01 2024 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-4
- Fix bad default 'return' status in traps
Resolves: RHEL-62228
* Sat Feb 10 2024 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-3
- Fix segfault in strdup
Resolves: RHEL-25019