]>
Commit | Line | Data |
---|---|---|
6644c1c7 MT |
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 | |
d54a2ce4 | 4 | Subject: [PATCH 17/78] Fix crash in DNSSEC code when attempting to verify |
6644c1c7 MT |
5 | large RRs. |
6 | ||
7 | --- | |
8 | CHANGELOG | 3 +++ | |
9 | src/dnssec.c | 27 +++++++++++++++++++-------- | |
10 | 2 files changed, 22 insertions(+), 8 deletions(-) | |
11 | ||
12 | diff --git a/CHANGELOG b/CHANGELOG | |
13 | index 01f5208ec006..956b71a151db 100644 | |
14 | --- a/CHANGELOG | |
15 | +++ b/CHANGELOG | |
16 | @@ -19,6 +19,9 @@ version 2.73 | |
17 | the answers given by --interface-name. Note that reverse queries | |
18 | (ie looking for names, given addresses) are not affected. | |
19 | Thanks to Michael Gorbach for the suggestion. | |
20 | + | |
21 | + Fix crash in DNSSEC code with long RRs. Thanks to Marco Davids | |
22 | + for the bug report. | |
23 | ||
24 | ||
25 | version 2.72 | |
26 | diff --git a/src/dnssec.c b/src/dnssec.c | |
27 | index 69bfc29e355f..3208ac701149 100644 | |
28 | --- a/src/dnssec.c | |
29 | +++ b/src/dnssec.c | |
30 | @@ -456,16 +456,27 @@ static u16 *get_desc(int type) | |
31 | ||
32 | /* Return bytes of canonicalised rdata, when the return value is zero, the remaining | |
33 | data, pointed to by *p, should be used raw. */ | |
34 | -static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, | |
35 | +static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, int bufflen, | |
36 | unsigned char **p, u16 **desc) | |
37 | { | |
38 | int d = **desc; | |
39 | ||
40 | - (*desc)++; | |
41 | - | |
42 | /* No more data needs mangling */ | |
43 | if (d == (u16)-1) | |
44 | - return 0; | |
45 | + { | |
46 | + /* If there's more data than we have space for, just return what fits, | |
47 | + we'll get called again for more chunks */ | |
48 | + if (end - *p > bufflen) | |
49 | + { | |
50 | + memcpy(buff, *p, bufflen); | |
51 | + *p += bufflen; | |
52 | + return bufflen; | |
53 | + } | |
54 | + | |
55 | + return 0; | |
56 | + } | |
57 | + | |
58 | + (*desc)++; | |
59 | ||
60 | if (d == 0 && extract_name(header, plen, p, buff, 1, 0)) | |
61 | /* domain-name, canonicalise */ | |
62 | @@ -560,7 +571,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int | |
63 | if (left1 != 0) | |
64 | memmove(buff1, buff1 + len1 - left1, left1); | |
65 | ||
66 | - if ((len1 = get_rdata(header, plen, end1, buff1 + left1, &p1, &dp1)) == 0) | |
67 | + if ((len1 = get_rdata(header, plen, end1, buff1 + left1, MAXDNAME - left1, &p1, &dp1)) == 0) | |
68 | { | |
69 | quit = 1; | |
70 | len1 = end1 - p1; | |
71 | @@ -571,7 +582,7 @@ static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int | |
72 | if (left2 != 0) | |
73 | memmove(buff2, buff2 + len2 - left2, left2); | |
74 | ||
75 | - if ((len2 = get_rdata(header, plen, end2, buff2 + left2, &p2, &dp2)) == 0) | |
76 | + if ((len2 = get_rdata(header, plen, end2, buff2 + left2, MAXDNAME - left2, &p2, &dp2)) == 0) | |
77 | { | |
78 | quit = 1; | |
79 | len2 = end2 - p2; | |
80 | @@ -808,7 +819,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in | |
81 | /* canonicalise rdata and calculate length of same, use name buffer as workspace */ | |
82 | cp = p; | |
83 | dp = rr_desc; | |
84 | - for (len = 0; (seg = get_rdata(header, plen, end, name, &cp, &dp)) != 0; len += seg); | |
85 | + for (len = 0; (seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp)) != 0; len += seg); | |
86 | len += end - cp; | |
87 | len = htons(len); | |
88 | hash->update(ctx, 2, (unsigned char *)&len); | |
89 | @@ -816,7 +827,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in | |
90 | /* Now canonicalise again and digest. */ | |
91 | cp = p; | |
92 | dp = rr_desc; | |
93 | - while ((seg = get_rdata(header, plen, end, name, &cp, &dp))) | |
94 | + while ((seg = get_rdata(header, plen, end, name, MAXDNAME, &cp, &dp))) | |
95 | hash->update(ctx, seg, (unsigned char *)name); | |
96 | if (cp != end) | |
97 | hash->update(ctx, end - cp, cp); | |
98 | -- | |
99 | 2.1.0 | |
100 |