From ak03@gte.com  Mon Apr 23 15:27:12 2001
Return-Path: <ak03@gte.com>
Received: from h132-197-97-45.gte.com (h132-197-97-45.gte.com [132.197.97.45])
	by hub.freebsd.org (Postfix) with ESMTP id 03D9137B423
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 23 Apr 2001 15:27:12 -0700 (PDT)
	(envelope-from ak03@gte.com)
Received: (from ak03@localhost)
	by h132-197-97-45.gte.com (8.11.3/8.11.3) id f3NMRAd01041;
	Mon, 23 Apr 2001 18:27:10 -0400 (EDT)
	(envelope-from ak03)
Message-Id: <200104232227.f3NMRAd01041@h132-197-97-45.gte.com>
Date: Mon, 23 Apr 2001 18:27:10 -0400 (EDT)
From: ak03@gte.com
To: FreeBSD-gnats-submit@freebsd.org
Subject: FIX: rpcbind dumps core sometimes 
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         26806
>Category:       bin
>Synopsis:       rpcbind can dump core under certain circumstances
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    iedowse
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Apr 23 15:30:01 PDT 2001
>Closed-Date:    Thu May 10 09:49:02 PDT 2001
>Last-Modified:  Thu May 10 09:52:25 PDT 2001
>Originator:     Alexander N. Kabaev
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
Verizon Laboratories Inc.
>Environment:
System: FreeBSD kanpc.gte.com 5.0-CURRENT FreeBSD 5.0-CURRENT #2: Mon Apr 23 14:50:40 EDT 2001 root@kanpc.gte.com:/usr/src/sys/compile/KANPC i386

>Description:
	rpcbind occasionally dump core on my -CURRENT box. After I was unable
	to get the meaningful core dump, it turns out that the program
	is crashing due to the unitialized parameter in addrmerge 
	procedure in rpcbind/util.c

	It looks like addrmerge tries to locate the network device most
	suitable for sending request reply to the client and then converts
	the unterface network address into a string. When the client
	address is on the local subnet, everything is OK and one of
	the branches of the switch statement on util.c:111 will execute
 	and initialize tbuf structure with proper values. If client is
	not on the local address, procedure tries to select "best"
	interface to handle the requiest but does NOT initialize
	tbuf structure and passes random garbage to the taddr2uaddr later
	when it reaches found: label.
	taddr2uaddr crashes with sig 11 in inet_ntop shortly after that.
	
>How-To-Repeat:
	Not sure. Simply run -CURRENT box in a large network with
	multiple subnets?
>Fix:
	Attached patch delays initialization of the tbuf structure
	until right before taddr2uaddr is called. rpcbind did not crash
	for a three days already while before it was reliably dumping 
	core no later than 30 min after system reboot.

Index: util.c
===================================================================
RCS file: /usr/ncvs/src/usr.sbin/rpcbind/util.c,v
retrieving revision 1.1
diff -u -r1.1 util.c
--- util.c	2001/03/19 12:50:11	1.1
+++ util.c	2001/04/23 21:48:25
@@ -174,29 +174,14 @@
 			 * ifsin: address of interface being examined.
 			 * clntsin: address that client want us to contact
 			 *           it on
-			 * servsin: local address of RPC service.
 			 * sinmask: netmask of this interface
-			 * newsin: initially a copy of clntsin, eventually
-			 *         the merged address
 			 */
-			servsin = (struct sockaddr_in *)serv_sa;
 			clntsin = (struct sockaddr_in *)clnt_sa;
 			sinmask = (struct sockaddr_in *)ifap->ifa_netmask;
-			newsin = (struct sockaddr_in *)&ss;
 			ifsin = (struct sockaddr_in *)ifap->ifa_addr;
 			if (!bitmaskcmp(&ifsin->sin_addr, &clntsin->sin_addr,
-			    &sinmask->sin_addr, sizeof (struct in_addr))) {
-				/*
-				 * Found it.
-				 */
-				memcpy(newsin, ifap->ifa_addr,
-				    clnt_sa->sa_len);
-				newsin->sin_port = servsin->sin_port;
-				tbuf.len = clnt_sa->sa_len;
-				tbuf.maxlen = sizeof (struct sockaddr_storage);
-				tbuf.buf = newsin;
+			    &sinmask->sin_addr, sizeof (struct in_addr)))
 				goto found;
