dnsmasq: also add the actual patches...
[15.05/openwrt.git] / package / network / services / dnsmasq / patches / 001-fix-dnssec-crash.patch
1 From 094b5c3d904bae9aeb3206d9f3b8348926b84975 Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Sun, 21 Dec 2014 16:11:52 +0000
4 Subject: [PATCH] Fix crash in DNSSEC code when attempting to verify large RRs.
5
6 ---
7  src/dnssec.c | 27 +++++++++++++++++++--------
8
9 diff --git a/src/dnssec.c b/src/dnssec.c
10 index 69bfc29..3208ac7 100644
11 --- a/src/dnssec.c
12 +++ b/src/dnssec.c
13 @@ -456,16 +456,27 @@ static u16 *get_desc(int type)
14  
15  /* Return bytes of canonicalised rdata, when the return value is zero, the remaining 
16     data, pointed to by *p, should be used raw. */
17 -static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, 
18 +static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, int bufflen,
19                      unsigned char **p, u16 **desc)
20  {
21    int d = **desc;
22    
23 -  (*desc)++;
24 -  
25    /* No more data needs mangling */
26    if (d == (u16)-1)
27 -    return 0;
28 +    {
29 +      /* If there's more data than we have space for, just return what fits,
30 +        we'll get called again for more chunks */
31 +      if (end - *p > bufflen)
32 +       {
33 +         memcpy(buff, *p, bufflen);
34 +         *p += bufflen;
35 +         return bufflen;
36 +       }
37 +      
38 +      return 0;
39 +    }
40
41 +  (*desc)++;
42    
43    if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
44      /* domain-name, canonicalise */
45 @@ -560,7 +571,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
46               if (left1 != 0)
47                 memmove(buff1, buff1 + len1 - left1, left1);
48               
49 -             if ((len1 = get_rdata(header, plen, end1, buff1 + left1, &p1, &dp1)) == 0)
50 +             if ((len1 = get_rdata(header, plen, end1, buff1 + left1, MAXDNAME - left1, &p1, &dp1)) == 0)
51                 {
52                   quit = 1;
53                   len1 = end1 - p1;
54 @@ -571,7 +582,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int
55               if (left2 != 0)
56                 memmove(buff2, buff2 + len2 - left2, left2);
57               
58 -             if ((len2 = get_rdata(header, plen, end2, buff2 + left2, &p2, &dp2)) == 0)
59 +             if ((len2 = get_rdata(header, plen, end2, buff2 + left2, MAXDNAME - left2, &p2, &dp2)) == 0)
60                 {
61                   quit = 1;
62                   len2 = end2 - p2;
63 @@ -808,7 +819,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
64           /* canonicalise rdata and calculate length of same, use name buffer as workspace */
65           cp = p;
66           dp = rr_desc;
67 -         for (len = 0; (seg = get_rdata(header, plen, end, name, &cp, &dp)) != 0; len += seg);
68 +         for (len = 0; (seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp)) != 0; len += seg);
69           len += end - cp;
70           len = htons(len);
71           hash->update(ctx, 2, (unsigned char *)&len); 
72 @@ -816,7 +827,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
73           /* Now canonicalise again and digest. */
74           cp = p;
75           dp = rr_desc;
76 -         while ((seg = get_rdata(header, plen, end, name, &cp, &dp)))
77 +         while ((seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp)))
78             hash->update(ctx, seg, (unsigned char *)name);
79           if (cp != end)
80             hash->update(ctx, end - cp, cp);
81 -- 
82 2.1.3
83