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