Skip site navigation (1)Skip section navigation (2)
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>