5cf0e00
commit ca668e35d16ca296dee1bd000de8eb8d20433a21
5cf0e00
Author: Chuck Lever <chuck.lever@oracle.com>
5cf0e00
Date:   Tue May 28 10:02:49 2019 -0400
5cf0e00
5cf0e00
    rpc.mountd: Fix mountd segfault
5cf0e00
    
5cf0e00
    After commit 8f459a072f93 ("Remove abuse of ai_canonname") the
5cf0e00
    ai_canonname field in addrinfo structs returned from
5cf0e00
    host_reliable_addrinfo() is always NULL. This results in mountd
5cf0e00
    segfaults when there are netgroups or hostname wildcards in
5cf0e00
    /etc/exports.
5cf0e00
    
5cf0e00
    Add an extra DNS query in check_wildcard() and check_netgroup() to
5cf0e00
    obtain the client's canonical hostname instead of dereferencing
5cf0e00
    the NULL pointer.
5cf0e00
    
5cf0e00
    Reported-by: Mark Wagner <mark@lanfear.net>
5cf0e00
    Fixes: 8f459a072f93 ("Remove abuse of ai_canonname")
5cf0e00
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
5cf0e00
    Signed-off-by: Steve Dickson <steved@redhat.com>
5cf0e00
5cf0e00
diff --git a/support/export/client.c b/support/export/client.c
5cf0e00
index a1fba01..ea4f89d 100644
5cf0e00
--- a/support/export/client.c
5cf0e00
+++ b/support/export/client.c
5cf0e00
@@ -608,24 +608,36 @@ check_subnetwork(const nfs_client *clp, const struct addrinfo *ai)
5cf0e00
 static int
5cf0e00
 check_wildcard(const nfs_client *clp, const struct addrinfo *ai)
5cf0e00
 {
5cf0e00
-	char *cname = clp->m_hostname;
5cf0e00
-	char *hname = ai->ai_canonname;
5cf0e00
+	char *hname, *cname = clp->m_hostname;
5cf0e00
 	struct hostent *hp;
5cf0e00
 	char **ap;
5cf0e00
+	int match;
5cf0e00
 
5cf0e00
-	if (wildmat(hname, cname))
5cf0e00
-		return 1;
5cf0e00
+	match = 0;
5cf0e00
+
5cf0e00
+	hname = host_canonname(ai->ai_addr);
5cf0e00
+	if (hname == NULL)
5cf0e00
+		goto out;
5cf0e00
+
5cf0e00
+	if (wildmat(hname, cname)) {
5cf0e00
+		match = 1;
5cf0e00
+		goto out;
5cf0e00
+	}
5cf0e00
 
5cf0e00
 	/* See if hname aliases listed in /etc/hosts or nis[+]
5cf0e00
 	 * match the requested wildcard */
5cf0e00
 	hp = gethostbyname(hname);
5cf0e00
 	if (hp != NULL) {
5cf0e00
 		for (ap = hp->h_aliases; *ap; ap++)
5cf0e00
-			if (wildmat(*ap, cname))
5cf0e00
-				return 1;
5cf0e00
+			if (wildmat(*ap, cname)) {
5cf0e00
+				match = 1;
5cf0e00
+				goto out;
5cf0e00
+			}
5cf0e00
 	}
5cf0e00
 
5cf0e00
-	return 0;
5cf0e00
+out:
5cf0e00
+	free(hname);
5cf0e00
+	return match;
5cf0e00
 }
5cf0e00
 
5cf0e00
 /*
5cf0e00
@@ -645,11 +657,9 @@ check_netgroup(const nfs_client *clp, const struct addrinfo *ai)
5cf0e00
 
5cf0e00
 	match = 0;
5cf0e00
 
5cf0e00
-	hname = strdup(ai->ai_canonname);
5cf0e00
-	if (hname == NULL) {
5cf0e00
-		xlog(D_GENERAL, "%s: no memory for strdup", __func__);
5cf0e00
+	hname = host_canonname(ai->ai_addr);
5cf0e00
+	if (hname == NULL)
5cf0e00
 		goto out;
5cf0e00
-	}
5cf0e00
 
5cf0e00
 	/* First, try to match the hostname without
5cf0e00
 	 * splitting off the domain */