Date: Wed, 7 Oct 1998 17:29:03 +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: <199810071529.RAA05457@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
> 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?199810071529.RAA05457>
