From trond@ramstind.gtf.ol.no  Tue Nov  2 15:53:04 2004
Return-Path: <trond@ramstind.gtf.ol.no>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 33BAA16A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Tue,  2 Nov 2004 15:53:04 +0000 (GMT)
Received: from ramstind.gtf.ol.no (ramstind.gtf.ol.no [128.39.174.16])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 2837C43D2D
	for <FreeBSD-gnats-submit@freebsd.org>; Tue,  2 Nov 2004 15:53:03 +0000 (GMT)
	(envelope-from trond@ramstind.gtf.ol.no)
Received: from ramstind.gtf.ol.no (Ximalas@localhost [127.0.0.1])
	by ramstind.gtf.ol.no (8.12.9/8.12.11) with ESMTP id iA2Fqx29051776
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 2 Nov 2004 16:53:01 +0100 (CET)
	(envelope-from trond@ramstind.gtf.ol.no)
Received: (from trond@localhost)
	by ramstind.gtf.ol.no (8.12.9/8.12.3/Submit) id iA2FqwJN051775;
	Tue, 2 Nov 2004 16:52:58 +0100 (CET)
Message-Id: <200411021552.iA2FqwJN051775@ramstind.gtf.ol.no>
Date: Tue, 2 Nov 2004 16:52:58 +0100 (CET)
From: Trond Endrestl <Trond.Endrestol@gtf.ol.no>
Reply-To: Trond Endrestl <Trond.Endrestol@gtf.ol.no>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: portmap forks ad infinitum when the NIS domain name is set, probably a bug in the RPC library
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         73422
>Category:       bin
>Synopsis:       portmap forks ad infinitum when the NIS domain name is set, probably a bug in the RPC library
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Nov 02 16:00:49 GMT 2004
>Closed-Date:    
>Last-Modified:  Tue Apr  4 18:40:17 GMT 2006
>Originator:     Trond Endrestl
>Release:        FreeBSD 4.10-RELEASE i386
>Organization:
Private
>Environment:
>Description:

I'm in the process of setting up NIS in my home and I've found a
problem that I believe resides in the RPC library.  I'm running
4.10-RELEASE and I've followed the instructions in the Handbook.
I've used FreeBSD since 1998, but I have only recently turned my
interest to NIS.

(Speaking of the Handbook, has anyone tried these instructions lately
and verified that you'll actually achieve the goal? Is NIS tested when
a new -RELEASE is rolled out?)

When portmap receives a request, any request, portmap uses the RPC
library to maintain the port mappings.  When the RPC library discovers
the NIS domain name is set, it tries to get the port of the NIS client
(i.e. ypbind).  As a result, if ypbind is not registered, ypbind might
even be in the process of registering with portmap right now, another
portmap process is created to service the request.  The new portmap
process is still using the very same RPC library, which in turn
discovers again the name of the NIS domain and tries to get hold of
the port belonging to the NIS client, and next, the snowball is
rolling and rolling, and soon the system has hundreds, if not
thousands, of portmap processes getting nowhere.

I've changed ypbind slightly so that it does not check the NIS domain
name before checking the command line, see the patch below.
Note: This is a very poor workaround! The real problem is still in the
RPC library.

My computers are all set up to be NIS servers, master or slaves, and
are therefore commanded to bind to themselves.  When the NIS servers
and clients (i.e. ypserv and ypbind) are finally up and running, I can
set the NIS domain name using domainname, and everything is OK unless
ypbind dies.

Should ypbind die, I need to unset the NIS domain name in order not to
trigger this nasty problem in the RPC library, restart ypbind, and set
the NIS domain name again.

Can someone fix the RPC library?  I guess the RPC library shouldn't
create and post requests on its own when processing other requests.

If no one corrects the RPC library, then part of the Handbook should
be rewritten, at least make a note that the RPC system, and thus NIS,
is broken.  RPC and NFS is still working though.

>How-To-Repeat:

Run portmap with a NIS domain name set, and try engaging portmap
by the use of rpcinfo, mountd, nfsd, whatever.

>Fix:

Patch for ypbind.c follows:

