Date: Wed, 7 Oct 1998 08:30:01 -0700 (PDT) From: Graham Wheeler <gram@cdsec.com> To: freebsd-bugs@FreeBSD.ORG Subject: Re: bin/8183: Signal handlers in inetd.c are unsafe Message-ID: <199810071530.IAA01261@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/8183; it has been noted by GNATS. 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 Date: Wed, 7 Oct 1998 17:29:03 +0200 (SAT) > Thank you very much for your problem report. > It has the internal identification `bin/8183'. > The individual assigned to look at your > report is: freebsd-bugs. > > >Category: bin > >Responsible: freebsd-bugs > >Synopsis: Signal handlers in inetd.c are unsafe > >Arrival-Date: Wed Oct 7 03:00:01 PDT 1998 > Here are context diff patches for the sources: diff -r -c /usr/src/usr.sbin/inetd.orig/inetd.8 /usr/src/usr.sbin/inetd/inetd.8 *** /usr/src/usr.sbin/inetd.orig/inetd.8 Wed Oct 7 11:22:45 1998 --- /usr/src/usr.sbin/inetd/inetd.8 Wed Oct 7 11:29:25 1998 *************** *** 32,38 **** .\" from: @(#)inetd.8 8.3 (Berkeley) 4/13/94 .\" $Id: inetd.8,v 1.9.2.6 1998/07/18 11:10:23 jkh Exp $ .\" ! .Dd February 7, 1996 .Dt INETD 8 .Os BSD 4.4 .Sh NAME --- 32,38 ---- .\" from: @(#)inetd.8 8.3 (Berkeley) 4/13/94 .\" $Id: inetd.8,v 1.9.2.6 1998/07/18 11:10:23 jkh Exp $ .\" ! .Dd October 7, 1998 .Dt INETD 8 .Os BSD 4.4 .Sh NAME *************** *** 43,48 **** --- 43,49 ---- .Nm inetd .Op Fl d .Op Fl l + .Op Fl X .Op Fl c Ar maximum .Op Fl C Ar rate .Op Fl a Ar address *************** *** 78,83 **** --- 79,86 ---- Turn on debugging. .It Fl l Turn on logging. + .It Fl X + Enable the extended config file format. .It Fl c Ar maximum Specify the default maximum number of services that can be invoked. May be overridden on a per-service basis with the "max-child" *************** *** 116,121 **** --- 119,133 ---- server program server program arguments .Ed + .Pp + If the + .Fl X + option is given, then each entry has an additional initial field, + which is the numeric IP address to which the listening socket should + be bound. The special value `any' causes the socket to be bound to + INADDR_ANY (the same as if the + .Fl X + option was not given). .Pp To specify an .No Tn "ONC RPC" Ns -based diff -r -c /usr/src/usr.sbin/inetd.orig/inetd.c /usr/src/usr.sbin/inetd/inetd.c *** /usr/src/usr.sbin/inetd.orig/inetd.c Tue Oct 6 16:04:43 1998 --- /usr/src/usr.sbin/inetd/inetd.c Wed Oct 7 17:17:00 1998 *************** *** 162,167 **** --- 162,168 ---- int debug = 0; int log = 0; + int extended_format = 0; int nsock, maxsock; fd_set allsock; int options; *************** *** 172,177 **** --- 173,179 ---- struct servent *sp; struct rpcent *rpc; struct in_addr bind_address; + int signalpipe[2]; struct servtab { char *se_service; /* name of service */ *************** *** 217,223 **** 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 daytime_dg __P((int, struct servtab *)); void daytime_stream __P((int, struct servtab *)); void discard_dg __P((int, struct servtab *)); --- 219,227 ---- void chargen_dg __P((int, struct servtab *)); void chargen_stream __P((int, struct servtab *)); void close_sep __P((struct servtab *)); ! 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,243 **** char *nextline __P((FILE *)); void print_service __P((char *, struct servtab *)); void addchild __P((struct servtab *, int)); ! void reapchild __P((int)); void enable __P((struct servtab *)); void disable __P((struct servtab *)); ! void retry __P((int)); int setconfig __P((void)); void setup __P((struct servtab *)); char *sskip __P((char **)); --- 238,249 ---- char *nextline __P((FILE *)); void print_service __P((char *, struct servtab *)); void addchild __P((struct servtab *, int)); ! void flag_reapchild __P((int)); ! void reapchild __P((void)); void enable __P((struct servtab *)); void disable __P((struct servtab *)); ! void flag_retry __P((int)); ! void retry __P((void)); int setconfig __P((void)); void setup __P((struct servtab *)); char *sskip __P((char **)); *************** *** 336,342 **** openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); bind_address.s_addr = htonl(INADDR_ANY); ! while ((ch = getopt(argc, argv, "dlR:a:c:C:p:")) != -1) switch(ch) { case 'd': debug = 1; --- 342,348 ---- openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); bind_address.s_addr = htonl(INADDR_ANY); ! while ((ch = getopt(argc, argv, "dlXR:a:c:C:p:")) != -1) switch(ch) { case 'd': debug = 1; *************** *** 345,350 **** --- 351,359 ---- case 'l': log = 1; break; + case 'X': + extended_format = 1; + break; case 'R': getvalue(optarg, &toomany, "-R %s: bad value for service invocation rate"); *************** *** 408,419 **** sigaddset(&sa.sa_mask, SIGALRM); sigaddset(&sa.sa_mask, SIGCHLD); sigaddset(&sa.sa_mask, SIGHUP); ! sa.sa_handler = retry; sigaction(SIGALRM, &sa, (struct sigaction *)0); ! config(SIGHUP); ! sa.sa_handler = config; sigaction(SIGHUP, &sa, (struct sigaction *)0); ! sa.sa_handler = reapchild; sigaction(SIGCHLD, &sa, (struct sigaction *)0); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, &sapipe); --- 417,428 ---- sigaddset(&sa.sa_mask, SIGALRM); sigaddset(&sa.sa_mask, SIGCHLD); sigaddset(&sa.sa_mask, SIGHUP); ! sa.sa_handler = flag_retry; sigaction(SIGALRM, &sa, (struct sigaction *)0); ! config(); ! sa.sa_handler = flag_config; sigaction(SIGHUP, &sa, (struct sigaction *)0); ! sa.sa_handler = flag_reapchild; sigaction(SIGCHLD, &sa, (struct sigaction *)0); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, &sapipe); *************** *** 428,433 **** --- 437,450 ---- (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,452 **** --- 464,504 ---- } 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,650 **** --- 697,716 ---- } /* + * 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,679 **** */ void ! reapchild(signo) int signo; { int k, status; pid_t pid; struct servtab *sep; --- 737,751 ---- */ void ! flag_reapchild(signo) int signo; { + flag_signal('C'); + } + + void + reapchild() + { int k, status; pid_t pid; struct servtab *sep; *************** *** 703,711 **** } void ! config(signo) int signo; { struct servtab *sep, *new, **sepp; long omask; --- 775,788 ---- } void ! flag_config(signo) int signo; { + flag_signal('H'); + } + + void config() + { struct servtab *sep, *new, **sepp; long omask; *************** *** 739,745 **** #endif for (sep = servtab; sep; sep = sep->se_next) if (strcmp(sep->se_service, new->se_service) == 0 && ! strcmp(sep->se_proto, new->se_proto) == 0) break; if (sep != 0) { int i; --- 816,825 ---- #endif for (sep = servtab; sep; sep = sep->se_next) if (strcmp(sep->se_service, new->se_service) == 0 && ! strcmp(sep->se_proto, new->se_proto) == 0 && ! (!extended_format || ! sep->se_ctrladdr.sin_addr.s_addr == ! new->se_ctrladdr.sin_addr.s_addr)) break; if (sep != 0) { int i; *************** *** 802,808 **** } if (sp->s_port != sep->se_ctrladdr.sin_port) { sep->se_ctrladdr.sin_family = AF_INET; ! sep->se_ctrladdr.sin_addr = bind_address; sep->se_ctrladdr.sin_port = sp->s_port; if (sep->se_fd >= 0) close_sep(sep); --- 882,889 ---- } if (sp->s_port != sep->se_ctrladdr.sin_port) { sep->se_ctrladdr.sin_family = AF_INET; ! if (!extended_format) ! sep->se_ctrladdr.sin_addr = bind_address; sep->se_ctrladdr.sin_port = sp->s_port; if (sep->se_fd >= 0) close_sep(sep); *************** *** 882,890 **** } void ! retry(signo) int signo; { struct servtab *sep; timingout = 0; --- 963,977 ---- } void ! flag_retry(signo) int signo; { + flag_signal('A'); + } + + void + retry() + { struct servtab *sep; timingout = 0; *************** *** 1119,1124 **** --- 1206,1219 ---- /* got an empty line containing just blanks/tabs. */ goto more; } + if (extended_format) + { + if (strcmp(arg, "any") == 0) + sep->se_ctrladdr.sin_addr.s_addr = INADDR_ANY; + else + sep->se_ctrladdr.sin_addr.s_addr = inet_addr(arg); + arg = sskip(&cp); + } if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) { char *c = arg + MUX_LEN; if (*c == '+') { *************** *** 1160,1166 **** sep->se_rpc_lowvers = 0; sep->se_ctrladdr.sin_family = AF_INET; sep->se_ctrladdr.sin_port = 0; ! sep->se_ctrladdr.sin_addr = bind_address; if ((versp = rindex(sep->se_service, '/'))) { *versp++ = '\0'; switch (sscanf(versp, "%d-%d", --- 1255,1262 ---- sep->se_rpc_lowvers = 0; sep->se_ctrladdr.sin_family = AF_INET; sep->se_ctrladdr.sin_port = 0; ! if (!extended_format) ! sep->se_ctrladdr.sin_addr = bind_address; if ((versp = rindex(sep->se_service, '/'))) { *versp++ = '\0'; switch (sscanf(versp, "%d-%d", -- 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?199810071530.IAA01261>