[Upstream] dnsproxy: Fix crash on malformed DNS response 79/151579/2
authorJaehyun Kim <jeik01.kim@samsung.com>
Thu, 21 Sep 2017 07:35:25 +0000 (16:35 +0900)
committerJaehyun Kim <jeik01.kim@samsung.com>
Thu, 21 Sep 2017 08:01:48 +0000 (17:01 +0900)
If the response query string is malformed, we might access memory
pass the end of "name" variable in parse_response().

Change-Id: I179583bd9f7682a49a2980d866ae3524d1b75879
Signed-off-by: Jaehyun Kim <jeik01.kim@samsung.com>
src/dnsproxy.c

index 5fd4b26..55ba69a 100755 (executable)
@@ -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;