Fix segfault upon SIGWINCH after 'stty -echo'
Resolves: RHEL-91097
This commit is contained in:
parent
4512a15f36
commit
39c92b3117
264
ksh-1.0.11-segfault-sigwinch.patch
Normal file
264
ksh-1.0.11-segfault-sigwinch.patch
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
From b533bc2feb9a1b58b9cdb3a9f5bc94f4ff060a84 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martijn Dekker <martijn@inlv.org>
|
||||||
|
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; /* <ESC> 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
|
||||||
|
|
8
ksh.spec
8
ksh.spec
@ -4,7 +4,7 @@ URL: http://www.kornshell.com/
|
|||||||
License: EPL-1.0
|
License: EPL-1.0
|
||||||
Epoch: 3
|
Epoch: 3
|
||||||
Version: 1.0.6
|
Version: 1.0.6
|
||||||
Release: 10%{?dist}
|
Release: 11%{?dist}
|
||||||
Source0: https://github.com/ksh93/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz
|
Source0: https://github.com/ksh93/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz
|
||||||
Source1: kshcomp.conf
|
Source1: kshcomp.conf
|
||||||
Source2: kshrc.rhs
|
Source2: kshrc.rhs
|
||||||
@ -48,6 +48,9 @@ Patch10: ksh-1.0.11-stty-noecho.patch
|
|||||||
# upstream commit: https://github.com/ksh93/ksh/commit/96d73c08a2786806f3def1fda66641b81e0af988
|
# upstream commit: https://github.com/ksh93/ksh/commit/96d73c08a2786806f3def1fda66641b81e0af988
|
||||||
Patch11: ksh-1.0.11-ssh-multibyte-long-paste.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
|
||||||
|
|
||||||
Conflicts: pdksh
|
Conflicts: pdksh
|
||||||
Requires: coreutils, diffutils
|
Requires: coreutils, diffutils
|
||||||
BuildRequires: gcc
|
BuildRequires: gcc
|
||||||
@ -169,6 +172,9 @@ fi
|
|||||||
%config(noreplace) %{_sysconfdir}/binfmt.d/kshcomp.conf
|
%config(noreplace) %{_sysconfdir}/binfmt.d/kshcomp.conf
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon May 19 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-11
|
||||||
|
- Fix segfault upon SIGWINCH after 'stty -echo' Resolves: RHEL-91097
|
||||||
|
|
||||||
* Wed Apr 16 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-10
|
* Wed Apr 16 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.6-10
|
||||||
- Fix long multibyte characters paste issue via ssh
|
- Fix long multibyte characters paste issue via ssh
|
||||||
Resolves: RHEL-87561
|
Resolves: RHEL-87561
|
||||||
|
Loading…
Reference in New Issue
Block a user