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>