Fix segfault upon SIGWINCH after 'stty -echo'
Resolves: RHEL-89866
This commit is contained in:
parent
9555fd1326
commit
1b767bc288
266
ksh-1.0.11-segfault-sigwinch.patch
Normal file
266
ksh-1.0.11-segfault-sigwinch.patch
Normal file
@ -0,0 +1,266 @@
|
||||
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 | 40 ++++++++++++++++----------------------
|
||||
3 files changed, 51 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c
|
||||
index 0f46b8d..6ff1555 100644
|
||||
--- a/src/cmd/ksh93/edit/edit.c
|
||||
+++ b/src/cmd/ksh93/edit/edit.c
|
||||
@@ -617,6 +617,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
|
||||
@@ -656,7 +666,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');
|
||||
/*
|
||||
@@ -678,9 +693,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)
|
||||
@@ -704,6 +717,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 37239a5..1a65c4d 100644
|
||||
--- a/src/cmd/ksh93/edit/emacs.c
|
||||
+++ b/src/cmd/ksh93/edit/emacs.c
|
||||
@@ -182,6 +182,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;
|
||||
@@ -191,6 +192,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)
|
||||
{
|
||||
@@ -203,10 +208,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);
|
||||
@@ -237,6 +238,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)
|
||||
{
|
||||
@@ -248,10 +250,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))
|
||||
@@ -346,7 +346,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') :
|
||||
@@ -752,8 +753,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 e95afa9..cea1204 100644
|
||||
--- a/src/cmd/ksh93/edit/vi.c
|
||||
+++ b/src/cmd/ksh93/edit/vi.c
|
||||
@@ -204,6 +204,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 */
|
||||
Vi_t *vp = ed->e_vi;
|
||||
char prompt[PRSIZE+2]; /* prompt */
|
||||
genchar Physical[2*MAXLINE]; /* physical image */
|
||||
@@ -211,6 +212,12 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit)
|
||||
genchar ubuf[MAXLINE]; /* used for u command */
|
||||
genchar Window[MAXLINE]; /* window image */
|
||||
int Globals[9]; /* local global variables */
|
||||
+
|
||||
+ /*** Set raw mode ***/
|
||||
+
|
||||
+ 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);
|
||||
@@ -225,16 +232,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));
|
||||
@@ -300,18 +300,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 ***/
|
||||
@@ -356,10 +347,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
|
||||
|
||||
9
ksh.spec
9
ksh.spec
@ -4,7 +4,7 @@ URL: http://www.kornshell.com/
|
||||
License: EPL-2.0
|
||||
Epoch: 3
|
||||
Version: 1.0.10
|
||||
Release: 6%{?dist}
|
||||
Release: 7%{?dist}
|
||||
Source0: https://github.com/ksh93/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz
|
||||
Source1: kshcomp.conf
|
||||
Source2: kshrc.rhs
|
||||
@ -22,6 +22,9 @@ Patch3: ksh-1.0.11-stty-noecho.patch
|
||||
# upstream commit: https://github.com/ksh93/ksh/commit/96d73c08a2786806f3def1fda66641b81e0af988
|
||||
Patch4: ksh-1.0.11-ssh-multibyte-long-paste.patch
|
||||
|
||||
# upstream commit: https://github.com/ksh93/ksh/commit/9f03b3bdb577ce74be3122d533c02830e3038e54
|
||||
Patch5: ksh-1.0.11-segfault-sigwinch.patch
|
||||
|
||||
Conflicts: pdksh
|
||||
Requires: coreutils, diffutils
|
||||
BuildRequires: gcc
|
||||
@ -150,6 +153,10 @@ fi
|
||||
%config(noreplace) %{_sysconfdir}/binfmt.d/kshcomp.conf
|
||||
|
||||
%changelog
|
||||
* Mon May 19 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.10-7
|
||||
- Fix segfault upon SIGWINCH after 'stty -echo'
|
||||
Resolves: RHEL-89866
|
||||
|
||||
* Wed Apr 16 2025 Vincent Mihalkovic <vmihalko@redhat.com> - 3:1.0.10-6
|
||||
- Fix long multibyte characters paste issue via ssh
|
||||
Resolves: RHEL-87564
|
||||
|
||||
Loading…
Reference in New Issue
Block a user