Debian Bug report logs -
#326709
libgpm can bomb the stack hooking to its own signal handlers
Reported by: Ron <ron@debian.org>
Date: Mon, 5 Sep 2005 08:33:02 UTC
Severity: important
Tags: patch
Found in versions gpm/1.19.6-21, gpm/1.20.4-2
Reply or subscribe to this bug.
Toggle useless messages
Report forwarded to debian-bugs-dist@lists.debian.org, Debian GPM Team <pkg-gpm-devel@lists.alioth.debian.org>:
Bug#326709; Package gpm.
(full text, mbox, link).
Acknowledgement sent to Ron <ron@debian.org>:
New Bug report received and forwarded. Copy sent to Debian GPM Team <pkg-gpm-devel@lists.alioth.debian.org>.
(full text, mbox, link).
Message #5 received at submit@bugs.debian.org (full text, mbox, reply):
Package: gpm
Version: 1.19.6-21
Severity: important
Tags: patch
Hi,
libgpm tries to hook to an existing signal handler for
SIGWINCH and SIGSTP, but doesn't check if its own handler
is already installed.
ncurses now loads libgpm dynamically if available and
would seem to call Gpm_Open more than once. This leads
to libgpm hooking to its own handler and a stack bomb
when the signal is next raised.
The following code demonstrates the problem:
#include <stdlib.h>
#include <signal.h>
#include <ncurses.h>
main()
{
initscr();
mousemask( ALL_MOUSE_EVENTS, NULL );
printw("Hello World !!!");
refresh();
getch();
raise( SIGWINCH );
endwin();
return EXIT_SUCCESS;
}
Build with:
$ LDFLAGS="-lncurses" make demo.c
It will segfault if run in a console controlled by gpm.
The following patch addresses it. I may NMU shortly applying
only this change as debian/patches/060_dont_hook_our_own_hook
unless requested to do otherwise.
cheers,
Ron
--- gpm-1.19.6/src/liblow.c.orig 2005-09-05 16:29:34.000000000 +0930
+++ gpm-1.19.6/src/liblow.c 2005-09-05 17:09:21.000000000 +0930
@@ -353,28 +353,40 @@
{
/* itz Wed Dec 16 23:22:16 PST 1998 use sigaction, the old
code caused a signal loop under XEmacs */
- struct sigaction sa;
+ struct sigaction sa, snow;
sigemptyset(&sa.sa_mask);
+ /* We must check if the signals have already been hooked by
+ * this routine, else they will hook back to themselves and
+ * bomb the stack the first time one is raised. */
+
#if (defined(SIGWINCH))
/* And the winch hook .. */
- sa.sa_handler = gpm_winch_hook;
- sa.sa_flags = 0;
- sigaction(SIGWINCH, &sa, &gpm_saved_winch_hook);
+ if (sigaction(SIGWINCH, NULL, &snow) == 0
+ && snow.sa_handler != gpm_winch_hook )
+ {
+ sa.sa_handler = gpm_winch_hook;
+ sa.sa_flags = 0;
+ sigaction(SIGWINCH, &sa, &gpm_saved_winch_hook);
+ }
#endif
#if (defined(SIGTSTP))
if (gpm_flag == 1) {
- /* Install suspend hook */
- sa.sa_handler = SIG_IGN;
- sigaction(SIGTSTP, &sa, &gpm_saved_suspend_hook);
-
- /* if signal was originally ignored, job control is not supported */
- if (gpm_saved_suspend_hook.sa_handler != SIG_IGN) {
- sa.sa_flags = SA_NOMASK;
- sa.sa_handler = gpm_suspend_hook;
- sigaction(SIGTSTP, &sa, 0);
- } /*if*/
+ if (sigaction(SIGTSTP, NULL, &snow) == 0
+ && snow.sa_handler != gpm_suspend_hook )
+ {
+ /* Install suspend hook */
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGTSTP, &sa, &gpm_saved_suspend_hook);
+
+ /* if signal was originally ignored, job control is not supported */
+ if (gpm_saved_suspend_hook.sa_handler != SIG_IGN) {
+ sa.sa_flags = SA_NOMASK;
+ sa.sa_handler = gpm_suspend_hook;
+ sigaction(SIGTSTP, &sa, 0);
+ } /*if*/
+ }
} /*if*/
#endif
-- System Information:
Debian Release: testing/unstable
APT prefers unstable
APT policy: (500, 'unstable')
Architecture: i386 (i686)
Shell: /bin/sh linked to /bin/bash
Kernel: Linux 2.6.12
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Versions of packages gpm depends on:
ii debconf [debconf-2.0] 1.4.58 Debian configuration management sy
ii debianutils 2.14.3 Miscellaneous utilities specific t
ii libc6 2.3.5-6 GNU C Library: Shared libraries an
ii ucf 2.001 Update Configuration File: preserv
gpm recommends no packages.
-- debconf information excluded
Information forwarded to debian-bugs-dist@lists.debian.org, Debian GPM Team <pkg-gpm-devel@lists.alioth.debian.org>:
Bug#326709; Package gpm.
(full text, mbox, link).
Acknowledgement sent to Ron <ron@debian.org>:
Extra info received and forwarded to list. Copy sent to Debian GPM Team <pkg-gpm-devel@lists.alioth.debian.org>.
(full text, mbox, link).
Message #10 received at 326709@bugs.debian.org (full text, mbox, reply):
Ok. With reference to IRC discussion with peterS, here is a patch
that supersedes the one I posted earlier and which covers a couple
of extra things.
- Don't explicitly initialise globals to their default value.
- Handle hooking to both sa_sigaction and sa_handler.
- use the gpm_flag to guard against multiple addition of the
SIGWINCH handler when Gpm_Open is called more than once.
Note: I didn't add a new flag for that after all, gpm_flag
seems to have been designed to ensure Gpm_Close must be called
the same number of times as Open, which does seem like what we
want if both lib(s) and app may open it explicitly.
There may still be other things that need to be wrapped in that
unrelated to signal handling.
- refactor the install_suspend_handler logic, getting rid of a
bunch of redundant logic in Gpm_Open, and addressing a problem
we didn't discuss yet in gpm_suspend_hook -- where if the SIGSTP
handler that was hooked to removed itself when called, or hooked
something else in etc. then we would blindly re hook to its old
state when control returned to gpm, leaving a new bomb for the
next time that signal was raised. Now we more cleanly pop our
handler off the chain before re-raising the signal, and push
it back on when things return.
tested locally as debian/patches/060_signal_hook_bomb
Time for me to get some sleep too though, poke me in the morning
if this raises any new questions. Mostly its just "sliding tile
puzzle" changes from where we left discussion earlier.
cheers,
Ron
--- gpm-1.19.6/src/liblow.c.orig 2005-09-05 22:56:14.000000000 +0930
+++ gpm-1.19.6/src/liblow.c 2005-09-05 22:57:06.000000000 +0930
@@ -5,6 +5,7 @@
* Copyright 1994,1995 rubini@linux.it (Alessandro Rubini)
* Copyright (C) 1998 Ian Zimmerman <itz@rahul.net>
* Copyright 2001 Nico Schottelius (nico@schottelius.org)
+ * Copyright 2005 Ron (ron@debian.org)
*
* xterm management is mostly by jtklehto@stekt.oulu.fi (Janne Kukonlehto)
*
@@ -68,23 +69,24 @@
} Gpm_Stst;
/*....................................... Global variables */
-int gpm_flag=0; /* almost unuseful now */
-int gpm_tried=0;
+int gpm_flag; /* open count for Gpm_Open/Gpm_Close */
+int gpm_tried;
int gpm_fd=-1;
-int gpm_hflag=0;
-Gpm_Stst *gpm_stack=NULL;
+int gpm_hflag;
+Gpm_Stst *gpm_stack;
struct timeval gpm_timeout={10,0};
-Gpm_Handler *gpm_handler=NULL;
-void *gpm_data=NULL;
-int gpm_zerobased=0;
-int gpm_visiblepointer=0;
+Gpm_Handler *gpm_handler;
+void *gpm_data;
+int gpm_zerobased;
+int gpm_visiblepointer;
int gpm_mx, gpm_my; /* max x and y (1-based) to fit margins */
unsigned char _gpm_buf[6*sizeof(short)];
unsigned short * _gpm_arg = (unsigned short *)_gpm_buf +1;
int gpm_consolefd=-1; /* used to invoke ioctl() */
-int gpm_morekeys=0;
+int gpm_morekeys;
+
/*-------------------------------------------------------------------*/
static inline int putdata(int where, Gpm_Connect *what)
{
@@ -112,13 +114,16 @@
static struct sigaction gpm_saved_winch_hook;
-static void gpm_winch_hook (int signum)
+static void gpm_winch_hook (int signum, siginfo_t *info, void *ucontext)
{
struct winsize win;
if (SIG_IGN != gpm_saved_winch_hook.sa_handler &&
SIG_DFL != gpm_saved_winch_hook.sa_handler) {
- gpm_saved_winch_hook.sa_handler(signum);
+ if (gpm_saved_winch_hook.sa_flags & SA_SIGINFO)
+ gpm_saved_winch_hook.sa_sigaction(signum, info, ucontext);
+ else
+ gpm_saved_winch_hook.sa_handler(signum);
} /*if*/
if (ioctl(gpm_consolefd, TIOCGWINSZ, &win) == -1) {
return;
@@ -139,12 +144,13 @@
static struct sigaction gpm_saved_suspend_hook;
-static void gpm_suspend_hook (int signum)
+static void install_suspend_handler();
+
+static void gpm_suspend_hook (int signum, siginfo_t *info, void *ucontext)
{
Gpm_Connect gpm_connect;
sigset_t old_sigset;
sigset_t new_sigset;
- struct sigaction sa;
int success;
sigemptyset (&new_sigset);
@@ -167,10 +173,13 @@
/* in bardo here */
/* Reincarnation. Prepare for another death early. */
- sigemptyset(&sa.sa_mask);
- sa.sa_handler = gpm_suspend_hook;
- sa.sa_flags = SA_NOMASK;
- sigaction (SIGTSTP, &sa, 0);
+ /* Note that if the saved handler unplugged itself
+ * while we were gone, then this could still all
+ * fall apart horribly should we try this again,
+ * even with the precautions taken here.
+ * Signal chaining really must be cooperative if
+ * there is any hope of it working reliably. */
+ install_suspend_handler();
/* Pop the gpm stack by closing the useless connection */
/* but do it only when we know we opened one.. */
@@ -178,6 +187,22 @@
Gpm_Close ();
} /*if*/
}
+
+void install_suspend_handler()
+{
+ struct sigaction sa;
+
+ /* if signal was originally ignored, job control is not supported */
+ if (sigaction(SIGTSTP, NULL, &sa) == 0
+ && sa.sa_sigaction != gpm_suspend_hook
+ && sa.sa_handler != SIG_IGN )
+ {
+ sigemptyset(&sa.sa_mask);
+ sa.sa_sigaction = gpm_suspend_hook;
+ sa.sa_flags = SA_NOMASK | SA_SIGINFO;
+ sigaction (SIGTSTP, &sa, &gpm_saved_suspend_hook);
+ }
+}
#endif /* SIGTSTP */
/*-------------------------------------------------------------------*/
@@ -354,28 +379,28 @@
/* itz Wed Dec 16 23:22:16 PST 1998 use sigaction, the old
code caused a signal loop under XEmacs */
struct sigaction sa;
- sigemptyset(&sa.sa_mask);
+
+ /* We must check if the signals have already been hooked by
+ * this routine, else they will hook back to themselves and
+ * bomb the stack the first time one is raised. */
#if (defined(SIGWINCH))
/* And the winch hook .. */
- sa.sa_handler = gpm_winch_hook;
- sa.sa_flags = 0;
- sigaction(SIGWINCH, &sa, &gpm_saved_winch_hook);
+ if (gpm_flag == 1
+ && sigaction(SIGWINCH, NULL, &sa) == 0
+ && sa.sa_sigaction != gpm_winch_hook )
+ {
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = gpm_winch_hook;
+ sigaction(SIGWINCH, &sa, &gpm_saved_winch_hook);
+ }
#endif
#if (defined(SIGTSTP))
- if (gpm_flag == 1) {
- /* Install suspend hook */
- sa.sa_handler = SIG_IGN;
- sigaction(SIGTSTP, &sa, &gpm_saved_suspend_hook);
-
- /* if signal was originally ignored, job control is not supported */
- if (gpm_saved_suspend_hook.sa_handler != SIG_IGN) {
- sa.sa_flags = SA_NOMASK;
- sa.sa_handler = gpm_suspend_hook;
- sigaction(SIGTSTP, &sa, 0);
- } /*if*/
- } /*if*/
+ /* Install suspend hook */
+ if (gpm_flag == 1)
+ install_suspend_handler();
#endif
} /*if*/
Information forwarded to debian-bugs-dist@lists.debian.org, Debian GPM Team <pkg-gpm-devel@lists.alioth.debian.org>:
Bug#326709; Package gpm.
(full text, mbox, link).
Acknowledgement sent to Daniel Jacobowitz <drow@false.org>:
Extra info received and forwarded to list. Copy sent to Debian GPM Team <pkg-gpm-devel@lists.alioth.debian.org>.
(full text, mbox, link).
Message #15 received at 326709@bugs.debian.org (full text, mbox, reply):
To the correct bug report this time...
I'll be uploading ncurses 5.5-1 shortly, which includes a change to only
call Gpm_Open once. I'm not going to close this bug, though, since it would
probably be good to fix in GPM too.
--
Daniel Jacobowitz
CodeSourcery, LLC
Information forwarded
to debian-bugs-dist@lists.debian.org, Debian GPM Team <pkg-gpm-devel@lists.alioth.debian.org>:
Bug#326709; Package gpm.
(Fri, 26 Sep 2008 19:42:07 GMT) (full text, mbox, link).
Acknowledgement sent
to Florian Kulzer <florian.kulzer+debian@icfo.es>:
Extra info received and forwarded to list. Copy sent to Debian GPM Team <pkg-gpm-devel@lists.alioth.debian.org>.
(Fri, 26 Sep 2008 19:42:07 GMT) (full text, mbox, link).
Message #20 received at 326709@bugs.debian.org (full text, mbox, reply):
Package: gpm
Version: 1.20.4-2
Followup-For: Bug #326709
Hi,
I think this problem may have resurfaced with version 5.6+20080920-1 of
libncursesw5; for example, aptitude now segfaults when I use it in
interactive mode on a tty while gpm is active. Here is the debugging
output:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fc0781126f0 (LWP 7476)]
0x00007fc0778155a0 in cwidget::toplevel::timeout_thread::instance () from /usr/lib/libcwidget.so.3
(gdb) bt
#0 0x00007fc0778155a0 in cwidget::toplevel::timeout_thread::instance () from /usr/lib/libcwidget.so.3
#1 0x00007fc077a341e6 in endwin () from /lib/libncursesw.so.5
#2 0x00007fc0775919aa in cwidget::toplevel::suspend_without_signals () at toplevel.cc:1162
#3 0x00007fc077591b82 in cwidget::toplevel::suspend () at toplevel.cc:1181
#4 0x00007fc077592141 in cwidget::toplevel::shutdown () at toplevel.cc:1192
#5 0x00000000004b3a37 in ui_main () at ui.cc:2764
#6 0x000000000041b4f0 in main (argc=20, argv=0x7fff8013f808) at main.cc:759
Ron's demo code crashes like this:
Hello World !!!
Program received signal SIGSEGV, Segmentation fault.
0x00007fce4e2a8330 in ?? ()
(gdb) bt
#0 0x00007fce4e2a8330 in ?? ()
#1 <signal handler called>
#2 0x00007fce4e6e1ef5 in raise () from /lib/libc.so.6
#3 0x0000000000400845 in main () at demo.c:12
Downgrading libncursesw5 to version 5.6+20080830-1 or disabling the GPM
daemon is sufficient to prevent the segfaults.
Thanks for your time.
-- System Information:
Debian Release: lenny/sid
APT prefers unstable
APT policy: (500, 'unstable'), (500, 'testing'), (500, 'stable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Kernel: Linux 2.6.26-flo (SMP w/2 CPU cores; PREEMPT)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
Versions of packages gpm depends on:
ii debconf [debconf-2.0] 1.5.23 Debian configuration management sy
ii debianutils 2.30 Miscellaneous utilities specific t
ii libc6 2.7-13 GNU C Library: Shared libraries
ii libgpm2 1.20.4-2 General Purpose Mouse - shared lib
ii lsb-base 3.2-20 Linux Standard Base 3.2 init scrip
ii ucf 3.0010 Update Configuration File: preserv
gpm recommends no packages.
gpm suggests no packages.
-- debconf information:
* gpm/responsiveness:
* gpm/repeat_type: none
* gpm/append:
gpm/restart: false
* gpm/sample_rate:
* gpm/type: exps2
* gpm/device: /dev/input/mice
Merged 326709 500103.
Request was from Sven Joachim <svenjoac@gmx.de>
to control@bugs.debian.org.
(Sat, 27 Sep 2008 07:45:06 GMT) (full text, mbox, link).
Disconnected #500103 from all other report(s).
Request was from Sven Joachim <svenjoac@gmx.de>
to control@bugs.debian.org.
(Sat, 27 Sep 2008 17:03:04 GMT) (full text, mbox, link).
Information forwarded
to debian-bugs-dist@lists.debian.org, Debian GPM Team <pkg-gpm-devel@lists.alioth.debian.org>:
Bug#326709; Package gpm.
(Tue, 30 Sep 2008 15:36:03 GMT) (full text, mbox, link).
Acknowledgement sent
to Florian Kulzer <florian.kulzer+debian@icfo.es>:
Extra info received and forwarded to list. Copy sent to Debian GPM Team <pkg-gpm-devel@lists.alioth.debian.org>.
(Tue, 30 Sep 2008 15:36:03 GMT) (full text, mbox, link).
Message #29 received at 326709@bugs.debian.org (full text, mbox, reply):
Package: gpm
Version: 1.20.4-2
Followup-For: Bug #326709
I just want to confirm that my problems stopped after upgrading to
libncursesw5 version 5.6+20080925-1. They seem to have been caused by a
separate issue with ncurses (#500103) after all; sorry for the noise.
Send a report that this bug log contains spam.
Debian bug tracking system administrator <owner@bugs.debian.org>.
Last modified:
Sat Jul 1 15:30:09 2023;
Machine Name:
bembo
Debian Bug tracking system
Debbugs is free software and licensed under the terms of the GNU
Public License version 2. The current version can be obtained
from https://bugs.debian.org/debbugs-source/.
Copyright © 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson,
2005-2017 Don Armstrong, and many other contributors.