Date: Thu, 8 Oct 1998 10:07:31 +0200 (SAT) From: Graham Wheeler <gram@cdsec.com> To: FreeBSD-gnats-submit@FreeBSD.ORG, freebsd-bugs@FreeBSD.ORG Cc: dag-erli@ifi.uio.no Subject: Re: bin/8183: Signal handlers in inetd.c are unsafe Message-ID: <199810080807.KAA07108@cdsec.com> In-Reply-To: <199810071000.DAA13971@freefall.freebsd.org> from "FreeBSD-gnats-submit@FreeBSD.ORG" at Oct 7, 98 03:00:01 am
next in thread | previous in thread | raw e-mail | index | archive | help
SEND-PR: -*- send-pr -*-
SEND-PR: Lines starting with `SEND-PR' will be removed automatically, as
SEND-PR: will all comments (text enclosed in `<' and `>').
SEND-PR:
SEND-PR: Please consult the send-pr man page `send-pr(1)' or the Texinfo
SEND-PR: manual if you are not sure how to fill out a problem report.
SEND-PR:
SEND-PR: Note that the Synopsis field is mandatory. The Subject (for
SEND-PR: the mail) will be made the same as Synopsis unless explicitly
SEND-PR: changed.
SEND-PR:
SEND-PR: Choose from the following categories:
SEND-PR:
SEND-PR: bin conf docs gnu i386 kern misc ports sparc
SEND-PR:
To: FreeBSD-gnats-submit@freebsd.org
Subject:
From: gram@cdsec.com
Reply-To: gram@cdsec.com
X-send-pr-version: 3.2
>Submitter-Id: current-users
>Originator: Graham Wheeler
>Organization: Citadel Data Security
>Confidential: no
>Synopsis: Signal handlers in inetd.c are unsafe
>Severity: serious
>Priority: medium
>Category: bin
>Release: FreeBSD 2.2.7
>Class: sw-bug
>Environment: Not important
>Description: The signal handlers in inetd.c make use of unsafe functions
> such as calls to allocate and free heap memory. This can
> result in heap corruption, which is typically manifested
> by inetd reporting the error message (from malloc or realloc):
>
> junk pointer: too low to make sense
>
>How-To-Repeat: The problem will usually occur if a signal is caught while
> in heap allocation function. The signal handler can also
> call these functions, which are not reentrant. As this is
> timing related, replicating it reliably can be difficult, but
> the problem is well known.
>
>Fix: The following patch fixes the problem, by modifying the signal
> handlers to write character flags to a pipe, and having the main
> select() loop read these flags and call the original handlers.
------------------ cut here ------------------------------------
--- /usr/src/usr.sbin/inetd.orig/inetd.c Tue Oct 6 16:04:43 1998
+++ /usr/src/usr.sbin/inetd/inetd.c Thu Oct 8 09:50:15 1998
@@ -172,6 +172,7 @@
struct servent *sp;
struct rpcent *rpc;
struct in_addr bind_address;
+int signalpipe[2];
struct servtab {
char *se_service; /* name of service */
@@ -217,7 +218,9 @@
void chargen_dg __P((int, struct servtab *));
void chargen_stream __P((int, struct servtab *));
void close_sep __P((struct servtab *));
-void config __P((int));
+void flag_signal __P((char));
+void flag_config __P((int));
+void config __P((void));
void daytime_dg __P((int, struct servtab *));
void daytime_stream __P((int, struct servtab *));
void discard_dg __P((int, struct servtab *));
@@ -234,10 +237,12 @@
char *nextline __P((FILE *));
void print_service __P((char *, struct servtab *));
void addchild __P((struct servtab *, int));
-void reapchild __P((int));
+void flag_reapchild __P((int));
+void reapchild __P((void));
void enable __P((struct servtab *));
void disable __P((struct servtab *));
-void retry __P((int));
+void flag_retry __P((int));
+void retry __P((void));
int setconfig __P((void));
void setup __P((struct servtab *));
char *sskip __P((char **));
@@ -408,12 +413,12 @@
sigaddset(&sa.sa_mask, SIGALRM);
sigaddset(&sa.sa_mask, SIGCHLD);
sigaddset(&sa.sa_mask, SIGHUP);
- sa.sa_handler = retry;
+ sa.sa_handler = flag_retry;
sigaction(SIGALRM, &sa, (struct sigaction *)0);
- config(SIGHUP);
- sa.sa_handler = config;
+ config();
+ sa.sa_handler = flag_config;
sigaction(SIGHUP, &sa, (struct sigaction *)0);
- sa.sa_handler = reapchild;
+ sa.sa_handler = flag_reapchild;
sigaction(SIGCHLD, &sa, (struct sigaction *)0);
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sa, &sapipe);
@@ -428,6 +433,14 @@
(void)setenv("inetd_dummy", dummy, 1);
}
+ if (pipe(signalpipe) != 0)
+ {
+ syslog(LOG_ERR, "pipe: %%m");
+ exit(EX_OSERR);
+ }
+ FD_SET(signalpipe[0], &allsock);
+ if (signalpipe[0]>maxsock) maxsock = signalpipe[0];
+
for (;;) {
int n, ctrl;
fd_set readable;
@@ -447,6 +460,41 @@
}
continue;
}
+ /* handle any queued signal flags */
+ if (FD_ISSET(signalpipe[0], &readable))
+ {
+ int n;
+ if (ioctl(signalpipe[0], FIONREAD, &n) == 0)
+ {
+ while (--n >= 0)
+ {
+ char c;
+ if (read(signalpipe[0], &c, 1) == 1)
+ {
+ if (debug) warnx("Handling signal flag %c", c);
+ switch(c)
+ {
+ case 'A': /* sigalrm */
+ retry(); break;
+ case 'C': /* sigchld */
+ reapchild(); break;
+ case 'H': /* sighup */
+ config(); break;
+ }
+ }
+ else
+ {
+ syslog(LOG_ERR, "read: %m");
+ exit(EX_OSERR);
+ }
+ }
+ }
+ else
+ {
+ syslog(LOG_ERR, "ioctl: %m");
+ exit(EX_OSERR);
+ }
+ }
for (sep = servtab; n && sep; sep = sep->se_next)
if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
n--;
@@ -645,6 +693,20 @@
}
/*
+ * Add a signal flag to the signal flag queue for later handling
+ */
+
+void flag_signal(c)
+ char c;
+{
+ if (write(signalpipe[1], &c, 1) != 1)
+ {
+ syslog(LOG_ERR, "write: %m");
+ exit(EX_OSERR);
+ }
+}
+
+/*
* Record a new child pid for this service. If we've reached the
* limit on children, then stop accepting incoming requests.
*/
@@ -671,9 +733,15 @@
*/
void
-reapchild(signo)
+flag_reapchild(signo)
int signo;
{
+ flag_signal('C');
+}
+
+void
+reapchild()
+{
int k, status;
pid_t pid;
struct servtab *sep;
@@ -703,9 +771,14 @@
}
void
-config(signo)
+flag_config(signo)
int signo;
{
+ flag_signal('H');
+}
+
+void config()
+{
struct servtab *sep, *new, **sepp;
long omask;
@@ -882,8 +955,14 @@
}
void
-retry(signo)
+flag_retry(signo)
int signo;
+{
+ flag_signal('A');
+}
+
+void
+retry()
{
struct servtab *sep;
------------------ cut here ------------------------------------
--
Dr Graham Wheeler E-mail: gram@cdsec.com
Citadel Data Security Phone: +27(21)23-6065/6/7
Internet/Intranet Network Specialists Mobile: +27(83)253-9864
Firewalls/Virtual Private Networks Fax: +27(21)24-3656
Data Security Products WWW: http://www.cdsec.com/
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199810080807.KAA07108>
