bind_Fix_for_CVE-2012-5166

Upstream-Status: Backport

Reference:http://launchpadlibrarian.net/119212498/bind9_1%3A9.7.3.dfsOBg
-1ubuntu2.6_1%3A9.7.3.dfsg-1ubuntu2.7.diff.gz

ISC BIND 9.x before 9.7.6-P4, 9.8.x before 9.8.3-P4, 9.9.x before
9.9.1-P4, and 9.4-ESV and 9.6-ESV before 9.6-ESV-R7-P4 allows
remote attackers to cause a denial of service (named daemon hang)
via unspecified combinations of resource records.

http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2012-5166

Signed-off-by: yanjun.zhu <yanjun.zhu@windriver.com>
diff -urpN a/bin/named/query.c b/bin/named/query.c
--- a/bin/named/query.c	2012-10-22 13:24:27.000000000 +0800
+++ b/bin/named/query.c	2012-10-22 13:17:04.000000000 +0800
@@ -1137,13 +1137,6 @@ query_isduplicate(ns_client_t *client, d
 		mname = NULL;
 	}
 
-	/*
-	 * If the dns_name_t we're looking up is already in the message,
-	 * we don't want to trigger the caller's name replacement logic.
-	 */
-	if (name == mname)
-		mname = NULL;
-
 	*mnamep = mname;
 
 	CTRACE("query_isduplicate: false: done");
@@ -1341,6 +1334,7 @@ query_addadditional(void *arg, dns_name_
 	if (dns_rdataset_isassociated(rdataset) &&
 	    !query_isduplicate(client, fname, type, &mname)) {
 		if (mname != NULL) {
+			INSIST(mname != fname);
 			query_releasename(client, &fname);
 			fname = mname;
 		} else
@@ -1401,11 +1395,13 @@ query_addadditional(void *arg, dns_name_
 			mname = NULL;
 			if (!query_isduplicate(client, fname,
 					       dns_rdatatype_a, &mname)) {
-				if (mname != NULL) {
-					query_releasename(client, &fname);
-					fname = mname;
-				} else
-					need_addname = ISC_TRUE;
+				if (mname != fname) {
+					if (mname != NULL) {
+						query_releasename(client, &fname);
+						fname = mname;
+					} else
+						need_addname = ISC_TRUE;
+				}
 				ISC_LIST_APPEND(fname->list, rdataset, link);
 				added_something = ISC_TRUE;
 				if (sigrdataset != NULL &&
@@ -1444,11 +1440,13 @@ query_addadditional(void *arg, dns_name_
 			mname = NULL;
 			if (!query_isduplicate(client, fname,
 					       dns_rdatatype_aaaa, &mname)) {
-				if (mname != NULL) {
-					query_releasename(client, &fname);
-					fname = mname;
-				} else
-					need_addname = ISC_TRUE;
+				if (mname != fname) {
+					if (mname != NULL) {
+						query_releasename(client, &fname);
+						fname = mname;
+					} else
+						need_addname = ISC_TRUE;
+				}
 				ISC_LIST_APPEND(fname->list, rdataset, link);
 				added_something = ISC_TRUE;
 				if (sigrdataset != NULL &&
@@ -1960,22 +1958,24 @@ query_addadditional2(void *arg, dns_name
 		    crdataset->type == dns_rdatatype_aaaa) {
 			if (!query_isduplicate(client, fname, crdataset->type,
 					       &mname)) {
-				if (mname != NULL) {
-					/*
-					 * A different type of this name is
-					 * already stored in the additional
-					 * section.  We'll reuse the name.
-					 * Note that this should happen at most
-					 * once.  Otherwise, fname->link could
-					 * leak below.
-					 */
-					INSIST(mname0 == NULL);
-
-					query_releasename(client, &fname);
-					fname = mname;
-					mname0 = mname;
-				} else
-					need_addname = ISC_TRUE;
+				if (mname != fname) {
+					if (mname != NULL) {
+						/*
+						 * A different type of this name is
+						 * already stored in the additional
+						 * section.  We'll reuse the name.
+						 * Note that this should happen at most
+						 * once.  Otherwise, fname->link could
+						 * leak below.
+						 */
+						INSIST(mname0 == NULL);
+
+						query_releasename(client, &fname);
+						fname = mname;
+						mname0 = mname;
+					} else
+						need_addname = ISC_TRUE;
+				}
 				ISC_LIST_UNLINK(cfname.list, crdataset, link);
 				ISC_LIST_APPEND(fname->list, crdataset, link);
 				added_something = ISC_TRUE;
