Sophie

Sophie

distrib > Mageia > 6 > armv7hl > media > core-updates-src > by-pkgid > 5f43aa6626a4a75350f15727468d9f69 > files > 4

connman-1.33-6.1.mga6.src.rpm

From: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Date: Wed, 9 Aug 2017 10:16:46 +0300
Subject: dnsproxy: Fix crash on malformed DNS response

If the response query string is malformed, we might access memory
pass the end of "name" variable in parse_response().

Origin: upstream, https://git.kernel.org/pub/scm/network/connman/connman.git/commit/?id=5c281d182ecdd0a424b64f7698f32467f8f67b71
X-CVE: CVE-2017-12865
Bug-Debian: http://bugs.debian.org/872844
---
 src/dnsproxy.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

--- a/src/dnsproxy.c
+++ b/src/dnsproxy.c
@@ -836,7 +836,7 @@ static struct cache_entry *cache_check(g
 static int get_name(int counter,
 		unsigned char *pkt, unsigned char *start, unsigned char *max,
 		unsigned char *output, int output_max, int *output_len,
-		unsigned char **end, char *name, int *name_len)
+		unsigned char **end, char *name, size_t max_name, int *name_len)
 {
 	unsigned char *p;
 
@@ -857,7 +857,7 @@ static int get_name(int counter,
 
 			return get_name(counter + 1, pkt, pkt + offset, max,
 					output, output_max, output_len, end,
-					name, name_len);
+					name, max_name, name_len);
 		} else {
 			unsigned label_len = *p;
 
@@ -867,6 +867,9 @@ static int get_name(int counter,
 			if (*output_len > output_max)
 				return -ENOBUFS;
 
+			if ((*name_len + 1 + label_len + 1) > max_name)
+				return -ENOBUFS;
+
 			/*
 			 * We need the original name in order to check
 			 * if this answer is the correct one.
@@ -898,14 +901,14 @@ static int parse_rr(unsigned char *buf,
 			unsigned char *response, unsigned int *response_size,
 			uint16_t *type, uint16_t *class, int *ttl, int *rdlen,
 			unsigned char **end,
-			char *name)
+			char *name, size_t max_name)
 {
 	struct domain_rr *rr;
 	int err, offset;
 	int name_len = 0, output_len = 0, max_rsp = *response_size;
 
 	err = get_name(0, buf, start, max, response, max_rsp,
-		&output_len, end, name, &name_len);
+			&output_len, end, name, max_name, &name_len);
 	if (err < 0)
 		return err;
 
@@ -1031,7 +1034,8 @@ static int parse_response(unsigned char
 		memset(rsp, 0, sizeof(rsp));
 
 		ret = parse_rr(buf, ptr, buf + buflen, rsp, &rsp_len,
-			type, class, ttl, &rdlen, &next, name);
+			type, class, ttl, &rdlen, &next, name,
+			sizeof(name) - 1);
 		if (ret != 0) {
 			err = ret;
 			goto out;
@@ -1097,7 +1101,7 @@ static int parse_response(unsigned char
 			 */
 			ret = get_name(0, buf, next - rdlen, buf + buflen,
 					rsp, rsp_len, &output_len, &end,
-					name, &name_len);
+					name, sizeof(name) - 1, &name_len);
 			if (ret != 0) {
 				/* just ignore the error at this point */
 				ptr = next;