changeset 3176:a38e922f22b0

6495346 memory leak in nss_dns.so.1/_nss_dns_gethost_withttl 6495347 getexecuser/getexecprof leak memory in nss_nis.so and nss_nisplus.so
author michen
date Mon, 27 Nov 2006 13:17:04 -0800
parents 5903f61aa150
children 6d48ee59c4fc
files usr/src/lib/nsswitch/dns/common/dns_common.c usr/src/lib/nsswitch/nis/common/getexecattr.c usr/src/lib/nsswitch/nisplus/common/getexecattr.c
diffstat 3 files changed, 36 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/nsswitch/dns/common/dns_common.c	Mon Nov 27 12:42:57 2006 -0800
+++ b/usr/src/lib/nsswitch/dns/common/dns_common.c	Mon Nov 27 13:17:04 2006 -0800
@@ -263,6 +263,18 @@
 	return ((nss_backend_t *)be);
 }
 
+/*
+ * __res_ndestroy is a simplified version of the non-public function
+ * res_ndestroy in libresolv.so.2. Before res_ndestroy can be made
+ * public, __res_ndestroy will be used to make sure the memory pointed
+ * by statp->_u._ext.ext is freed after res_nclose() is called.
+ */
+static void
+__res_ndestroy(res_state statp) {
+	res_nclose(statp);
+	if (statp->_u._ext.ext != NULL)
+		free(statp->_u._ext.ext);
+}
 
 /*
  * nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode)
@@ -343,14 +355,14 @@
 	blen = 0;
 	sret = nss_packed_getkey(buffer, bufsize, &dbname, &dbop, &arg);
 	if (sret != NSS_SUCCESS) {
-		res_nclose(statp);
+		__res_ndestroy(statp);
 		return (NSS_ERROR);
 	}
 
 	if (ipnode) {
 		/* initially only handle the simple cases */
 		if (arg.key.ipnode.flags != 0) {
-			res_nclose(statp);
+			__res_ndestroy(statp);
 			return (NSS_ERROR);
 		}
 		name = arg.key.ipnode.name;
@@ -368,11 +380,11 @@
 			pbuf->p_herrno = HOST_NOT_FOUND;
 			pbuf->p_status = NSS_NOTFOUND;
 			pbuf->data_len = 0;
-			res_nclose(statp);
+			__res_ndestroy(statp);
 			return (NSS_NOTFOUND);
 		}
 		/* else lookup error - handle in general code */
-		res_nclose(statp);
+		__res_ndestroy(statp);
 		return (NSS_ERROR);
 	}
 
@@ -385,25 +397,25 @@
 	qdcount = ntohs(hp->qdcount);
 	cp += HFIXEDSZ;
 	if (qdcount != 1) {
-		res_nclose(statp);
+		__res_ndestroy(statp);
 		return (NSS_ERROR);
 	}
 	n = dn_expand(bom, eom, cp, host, MAXHOSTNAMELEN);
 	if (n < 0) {
-		res_nclose(statp);
+		__res_ndestroy(statp);
 		return (NSS_ERROR);
 	} else
 		hlen = strlen(host);
 	cp += n + QFIXEDSZ;
 	if (cp > eom) {
-		res_nclose(statp);
+		__res_ndestroy(statp);
 		return (NSS_ERROR);
 	}
 	while (ancount-- > 0 && cp < eom && blen < bsize) {
 		n = dn_expand(bom, eom, cp, ans, MAXHOSTNAMELEN);
 		if (n > 0) {
 			if (strncasecmp(host, ans, hlen) != 0) {
-				res_nclose(statp);
+				__res_ndestroy(statp);
 				return (NSS_ERROR);	/* spoof? */
 			}
 		}
@@ -435,8 +447,10 @@
 					 * attempted buffer overflow exploit
 					 * generic code will do a syslog
 					 */
-					if (alen + len + 2 > NS_MAXMSG)
+					if (alen + len + 2 > NS_MAXMSG) {
+						__res_ndestroy(statp);
 						return (NSS_ERROR);
+					}
 					*apc++ = ' ';
 					alen++;
 					(void) strlcpy(apc, aname, len + 1);
@@ -460,7 +474,7 @@
 		af = (type == T_A ? AF_INET : AF_INET6);
 		np = inet_ntop(af, (void *)cp, nbuf, INET6_ADDRSTRLEN);
 		if (np == NULL) {
-			res_nclose(statp);
+			__res_ndestroy(statp);
 			return (NSS_ERROR);
 		}
 		cp += n;
@@ -470,8 +484,10 @@
 		len = iplen + 2 + hlen + alen;
 		if (alen > 0)
 			len++;
-		if (blen + len > bsize)
+		if (blen + len > bsize) {
+			__res_ndestroy(statp);
 			return (NSS_ERROR);
+		}
 		(void) strlcpy(bptr, np, bsize - blen);
 		blen += iplen;
 		bptr += iplen;
@@ -495,6 +511,7 @@
 	/* still room? */
 	if (len + sizeof (nssuint_t) > pbuf->data_len) {
 		/* sigh, no, what happened? */
+		__res_ndestroy(statp);
 		return (NSS_ERROR);
 	}
 	pbuf->ext_off = pbuf->data_off + len;
@@ -502,6 +519,6 @@
 	pbuf->data_len = blen;
 	pttl = (nssuint_t *)((void *)((char *)pbuf + pbuf->ext_off));
 	*pttl = ttl;
-	res_nclose(statp);
+	__res_ndestroy(statp);
 	return (NSS_SUCCESS);
 }
--- a/usr/src/lib/nsswitch/nis/common/getexecattr.c	Mon Nov 27 12:42:57 2006 -0800
+++ b/usr/src/lib/nsswitch/nis/common/getexecattr.c	Mon Nov 27 13:17:04 2006 -0800
@@ -282,9 +282,12 @@
 				res = ypres;
 				break;
 			} else {
+				char *val_save = val;
+
 				massage_netdb((const char **)&val, &vallen);
 				res = _exec_nis_parse((const char *)val,
 				    vallen, argp, check_policy);
+				free(val_save);
 				break;
 			}
 		} while (res == NSS_SUCCESS);
@@ -339,13 +342,13 @@
 static  nss_status_t
 get_wild(nis_backend_ptr_t be, nss_XbyY_args_t *argp, int getby_flag)
 {
-	char		*orig_id = NULL;
+	const char	*orig_id;
 	char		*old_id = NULL;
 	char		*wild_id = NULL;
 	nss_status_t	res = NSS_NOTFOUND;
 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
 
-	orig_id = strdup(_priv_exec->id);
+	orig_id = _priv_exec->id;
 	old_id = strdup(_priv_exec->id);
 	wild_id = old_id;
 	while ((wild_id = _exec_wild_id(wild_id, _priv_exec->type)) != NULL) {
--- a/usr/src/lib/nsswitch/nisplus/common/getexecattr.c	Mon Nov 27 12:42:57 2006 -0800
+++ b/usr/src/lib/nsswitch/nisplus/common/getexecattr.c	Mon Nov 27 13:17:04 2006 -0800
@@ -336,13 +336,13 @@
 static nss_status_t
 get_wild(nisplus_backend_ptr_t be, nss_XbyY_args_t *argp, int getby_flag)
 {
-	char		*orig_id = NULL;
+	const char	*orig_id = NULL;
 	char		*old_id = NULL;
 	char		*wild_id = NULL;
 	nss_status_t	res = NSS_NOTFOUND;
 	_priv_execattr	*_priv_exec = (_priv_execattr *)(argp->key.attrp);
 
-	orig_id = strdup(_priv_exec->id);
+	orig_id = _priv_exec->id;
 	old_id = strdup(_priv_exec->id);
 	wild_id = old_id;
 	while ((wild_id = _exec_wild_id(wild_id, _priv_exec->type)) != NULL) {