-			}
 			break;
 #ifdef INET6
 		case AF_INET6:
@@ -205,10 +190,7 @@
 			 * ifsin6: address of interface being examined.
 			 * clntsin6: address that client want us to contact
 			 *           it on
-			 * servsin6: local address of RPC service.
 			 * sin6mask: netmask of this interface
-			 * newsin6: initially a copy of clntsin, eventually
-			 *          the merged address
 			 *
 			 * For v6 link local addresses, if the client contacted
 			 * us via a link-local address, and wants us to reply
@@ -218,27 +200,19 @@
 			ifsin6 = (struct sockaddr_in6 *)ifap->ifa_addr;
 			in6_fillscopeid(ifsin6);
 			clntsin6 = (struct sockaddr_in6 *)clnt_sa;
-			servsin6 = (struct sockaddr_in6 *)serv_sa;
 			sin6mask = (struct sockaddr_in6 *)ifap->ifa_netmask;
-			newsin6 = (struct sockaddr_in6 *)&ss;
 			if (IN6_IS_ADDR_LINKLOCAL(&ifsin6->sin6_addr) &&
 			    IN6_IS_ADDR_LINKLOCAL(&realsin6->sin6_addr) &&
 			    IN6_IS_ADDR_LINKLOCAL(&clntsin6->sin6_addr)) {
 				if (ifsin6->sin6_scope_id !=
 				    realsin6->sin6_scope_id)
 					continue;
-match:
-				memcpy(newsin6, ifsin6, clnt_sa->sa_len);
-				newsin6->sin6_port = servsin6->sin6_port;
-				tbuf.maxlen = sizeof (struct sockaddr_storage);
-				tbuf.len = clnt_sa->sa_len;
-				tbuf.buf = newsin6;
 				goto found;
 			}
 			if (!bitmaskcmp(&ifsin6->sin6_addr,
 			    &clntsin6->sin6_addr, &sin6mask->sin6_addr,
 			    sizeof (struct in6_addr)))
-				goto match;
+				goto found;
 			break;
 #endif
 		default:
@@ -268,8 +242,31 @@
 	}
 	ifap = bestif;
 found:
-	if (ifap != NULL)
+	if (ifap != NULL) {
+		memcpy(newsin, ifap->ifa_addr, clnt_sa->sa_len);
+		tbuf.len = clnt_sa->sa_len;
+		tbuf.maxlen = sizeof (struct sockaddr_storage);
+		tbuf.buf = &ss;
+
+		switch (clnt->sa_family) {
+		case AF_INET:
+			servsin = (struct sockaddr_in *)serv_sa;
+			newsin = (struct sockaddr_in *)&ss;
+			newsin->sin_port = servsin->sin_port;
+			break;
+#ifdef INET6
+		case AF_INET6:
+			servsin6 = (struct sockaddr_in6 *)serv_sa;
+			newsin6 = (struct sockaddr_in6 *)&ss;
+			newsin6->sin6_port = servsin6->sin6_port;
+			break;
+#endif
+		default:
+			goto freeit;
+		}
+
 		ret = taddr2uaddr(nconf, &tbuf);
+	}
 freeit:
 	freenetconfigent(nconf);
 	free(serv_sa);
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->iedowse 
Responsible-Changed-By: iedowse 
Responsible-Changed-When: Mon Apr 23 17:01:45 PDT 2001 
Responsible-Changed-Why:  
I'll deal with this. Thanks for the patch and the analysis! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=26806 
State-Changed-From-To: open->feedback 
State-Changed-By: iedowse 
State-Changed-When: Thu Apr 26 10:26:45 PDT 2001 
State-Changed-Why:  

I've committed a bugfix from NetBSD which should address this issue. I 
think your patch may have been more complete, but I'd like to keep the 
code as close as possible to NetBSD's for now. Could you verify that 
revision 1.2 of util.c fixes the problem you were seeing? Thanks. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=26806 
State-Changed-From-To: feedback->closed 
State-Changed-By: iedowse 
State-Changed-When: Thu May 10 09:49:02 PDT 2001 
State-Changed-Why:  

Submitter has confirmed that util.c r1.2 resolved this issue. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=26806 
>Unformatted:
