summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSona Sarmadi <sona.sarmadi@enea.com>2017-10-04 12:34:25 +0200
committerAdrian Dudau <adrian.dudau@enea.com>2017-10-04 15:28:01 +0200
commit4a1d1cdf2bf53dedfdb25ae1a045dfbcfda77c85 (patch)
tree9d34a79d81f538474e66fe7f8e622838322010d2
parentd74d2d2928ef9d5cffab2c9c19b4b6d50532962c (diff)
downloadmeta-el-common-4a1d1cdf2bf53dedfdb25ae1a045dfbcfda77c85.tar.gz
dnsmasq: CVE-2017-14491
Heap based overflow (2 bytes). Before 2.76 and this commit overflow was unrestricted. References: https://cve.mitre.org/cgi-bin/cvename.cgi?name=2017-14491 https://security.googleblog.com/2017/10/behind-masq-yet-more-dns-and-dhcp.html Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> Signed-off-by: Adrian Dudau <adrian.dudau@enea.com>
-rw-r--r--recipes-networking/dnsmasq/dnsmasq/0001-CVE-2017-14491.patch269
-rw-r--r--recipes-networking/dnsmasq/dnsmasq/0002-CVE-2017-14491.patch73
-rw-r--r--recipes-networking/dnsmasq/dnsmasq_%.bbappend6
3 files changed, 348 insertions, 0 deletions
diff --git a/recipes-networking/dnsmasq/dnsmasq/0001-CVE-2017-14491.patch b/recipes-networking/dnsmasq/dnsmasq/0001-CVE-2017-14491.patch
new file mode 100644
index 0000000..1eda591
--- /dev/null
+++ b/recipes-networking/dnsmasq/dnsmasq/0001-CVE-2017-14491.patch
@@ -0,0 +1,269 @@
1From 0549c73b7ea6b22a3c49beb4d432f185a81efcbc Mon Sep 17 00:00:00 2001
2From: Simon Kelley <simon@thekelleys.org.uk>
3Date: Mon, 25 Sep 2017 18:17:11 +0100
4Subject: [PATCH] Security fix, CVE-2017-14491 DNS heap buffer overflow.
5
6Fix heap overflow in DNS code. This is a potentially serious
7security hole. It allows an attacker who can make DNS
8requests to dnsmasq, and who controls the contents of
9a domain, which is thereby queried, to overflow
10(by 2 bytes) a heap buffer and either crash, or
11even take control of, dnsmasq.
12
13CVE: CVE-2017-14491
14Upstream-Status: Backport [src/dnsmasq.h patch failed, modified manually]
15
16Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
17
18diff -Nurp a/CHANGELOG b/CHANGELOG
19--- a/CHANGELOG 2016-05-18 16:51:54.000000000 +0200
20+++ b/CHANGELOG 2017-10-04 09:38:20.445498463 +0200
21@@ -123,6 +123,18 @@ version 2.75
22 dhcp-script is configured. Thanks to Adrian Davey for
23 reporting the bug and testing the fix.
24
25+ Fix heap overflow in DNS code. This is a potentially serious
26+ security hole. It allows an attacker who can make DNS
27+ requests to dnsmasq, and who controls the contents of
28+ a domain, which is thereby queried, to overflow
29+ (by 2 bytes) a heap buffer and either crash, or
30+ even take control of, dnsmasq.
31+ CVE-2017-14491 applies.
32+ Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
33+ and Kevin Hamacher of the Google Security Team for
34+ finding this.
35+
36+
37
38 version 2.74
39 Fix reversion in 2.73 where --conf-file would attempt to
40diff -Nurp a/src/dnsmasq.h b/src/dnsmasq.h
41--- a/src/dnsmasq.h 2016-05-18 16:51:54.000000000 +0200
42+++ b/src/dnsmasq.h 2017-10-04 09:39:39.366156718 +0200
43@@ -1161,7 +1161,7 @@ u32 rand32(void);
44 u64 rand64(void);
45 int legal_hostname(char *c);
46 char *canonicalise(char *s, int *nomem);
47-unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
48+unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
49 void *safe_malloc(size_t size);
50 void safe_pipe(int *fd, int read_noblock);
51 void *whine_malloc(size_t size);
52diff -Nurp a/src/dnssec.c b/src/dnssec.c
53--- a/src/dnssec.c 2016-05-18 16:51:54.000000000 +0200
54+++ b/src/dnssec.c 2017-10-04 09:38:20.445498463 +0200
55@@ -2227,7 +2227,7 @@ size_t dnssec_generate_query(struct dns_
56
57 p = (unsigned char *)(header+1);
58
59- p = do_rfc1035_name(p, name);
60+ p = do_rfc1035_name(p, name, NULL);
61 *p++ = 0;
62 PUTSHORT(type, p);
63 PUTSHORT(class, p);
64diff -Nurp a/src/option.c b/src/option.c
65--- a/src/option.c 2016-05-18 16:51:54.000000000 +0200
66+++ b/src/option.c 2017-10-04 09:38:20.449498294 +0200
67@@ -1378,7 +1378,7 @@ static int parse_dhcp_opt(char *errstr,
68 }
69
70 p = newp;
71- end = do_rfc1035_name(p + len, dom);
72+ end = do_rfc1035_name(p + len, dom, NULL);
73 *end++ = 0;
74 len = end - p;
75 free(dom);
76diff -Nurp a/src/rfc1035.c b/src/rfc1035.c
77--- a/src/rfc1035.c 2016-05-18 16:51:54.000000000 +0200
78+++ b/src/rfc1035.c 2017-10-04 09:38:20.449498294 +0200
79@@ -1049,6 +1049,7 @@ int check_for_ignored_address(struct dns
80 return 0;
81 }
82
83+
84 int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
85 unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
86 {
87@@ -1058,12 +1059,21 @@ int add_resource_record(struct dns_heade
88 unsigned short usval;
89 long lval;
90 char *sval;
91+#define CHECK_LIMIT(size) \
92+ if (limit && p + (size) > (unsigned char*)limit) \
93+ { \
94+ va_end(ap); \
95+ goto truncated; \
96+ }
97
98 if (truncp && *truncp)
99 return 0;
100-
101+
102 va_start(ap, format); /* make ap point to 1st unamed argument */
103-
104+
105+ /* nameoffset (1 or 2) + type (2) + class (2) + ttl (4) + 0 (2) */
106+ CHECK_LIMIT(12);
107+
108 if (nameoffset > 0)
109 {
110 PUTSHORT(nameoffset | 0xc000, p);
111@@ -1072,7 +1082,13 @@ int add_resource_record(struct dns_heade
112 {
113 char *name = va_arg(ap, char *);
114 if (name)
115- p = do_rfc1035_name(p, name);
116+ p = do_rfc1035_name(p, name, limit);
117+ if (!p)
118+ {
119+ va_end(ap);
120+ goto truncated;
121+ }
122+
123 if (nameoffset < 0)
124 {
125 PUTSHORT(-nameoffset | 0xc000, p);
126@@ -1093,6 +1109,7 @@ int add_resource_record(struct dns_heade
127 {
128 #ifdef HAVE_IPV6
129 case '6':
130+ CHECK_LIMIT(IN6ADDRSZ);
131 sval = va_arg(ap, char *);
132 memcpy(p, sval, IN6ADDRSZ);
133 p += IN6ADDRSZ;
134@@ -1100,36 +1117,47 @@ int add_resource_record(struct dns_heade
135 #endif
136
137 case '4':
138+ CHECK_LIMIT(INADDRSZ);
139 sval = va_arg(ap, char *);
140 memcpy(p, sval, INADDRSZ);
141 p += INADDRSZ;
142 break;
143
144 case 'b':
145+ CHECK_LIMIT(1);
146 usval = va_arg(ap, int);
147 *p++ = usval;
148 break;
149
150 case 's':
151+ CHECK_LIMIT(2);
152 usval = va_arg(ap, int);
153 PUTSHORT(usval, p);
154 break;
155
156 case 'l':
157+ CHECK_LIMIT(4);
158 lval = va_arg(ap, long);
159 PUTLONG(lval, p);
160 break;
161
162 case 'd':
163- /* get domain-name answer arg and store it in RDATA field */
164- if (offset)
165- *offset = p - (unsigned char *)header;
166- p = do_rfc1035_name(p, va_arg(ap, char *));
167- *p++ = 0;
168+ /* get domain-name answer arg and store it in RDATA field */
169+ if (offset)
170+ *offset = p - (unsigned char *)header;
171+ p = do_rfc1035_name(p, va_arg(ap, char *), limit);
172+ if (!p)
173+ {
174+ va_end(ap);
175+ goto truncated;
176+ }
177+ CHECK_LIMIT(1);
178+ *p++ = 0;
179 break;
180
181 case 't':
182 usval = va_arg(ap, int);
183+ CHECK_LIMIT(usval);
184 sval = va_arg(ap, char *);
185 if (usval != 0)
186 memcpy(p, sval, usval);
187@@ -1141,20 +1169,24 @@ int add_resource_record(struct dns_heade
188 usval = sval ? strlen(sval) : 0;
189 if (usval > 255)
190 usval = 255;
191+ CHECK_LIMIT(usval + 1);
192 *p++ = (unsigned char)usval;
193 memcpy(p, sval, usval);
194 p += usval;
195 break;
196 }
197
198+#undef CHECK_LIMIT
199 va_end(ap); /* clean up variable argument pointer */
200
201 j = p - sav - 2;
202- PUTSHORT(j, sav); /* Now, store real RDLength */
203+ /* this has already been checked against limit before */
204+ PUTSHORT(j, sav); /* Now, store real RDLength */
205
206 /* check for overflow of buffer */
207 if (limit && ((unsigned char *)limit - p) < 0)
208 {
209+truncated:
210 if (truncp)
211 *truncp = 1;
212 return 0;
213diff -Nurp a/src/rfc2131.c b/src/rfc2131.c
214--- a/src/rfc2131.c 2016-05-18 16:51:54.000000000 +0200
215+++ b/src/rfc2131.c 2017-10-04 09:38:20.449498294 +0200
216@@ -2419,10 +2419,10 @@ static void do_options(struct dhcp_conte
217
218 if (fqdn_flags & 0x04)
219 {
220- p = do_rfc1035_name(p, hostname);
221+ p = do_rfc1035_name(p, hostname, NULL);
222 if (domain)
223 {
224- p = do_rfc1035_name(p, domain);
225+ p = do_rfc1035_name(p, domain, NULL);
226 *p++ = 0;
227 }
228 }
229diff -Nurp a/src/rfc3315.c b/src/rfc3315.c
230--- a/src/rfc3315.c 2016-05-18 16:51:54.000000000 +0200
231+++ b/src/rfc3315.c 2017-10-04 09:38:20.449498294 +0200
232@@ -1472,10 +1472,10 @@ static struct dhcp_netid *add_options(st
233 if ((p = expand(len + 2)))
234 {
235 *(p++) = state->fqdn_flags;
236- p = do_rfc1035_name(p, state->hostname);
237+ p = do_rfc1035_name(p, state->hostname, NULL);
238 if (state->send_domain)
239 {
240- p = do_rfc1035_name(p, state->send_domain);
241+ p = do_rfc1035_name(p, state->send_domain, NULL);
242 *p = 0;
243 }
244 }
245diff -Nurp a/src/util.c b/src/util.c
246--- a/src/util.c 2016-05-18 16:51:54.000000000 +0200
247+++ b/src/util.c 2017-10-04 09:38:20.453498124 +0200
248@@ -218,15 +218,20 @@ char *canonicalise(char *in, int *nomem)
249 return ret;
250 }
251
252-unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
253+unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
254 {
255 int j;
256
257 while (sval && *sval)
258 {
259+ if (limit && p + 1 > (unsigned char*)limit)
260+ return p;
261+
262 unsigned char *cp = p++;
263 for (j = 0; *sval && (*sval != '.'); sval++, j++)
264 {
265+ if (limit && p + 1 > (unsigned char*)limit)
266+ return p;
267 #ifdef HAVE_DNSSEC
268 if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
269 *p++ = (*(++sval))-1;
diff --git a/recipes-networking/dnsmasq/dnsmasq/0002-CVE-2017-14491.patch b/recipes-networking/dnsmasq/dnsmasq/0002-CVE-2017-14491.patch
new file mode 100644
index 0000000..6f27667
--- /dev/null
+++ b/recipes-networking/dnsmasq/dnsmasq/0002-CVE-2017-14491.patch
@@ -0,0 +1,73 @@
1From 62cb936cb7ad5f219715515ae7d32dd281a5aa1f Mon Sep 17 00:00:00 2001
2From: Simon Kelley <simon@thekelleys.org.uk>
3Date: Tue, 26 Sep 2017 22:00:11 +0100
4Subject: [PATCH] Security fix, CVE-2017-14491, DNS heap buffer overflow.
5
6Further fix to 0549c73b7ea6b22a3c49beb4d432f185a81efcbc
7Handles case when RR name is not a pointer to the question,
8only occurs for some auth-mode replies, therefore not
9detected by fuzzing (?)
10
11CVE: CVE-2017-14491
12Upstream-Status: Backport
13
14Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
15---
16 src/rfc1035.c | 27 +++++++++++++++------------
17 1 file changed, 15 insertions(+), 12 deletions(-)
18
19diff --git a/src/rfc1035.c b/src/rfc1035.c
20index 27af023..56ab88b 100644
21--- a/src/rfc1035.c
22+++ b/src/rfc1035.c
23@@ -1086,32 +1086,35 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
24
25 va_start(ap, format); /* make ap point to 1st unamed argument */
26
27- /* nameoffset (1 or 2) + type (2) + class (2) + ttl (4) + 0 (2) */
28- CHECK_LIMIT(12);
29-
30 if (nameoffset > 0)
31 {
32+ CHECK_LIMIT(2);
33 PUTSHORT(nameoffset | 0xc000, p);
34 }
35 else
36 {
37 char *name = va_arg(ap, char *);
38- if (name)
39- p = do_rfc1035_name(p, name, limit);
40- if (!p)
41- {
42- va_end(ap);
43- goto truncated;
44- }
45-
46+ if (name && !(p = do_rfc1035_name(p, name, limit)))
47+ {
48+ va_end(ap);
49+ goto truncated;
50+ }
51+
52 if (nameoffset < 0)
53 {
54+ CHECK_LIMIT(2);
55 PUTSHORT(-nameoffset | 0xc000, p);
56 }
57 else
58- *p++ = 0;
59+ {
60+ CHECK_LIMIT(1);
61+ *p++ = 0;
62+ }
63 }
64
65+ /* type (2) + class (2) + ttl (4) + rdlen (2) */
66+ CHECK_LIMIT(10);
67+
68 PUTSHORT(type, p);
69 PUTSHORT(class, p);
70 PUTLONG(ttl, p); /* TTL */
71--
721.7.10.4
73
diff --git a/recipes-networking/dnsmasq/dnsmasq_%.bbappend b/recipes-networking/dnsmasq/dnsmasq_%.bbappend
new file mode 100644
index 0000000..e228035
--- /dev/null
+++ b/recipes-networking/dnsmasq/dnsmasq_%.bbappend
@@ -0,0 +1,6 @@
1# look for files in the layer first
2FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
3
4SRC_URI += "file://0001-CVE-2017-14491.patch \
5 file://0002-CVE-2017-14491.patch \
6"