*** ypbind.c.orig	Fri Feb 15 01:46:59 2002
--- ypbind.c	Tue Nov  2 13:47:58 2004
***************
*** 403,413 ****
  	if (flock(yplockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK)
  		errx(1, "another ypbind is already running. Aborting");
  
- 	/* XXX domainname will be overriden if we use restricted mode */
- 	yp_get_default_domain(&domain_name);
- 	if (domain_name[0] == '\0')
- 		errx(1, "domainname not set. Aborting");
- 
  	for (i = 1; i<argc; i++) {
  		if (strcmp("-ypset", argv[i]) == 0)
  			ypsetmode = YPSET_ALL;
--- 403,408 ----
***************
*** 419,424 ****
--- 414,426 ----
  			yp_restricted_mode(argv[i+1]);
  		else if (strcmp("-m", argv[i]) == 0)
  			yp_manycast++;
+ 	}
+ 
+ 	if (domain_name == NULL || domain_name[0] == '\0') {
+ 		/* XXX domainname will be overriden if we use restricted mode */
+ 		yp_get_default_domain(&domain_name);
+ 		if (domain_name[0] == '\0')
+ 			errx(1, "domainname not set. Aborting");
  	}
  
  	/* blow away everything in BINDINGDIR (if it exists) */

>Release-Note:
>Audit-Trail:

From: =?ISO-8859-1?Q?Trond_Endrest=F8l?= <Trond.Endrestol@gtf.ol.no>
To: FreeBSD-gnats-submit@freebsd.org
Cc:  
Subject: Re: bin/73422: portmap forks ad infinitum when the NIS domain name
 is set, probably a bug in the RPC library
Date: Fri, 12 Nov 2004 14:42:45 +0100 (CET)

 This is a followup to the original PR.  I have done some further
 investigations and believe to have isolated the problem.
 
 >Submitter-Id:	current-users
 >Originator:	Trond Endrestl
 >Organization:	Private
 >Confidential:	no
 >Synopsis:	portmap forks ad infinitum if verbose logging is turned on and NIS domainname is set
 >Severity:	serious
 >Priority:	high
 >Category:	bin
 >Class:		sw-bug
 >Release:	FreeBSD 4.10-RELEASE i386
 >Environment:
 System: FreeBSD sovereign.bsd.net 4.10-RELEASE FreeBSD 4.10-RELEASE #0: Fri Oct 22 22:31:31 CEST 2004 root@sovereign.bsd.net:/usr/src/sys/compile/SOVEREIGN i386
 
 
 	Pentium 133 MHz running FreeBSD 4.10-RELEASE
 >Description:
 	1. If portmap is running with verbose logging (-v) and the NIS
 	   domain name is set, it will try to resolve RPC program numbers
 	   into names using getrpcbynumber() in logit() in pmap_check.c
 
 	2. This results in a new request to portmap about the port number
 	   for ypbind.  ypbind may not have registered yet with portmap,
 	   and due to the verbose logging, portmap attempts another call
 	   to getrpcbynumber(). As portmap does the logging by forking
 	   a child to do the work, this leads to hundreds, if not
 	   thousands, of portmap processes getting nowhere.
 
 	3. End result is a utmost slow system, with a non-functioning
 	   portmapper, and a system in desperate need of operator attention.
 >How-To-Repeat:
 	Run portmap with verbose logging turned on (-v) and
 	with the NIS domain name set to a valid value
 	(e.g. nisdomainname="blah.blah.blah").
 >Fix:
 
 	Simplest solution:
 
 	Advice users to run portmap without verbose logging if running NIS.
 	I.e., make a point of this in the FreeBSD Handbook if nothing
 	further is done to correct the issue.
 
 
 	A better solution:
 
 	Change ypbind to check the NIS domain name after processing
 	the command line.  The domain name may have been set by using
 	-S domain,nisserver1,nisserver2,...
 	See patch below for ypbind.c.
 
 	Change portmap not to resolve RPC program numbers into names
 	when doing verbose logging.  See patch below for pmap_check.c.
 	If possible to resolve RPC program numbers using something
 	other than NIS even if the NIS domain name is set, use that
 	approach.
 
 	Change /etc/rc.network to unset the NIS domain name early in
 	network_pass1().  This helps if the user recently went from
 	multiuser mode to single user mode, and wants to go back
 	to multiuser mode.  Otherwise, programs such as named tries to
 	contact portmap and may suspend the booting process for
 	a minute or so.  Let /etc/rc.network set the NIS domain name
 	just prior to launching ypserv and other NIS related servers.
 	See patch below for /etc/rc.network.
 
 	If nothing is done with pmap_check.c as described above,
 	still let /etc/rc.network unset the NIS domain name at
 	the beginning of execution, and set the NIS domain name after
 	ypbind is launched.  Programs such as rpc.yppasswdd and ypbind
 	need to be told the NIS domain name using command line
 	options.
 
 	Patches follows:
 
 *** ypbind.c.orig	Fri Feb 15 01:46:59 2002
 --- ypbind.c	Tue Nov  2 15:54:05 2004
 ***************
 *** 403,413 ****
   	if (flock(yplockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK)
   		errx(1, "another ypbind is already running. Aborting");
 
 - 	/* XXX domainname will be overriden if we use restricted mode */
 - 	yp_get_default_domain(&domain_name);
 - 	if (domain_name[0] == '\0')
 - 		errx(1, "domainname not set. Aborting");
 -
   	for (i = 1; i<argc; i++) {
   		if (strcmp("-ypset", argv[i]) == 0)
   			ypsetmode = YPSET_ALL;
 --- 403,408 ----
 ***************
 *** 419,424 ****
 --- 414,426 ----
   			yp_restricted_mode(argv[i+1]);
   		else if (strcmp("-m", argv[i]) == 0)
   			yp_manycast++;
 + 	}
 +
 + 	if (domain_name == NULL || domain_name[0] == '\0') {
 + 		/* XXX domainname will be overriden if we use restricted mode */
 + 		yp_get_default_domain(&domain_name);
 + 		if (domain_name[0] == '\0')
 + 			errx(1, "domainname not set. Aborting");
   	}
 
   	/* blow away everything in BINDINGDIR (if it exists) */
 
 *** pmap_check.c.orig	Sun Jan 16 00:08:28 2000
 --- pmap_check.c	Fri Nov 12 12:32:35 2004
 ***************
 *** 238,246 ****
 
   	if (prognum == 0) {
   	    progname = "";
 ! 	} else if ((rpc = getrpcbynumber((int) prognum))) {
   	    progname = rpc->r_name;
 ! 	} else {
   	    sprintf(progbuf, "%lu", prognum);
   	    progname = progbuf;
   	}
 --- 238,246 ----
 
   	if (prognum == 0) {
   	    progname = "";
 ! 	} /* else if ((rpc = getrpcbynumber((int) prognum))) {
   	    progname = rpc->r_name;
 ! 	} */ else {
   	    sprintf(progbuf, "%lu", prognum);
   	    progname = progbuf;
   	}
 
 *** rc.network.orig	Tue May 25 23:28:42 2004
 --- rc.network	Fri Nov 12 13:38:42 2004
 ***************
 *** 133,148 ****
   		;;
   	esac
 
 ! 	# Set the domainname if we're using NIS
   	#
 ! 	case ${nisdomainname} in
 ! 	[Nn][Oo] | '')
 ! 		;;
 ! 	*)
 ! 		domainname ${nisdomainname}
 ! 		echo -n ' domain'
 ! 		;;
 ! 	esac
 
   	echo '.'
 
 --- 133,142 ----
   		;;
   	esac
 
 ! 	# Unset the domainname, it will be set later if requested
   	#
 ! 	domainname ''
 ! 	echo -n ' domain (unset)'
 
   	echo '.'
 
 ***************
 *** 579,584 ****
 --- 573,589 ----
   	case ${portmap_enable} in
   	[Yy][Ee][Ss])
   		echo -n ' portmap';	${portmap_program:-/usr/sbin/portmap} ${portmap_flags}
 + 		;;
 + 	esac
 +
 + 	# Set the domainname if we're using NIS
 + 	#
 + 	case ${nisdomainname} in
 + 	[Nn][Oo] | '')
 + 		;;
 + 	*)
 + 		domainname ${nisdomainname}
 + 		echo -n " domain (${nisdomainname})"
   		;;
   	esac
 
 -- 
 ----------------------------------------------------------------------
 Trond Endrestl                          |    trond@ramstind.gtf.ol.no
 Patron of The Art of Computer Programming|   FreeBSD 4.8-S & Pine 4.55

