Subject: bin/18652: inetd(8) signal handlers are not async-signal-safe
To: None <gnats-bugs@gnats.netbsd.org>
From: None <ryany@pobox.com>
List: netbsd-bugs
Date: 10/13/2002 23:59:23
>Number: 18652
>Category: bin
>Synopsis: inetd(8) signal handlers are not async-signal-safe
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Oct 13 21:00:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator: Ryan Younce
>Release: NetBSD 1.6I
>Organization:
>Environment:
System: NetBSD rdu57-072-122.nc.rr.com 1.6I NetBSD 1.6I (DORMOUSE) #0: Sun Oct 13 06:38:37 EDT 2002 root@rdu57-072-122.nc.rr.com:/usr/src/sys/arch/i386/compile/DORMOUSE i386
Architecture: i386
Machine: i386
$NetBSD: inetd.c,v 1.84 2002/09/19 21:59:03 mycroft Exp $
>Description:
The current implementation of inetd uses signal handlers which
call functions that are not defined to be asynchronous signal safe.
>How-To-Repeat:
Unknown or difficult.
>Fix:
This solution implements volatile signal flags which are set in the
signal handler, which then returns. Since a signal will interrupt
an select(2) call (and main() will continue the loop in the event that
select(2) prematurely exited due to a signal), the respective support
function is called at the beginning of the loop's next iteration.
It is difficult to exploit the erroneous behavior or test the
patched version, but the following should theoretically make inetd
immune to any asynchronous side effects due to signal handling.
Index: inetd.c
===================================================================
RCS file: /cvsroot/basesrc/usr.sbin/inetd/inetd.c,v
retrieving revision 1.84
diff -u -r1.84 inetd.c
--- inetd.c 2002/09/19 21:59:03 1.84
+++ inetd.c 2002/10/14 03:31:14
@@ -282,6 +282,12 @@
char *curdom;
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
+/* Signal flags */
+volatile sig_atomic_t do_retry;
+volatile sig_atomic_t do_config;
+volatile sig_atomic_t do_reapchild;
+volatile sig_atomic_t do_goaway;
+
#ifndef OPEN_MAX
#define OPEN_MAX 64
#endif
@@ -373,6 +379,10 @@
void run_service __P((int, struct servtab *));
int setconfig __P((void));
void setup __P((struct servtab *));
+void signal_config __P((int));
+void signal_goaway __P((int));
+void signal_reapchild __P((int));
+void signal_retry __P((int));
char *sskip __P((char **));
char *skip __P((char **));
void tcpmux __P((int, struct servtab *));
@@ -489,18 +499,23 @@
}
#endif
+ do_retry = 0;
+ do_config = 0;
+ do_reapchild = 0;
+ do_goaway = 0;
+
memset(&sv, 0, sizeof(sv));
sv.sv_mask = SIGBLOCK;
- sv.sv_handler = retry;
+ sv.sv_handler = signal_retry;
sigvec(SIGALRM, &sv, (struct sigvec *)0);
config(SIGHUP);
- sv.sv_handler = config;
+ sv.sv_handler = signal_config;
sigvec(SIGHUP, &sv, (struct sigvec *)0);
- sv.sv_handler = reapchild;
+ sv.sv_handler = signal_reapchild;
sigvec(SIGCHLD, &sv, (struct sigvec *)0);
- sv.sv_handler = goaway;
+ sv.sv_handler = signal_goaway;
sigvec(SIGTERM, &sv, (struct sigvec *)0);
- sv.sv_handler = goaway;
+ sv.sv_handler = signal_goaway;
sigvec(SIGINT, &sv, (struct sigvec *)0);
sv.sv_mask = 0L;
sv.sv_handler = SIG_IGN;
@@ -510,6 +525,23 @@
int n, ctrl;
fd_set readable;
+ if (do_retry) {
+ retry(do_retry);
+ do_retry = 0;
+ }
+ if (do_config) {
+ config(do_config);
+ do_config = 0;
+ }
+ if (do_reapchild) {
+ reapchild(do_reapchild);
+ do_reapchild = 0;
+ }
+ if (do_goaway) {
+ goaway(do_goaway);
+ do_goaway = 0;
+ }
+
if (nsock == 0) {
(void) sigblock(SIGBLOCK);
while (nsock == 0)
@@ -741,6 +773,33 @@
recv(ctrl, buf, sizeof (buf), 0);
_exit(1);
}
+}
+
+void
+signal_retry(signo)
+ int signo;
+{
+ do_retry = signo;
+}
+
+void
+signal_config(signo)
+ int signo;
+{
+ do_config = signo;
+}
+
+void
+signal_reapchild(signo)
+ int signo;
+{
+ do_reapchild = signo;
+}
+
+void
+signal_goaway(signo)
+{
+ do_goaway = signo;
}
void
>Release-Note:
>Audit-Trail:
>Unformatted:
As of NetBSD-current 10/13/2002