summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaehyun Kim <jeik01.kim@samsung.com>2017-09-21 16:35:25 +0900
committerJaehyun Kim <jeik01.kim@samsung.com>2017-09-21 16:58:49 +0900
commit05a82de3f7caf230706acc6251a2a739833d4ab3 (patch)
tree4824486a70931f802704805bce092fc2680c0c97
parenta95e33cf9bebdce45ff17d5d4d0c5fcfd5a907dd (diff)
downloadconnman-05a82de3f7caf230706acc6251a2a739833d4ab3.tar.gz
connman-05a82de3f7caf230706acc6251a2a739833d4ab3.tar.bz2
connman-05a82de3f7caf230706acc6251a2a739833d4ab3.zip
[Upstream] 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(). Change-Id: Iea436d5ba15222b5861f4abdfa270f451c4d4e61 Signed-off-by: Jaehyun Kim <jeik01.kim@samsung.com>
-rwxr-xr-xsrc/dnsproxy.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/src/dnsproxy.c b/src/dnsproxy.c
index 5fd4b262..55ba69a6 100755
--- a/src/dnsproxy.c
+++ b/src/dnsproxy.c
@@ -855,7 +855,7 @@ static struct cache_entry *cache_check(gpointer request, int *qtype, int proto)
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;
@@ -876,7 +876,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;
@@ -886,6 +886,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.
@@ -917,14 +920,14 @@ static int parse_rr(unsigned char *buf, unsigned char *start,
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;
@@ -1050,7 +1053,8 @@ static int parse_response(unsigned char *buf, int buflen,
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;
@@ -1116,7 +1120,7 @@ static int parse_response(unsigned char *buf, int buflen,
*/
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;