From: Kai <kai@xs4all.nl>
To: bug-followup@FreeBSD.org, Trond.Endrestol@gtf.ol.no
Cc:  
Subject: Re: bin/73422: portmap forks ad infinitum when the NIS domain name is set, probably a bug in the RPC library
Date: Wed, 3 Aug 2005 15:12:38 +0200

 Hello,
 
 We're having trouble with our nis servers running in the same problems as
 the above problems, though we are running *without* the -v option.
 
 Having a look at the endless problem reports on portmap I can only come
 to the conclusioin that one shouldn't try to do any conversion of
 portnumbers to names in the logit() function. Or even, which flabbergasted
 me even more, a call to getnameinfo() in freebsd5's rpcbind.
 
 I surely can see that one can stall the process on purpose this way.
 
 The thing is that this only triggers when a lot of logging is done. Ofcourse
 "a lot of logging" isn't supposed to happen that often, but when it does,
 as with the '-v' option, it triggers this bug.
 
 I therefore suggest the following patches to rpcbind in
 usr.sbin/rpcbind/security.c, and the almost identical patch to portmap in
 usr.sbin/portmap/pmap_check.c.
 
 Regards,
 
 Kai Storbeck
 XS4ALL Internet
 
 --- security.c.orig     Wed Aug  3 14:48:24 2005
 +++ security.c  Wed Aug  3 14:59:03 2005
 @@ -165,7 +165,7 @@
         char    procbuf[32];
         char   *progname;
         char    progbuf[32];
 -       char fromname[NI_MAXHOST];
 +       /* char fromname[NI_MAXHOST]; */
         struct rpcent *rpc;
         static const char *procmap[] = {
         /* RPCBPROC_NULL */             "null",
 @@ -195,8 +195,9 @@
  
                 if (prognum == 0) {
                         progname = "";
 -               } else if ((rpc = getrpcbynumber((int) prognum))) {
 -                       progname = rpc->r_name;
 +               /* } else if ((rpc = getrpcbynumber((int) prognum))) {
 +                *      progname = rpc->r_name;
 +                */
                 } else {
                         snprintf(progname = progbuf, sizeof(progbuf), "%u",
                             (unsigned)prognum);
 @@ -213,14 +214,15 @@
  
                 /* Write syslog record. */
  
 -               if (addr->sa_family == AF_LOCAL)
 -                       strcpy(fromname, "local");
 -               else
 -                       getnameinfo(addr, addr->sa_len, fromname,
 -                           sizeof fromname, NULL, 0, NI_NUMERICHOST);
 +               /* if (addr->sa_family == AF_LOCAL)
 +                *      strcpy(fromname, "local");
 +                * else
 +                *      getnameinfo(addr, addr->sa_len, fromname,
 +                *          sizeof fromname, NULL, 0, NI_NUMERICHOST);
 +                */
  
                 syslog(severity, "connect from %s to %s(%s)%s",
 -                       fromname, procname, progname, text);
 +                       inet_ntoa(addr->sin_addr), procname, progname,
 text);
                 _exit(0);
         }
  }
 
 
 
 --- pmap_check.c.orig   Wed Aug  3 15:00:28 2005
 +++ pmap_check.c        Wed Aug  3 15:02:37 2005
 @@ -238,8 +238,9 @@
  
         if (prognum == 0) {
             progname = "";
 -       } else if ((rpc = getrpcbynumber((int) prognum))) {
 -           progname = rpc->r_name;
 +       /* } else if ((rpc = getrpcbynumber((int) prognum))) {
 +        *    progname = rpc->r_name;
 +        */
         } else {
             sprintf(progbuf, "%lu", prognum);
             progname = progbuf;

From: linimon@lonesome.com (Mark Linimon)
To: bug-followup@FreeBSD.org
Cc: Mark Linimon <linimon@lonesome.com>
Subject: Re: bin/73422 : portmap forks ad infinitum when the NIS domain name is set, probably a bug in the RPC library
Date: Tue, 4 Apr 2006 13:31:54 -0500

 Forwarding from a post to -stable:
 
 ----- Forwarded message from Trond Endrestl <Trond.Endrestol@fagskolen.gjovik.no> -----
 
 I took a look at 6.1-PRE to see if the nasty NIS bugs are still present, and
 I believe they are.
 
 I present the following four patches and I hope you'll consider making
 them part of the upcoming 6.1-RELEASE.
 
 Trond Endrestl.
 
 ----
 
 *** /etc/rc.d/nisdomain.orig	Wed Feb  1 21:43:28 2006
 --- /etc/rc.d/nisdomain	Mon Mar 27 08:30:07 2006
 ***************
 *** 34,40 ****
 
   name="nisdomain"
   start_cmd="nisdomain_start"
 ! stop_cmd=":"
 
   nisdomain_start()
   {
 --- 34,40 ----
 
   name="nisdomain"
   start_cmd="nisdomain_start"
 ! stop_cmd="nisdomain_stop"
 
   nisdomain_start()
   {
 ***************
 *** 48,53 ****
 --- 48,61 ----
   		echo "Setting NIS domain: `/bin/domainname`."
   		;;
   	esac
 + }
 +
 + nisdomain_stop()
 + {
 + 	# Unset the domainname in any case
 + 	#
 + 	domainname ''
 + 	echo "Unsetting NIS domain."
   }
 
   load_rc_config $name
 
 *** /usr/src/usr.sbin/rpcbind/Makefile.orig	Thu Mar 16 21:52:31 2006
 --- /usr/src/usr.sbin/rpcbind/Makefile	Tue Mar 28 16:47:41 2006
 ***************
 *** 19,24 ****
 --- 19,28 ----
   CFLAGS+= -DINET6
   .endif
 
 + .if defined(NO_NIS)
 + CFLAGS+= -DNO_NIS
 + .endif
 +
   DPADD=	${LIBWRAP} ${LIBUTIL}
   LDADD=	-lwrap -lutil
 
 *** /usr/src/usr.sbin/rpcbind/security.c.orig	Mon Dec 16 23:24:26 2002
 --- /usr/src/usr.sbin/rpcbind/security.c	Tue Mar 28 16:52:21 2006
 ***************
 *** 165,171 ****
 --- 165,173 ----
   	char	procbuf[32];
   	char   *progname;
   	char	progbuf[32];
 + #ifdef NO_NIS
   	char fromname[NI_MAXHOST];
 + #endif
   	struct rpcent *rpc;
   	static const char *procmap[] = {
   	/* RPCBPROC_NULL */		"null",
 ***************
 *** 193,198 ****
 --- 195,201 ----
 
   		/* Try to map program number to name. */
 
 + #ifdef NO_NIS
   		if (prognum == 0) {
   			progname = "";
   		} else if ((rpc = getrpcbynumber((int) prognum))) {
 ***************
 *** 201,206 ****
 --- 204,217 ----
   			snprintf(progname = progbuf, sizeof(progbuf), "%u",
   			    (unsigned)prognum);
   		}
 + #else
 + 		if (prognum == 0) {
 + 			progname = "";
 + 		} else {
 + 			snprintf(progname = progbuf, sizeof(progbuf), "%u",
 + 			    (unsigned)prognum);
 + 		}
 + #endif
 
   		/* Try to map procedure number to name. */
 
 ***************
 *** 213,226 ****
 --- 224,244 ----
 
   		/* Write syslog record. */
 
 + #ifdef NO_NIS
   		if (addr->sa_family == AF_LOCAL)
   			strcpy(fromname, "local");
   		else
   			getnameinfo(addr, addr->sa_len, fromname,
   			    sizeof fromname, NULL, 0, NI_NUMERICHOST);
 + #endif
 
 + #ifdef NO_NIS
   		syslog(severity, "connect from %s to %s(%s)%s",
   			fromname, procname, progname, text);
 + #else
 + 		syslog(severity, "connect from %s to %s(%s)%s",
 + 			inet_ntoa(((struct sockaddr_in *)addr)->sin_addr), procname, progname, text);
 + #endif
   		_exit(0);
   	}
   }
 
 *** /usr/src/usr.sbin/ypbind/ypbind.c.orig	Sun Oct 17 21:33:33 2004
 --- /usr/src/usr.sbin/ypbind/ypbind.c	Mon Mar 27 08:23:09 2006
 ***************
 *** 388,398 ****
   	if (flock(yplockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK)
   		errx(1, "another ypbind is already running. Aborting");
 
 - 	/* XXX domainname will be overriden if we use restricted mode */
 - 	yp_get_default_domain(&domain_name);
 - 	if (domain_name[0] == '\0')
 - 		errx(1, "domainname not set. Aborting");
 -
   	for (i = 1; i<argc; i++) {
   		if (strcmp("-ypset", argv[i]) == 0)
   			ypsetmode = YPSET_ALL;
 --- 388,393 ----
 ***************
 *** 406,411 ****
 --- 401,413 ----
   			yp_manycast++;
   		else
   			errx(1, "unknown option: %s", argv[i]);
 + 	}
 +
 + 	if (domain_name == NULL || domain_name[0] == '\0') {
 + 		/* XXX domainname will be overriden if we use restricted mode */
 + 		yp_get_default_domain(&domain_name);
 + 		if (domain_name[0] == '\0')
 + 			errx(1, "domainname not set. Aborting");
   	}
 
   	/* blow away everything in BINDINGDIR (if it exists) */
 
 ----
 -- 
 ----------------------------------------------------------------------
 Trond Endrestl                          |   trond@fagskolen.gjovik.no
 Patron of The Art of Computer Programming|   FreeBSD 4.8-S & Pine 4.55
>Unformatted:
 >System:
 
