summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Borg <martin.borg@enea.com>2018-02-28 09:33:50 +0100
committerMartin Borg <martin.borg@enea.com>2018-02-28 09:33:50 +0100
commit495b231e8e0da5046b6b1803d372fe33d0b14be9 (patch)
tree63a15b7f1e71be9c3ab4f2ee829e9b59e2f0515f
parent75578eccbe6c1de6b437e1599fe674e6b7ee2db1 (diff)
downloadmeta-el-common-495b231e8e0da5046b6b1803d372fe33d0b14be9.tar.gz
Drop CVE patches that have been fixed in upstream poky/rocko
Signed-off-by: Martin Borg <martin.borg@enea.com>
-rw-r--r--recipes-connectivity/bind/bind/0001-fix-back-port-issue.patch29
-rw-r--r--recipes-connectivity/bind/bind/CVE-2016-9444.patch186
-rw-r--r--recipes-connectivity/bind/bind/CVE-2017-3135.patch30
-rw-r--r--recipes-connectivity/bind/bind/CVE-2017-3136.patch47
-rw-r--r--recipes-connectivity/bind/bind_%.bbappend7
-rw-r--r--recipes-core/glibc/glibc/CVE-2017-1000366.patch53
-rw-r--r--recipes-core/glibc/glibc/CVE-2017-12132.patch866
-rw-r--r--recipes-core/glibc/glibc/CVE-2017-8804.patch225
-rw-r--r--recipes-core/glibc/glibc_%.bbappend8
-rw-r--r--recipes-core/systemd/systemd/CVE-2017-9445.patch56
-rw-r--r--recipes-core/systemd/systemd_%.bbappend6
-rw-r--r--recipes-devtools/dpkg/dpkg/CVE-2017-8283.patch190
-rw-r--r--recipes-devtools/dpkg/dpkg/test-case-for-CVE-2017-8283.patch83
-rw-r--r--recipes-devtools/dpkg/dpkg_%.bbappend6
-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/CVE-2017-14492.patch57
-rw-r--r--recipes-networking/dnsmasq/dnsmasq/CVE-2017-14493.patch55
-rw-r--r--recipes-networking/dnsmasq/dnsmasq/CVE-2017-14494.patch55
-rw-r--r--recipes-networking/dnsmasq/dnsmasq/CVE-2017-14495.patch69
-rw-r--r--recipes-networking/dnsmasq/dnsmasq/CVE-2017-14496.patch94
-rw-r--r--recipes-networking/dnsmasq/dnsmasq_%.bbappend11
22 files changed, 0 insertions, 2475 deletions
diff --git a/recipes-connectivity/bind/bind/0001-fix-back-port-issue.patch b/recipes-connectivity/bind/bind/0001-fix-back-port-issue.patch
deleted file mode 100644
index a874469..0000000
--- a/recipes-connectivity/bind/bind/0001-fix-back-port-issue.patch
+++ /dev/null
@@ -1,29 +0,0 @@
1From 6bed6ea11b1880e0a078bd02c1d31d21f0540583 Mon Sep 17 00:00:00 2001
2From: Mark Andrews <marka@isc.org>
3Date: Thu, 29 Dec 2016 10:48:46 +1100
4Subject: [PATCH] fix back port issue
5
6This patch is needed for CVE-2016-9444 fix.
7Upstream-Status: Backport [backport from v9_10_6_patch: https://source.isc.org/cgi-bin/gitweb.cgi?p=bind9.git;a=patch;h=6bed6ea11b1880e0a078bd02c1d31d21f0540583]
8
9Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
10---
11 lib/dns/message.c | 2 +-
12 1 file changed, 1 insertion(+), 1 deletion(-)
13
14diff --git a/lib/dns/message.c b/lib/dns/message.c
15index fe8e5d0..5b8166a 100644
16--- a/lib/dns/message.c
17+++ b/lib/dns/message.c
18@@ -1639,7 +1639,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
19 ((msg->flags & DNS_MESSAGEFLAG_TC) == 0) &&
20 !preserve_order &&
21 !auth_signed(section))
22- DO_ERROR(DNS_R_FORMERR);
23+ DO_FORMERR;
24
25 if (seen_problem)
26 return (DNS_R_RECOVERABLE);
27--
281.9.1
29
diff --git a/recipes-connectivity/bind/bind/CVE-2016-9444.patch b/recipes-connectivity/bind/bind/CVE-2016-9444.patch
deleted file mode 100644
index 2c1e125..0000000
--- a/recipes-connectivity/bind/bind/CVE-2016-9444.patch
+++ /dev/null
@@ -1,186 +0,0 @@
1From 254d55749ccb1129e7d021a51d0c3b7d3da26ee1 Mon Sep 17 00:00:00 2001
2From: Sona Sarmadi <sona.sarmadi@enea.com>
3Date: Tue, 12 Sep 2017 14:13:28 +0200
4Subject: [PATCH] CVE-2016-9444
5
6An unusually-formed DS record response could cause an assertion failure
7
8CVE: CVE-2016-9444
9Upstream-Status: Backport [backport from remotes/origin/v9_10_6_patch
10https://source.isc.org/cgi-bin/gitweb.cgi?p=bind9.git;a=commit;h=04c7ee66b1eda851737cc7582a2a88193a0b4118]
11
12Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
13---
14 CHANGES | 4 +++
15 lib/dns/message.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++---
16 lib/dns/resolver.c | 21 ++++++---------
17 3 files changed, 85 insertions(+), 16 deletions(-)
18
19diff --git a/CHANGES b/CHANGES
20index 97d2e60..5760ca5 100644
21--- a/CHANGES
22+++ b/CHANGES
23@@ -1,3 +1,7 @@
24+4517. [security] Named could mishandle authority sections that were
25+ missing RRSIGs triggering an assertion failure.
26+ (CVE-2016-9444) [RT # 43632]
27+
28 4504. [security] Allow the maximum number of records in a zone to
29 be specified. This provides a control for issues
30 raised in CVE-2016-6170. [RT #42143]
31diff --git a/lib/dns/message.c b/lib/dns/message.c
32index 0dd4c77..2e37dac 100644
33--- a/lib/dns/message.c
34+++ b/lib/dns/message.c
35@@ -1171,6 +1171,63 @@ update(dns_section_t section, dns_rdataclass_t rdclass) {
36 return (ISC_FALSE);
37 }
38
39+/*
40+ * Check to confirm that all DNSSEC records (DS, NSEC, NSEC3) have
41+ * covering RRSIGs.
42+ */
43+static isc_boolean_t
44+auth_signed(dns_namelist_t *section) {
45+ dns_name_t *name;
46+
47+ for (name = ISC_LIST_HEAD(*section);
48+ name != NULL;
49+ name = ISC_LIST_NEXT(name, link))
50+ {
51+ int auth_dnssec = 0, auth_rrsig = 0;
52+ dns_rdataset_t *rds;
53+
54+ for (rds = ISC_LIST_HEAD(name->list);
55+ rds != NULL;
56+ rds = ISC_LIST_NEXT(rds, link))
57+ {
58+ switch (rds->type) {
59+ case dns_rdatatype_ds:
60+ auth_dnssec |= 0x1;
61+ break;
62+ case dns_rdatatype_nsec:
63+ auth_dnssec |= 0x2;
64+ break;
65+ case dns_rdatatype_nsec3:
66+ auth_dnssec |= 0x4;
67+ break;
68+ case dns_rdatatype_rrsig:
69+ break;
70+ default:
71+ continue;
72+ }
73+
74+ switch (rds->covers) {
75+ case dns_rdatatype_ds:
76+ auth_rrsig |= 0x1;
77+ break;
78+ case dns_rdatatype_nsec:
79+ auth_rrsig |= 0x2;
80+ break;
81+ case dns_rdatatype_nsec3:
82+ auth_rrsig |= 0x4;
83+ break;
84+ default:
85+ break;
86+ }
87+ }
88+
89+ if (auth_dnssec != auth_rrsig)
90+ return (ISC_FALSE);
91+ }
92+
93+ return (ISC_TRUE);
94+}
95+
96 static isc_result_t
97 getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
98 dns_section_t sectionid, unsigned int options)
99@@ -1196,12 +1253,12 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
100 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
101 seen_problem = ISC_FALSE;
102
103+ section = &msg->sections[sectionid];
104+
105 for (count = 0; count < msg->counts[sectionid]; count++) {
106 int recstart = source->current;
107 isc_boolean_t skip_name_search, skip_type_search;
108
109- section = &msg->sections[sectionid];
110-
111 skip_name_search = ISC_FALSE;
112 skip_type_search = ISC_FALSE;
113 free_rdataset = ISC_FALSE;
114@@ -1364,7 +1421,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
115 goto cleanup;
116 rdata->rdclass = rdclass;
117 issigzero = ISC_FALSE;
118- if (rdtype == dns_rdatatype_rrsig &&
119+ if (rdtype == dns_rdatatype_rrsig &&
120 rdata->flags == 0) {
121 covers = dns_rdata_covers(rdata);
122 if (covers == 0)
123@@ -1575,6 +1632,19 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
124 INSIST(free_rdataset == ISC_FALSE);
125 }
126
127+ /*
128+ * If any of DS, NSEC or NSEC3 appeared in the
129+ * authority section of a query response without
130+ * a covering RRSIG, FORMERR
131+ */
132+ if (sectionid == DNS_SECTION_AUTHORITY &&
133+ msg->opcode == dns_opcode_query &&
134+ ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) &&
135+ ((msg->flags & DNS_MESSAGEFLAG_TC) == 0) &&
136+ !preserve_order &&
137+ !auth_signed(section))
138+ DO_ERROR(DNS_R_FORMERR);
139+
140 if (seen_problem)
141 return (DNS_R_RECOVERABLE);
142 return (ISC_R_SUCCESS);
143diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
144index b8fa6b3..017b4ba 100644
145--- a/lib/dns/resolver.c
146+++ b/lib/dns/resolver.c
147@@ -5435,16 +5435,13 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
148 rdataset->type,
149 &noqname);
150 if (tresult == ISC_R_SUCCESS &&
151- noqname != NULL) {
152- tresult =
153- dns_rdataset_addnoqname(
154+ noqname != NULL)
155+ (void) dns_rdataset_addnoqname(
156 rdataset, noqname);
157- RUNTIME_CHECK(tresult ==
158- ISC_R_SUCCESS);
159- }
160 }
161- if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0)
162- options = DNS_DBADD_PREFETCH;
163+ if ((fctx->options &
164+ DNS_FETCHOPT_PREFETCH) != 0)
165+ options = DNS_DBADD_PREFETCH;
166 addedrdataset = ardataset;
167 result = dns_db_addrdataset(fctx->cache, node,
168 NULL, now, rdataset,
169@@ -5584,11 +5581,9 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
170 tresult = findnoqname(fctx, name,
171 rdataset->type, &noqname);
172 if (tresult == ISC_R_SUCCESS &&
173- noqname != NULL) {
174- tresult = dns_rdataset_addnoqname(
175- rdataset, noqname);
176- RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
177- }
178+ noqname != NULL)
179+ (void) dns_rdataset_addnoqname(
180+ rdataset, noqname);
181 }
182
183 /*
184--
1851.9.1
186
diff --git a/recipes-connectivity/bind/bind/CVE-2017-3135.patch b/recipes-connectivity/bind/bind/CVE-2017-3135.patch
deleted file mode 100644
index 8cb2340..0000000
--- a/recipes-connectivity/bind/bind/CVE-2017-3135.patch
+++ /dev/null
@@ -1,30 +0,0 @@
1From 6106ed6841b253c78c6120be24c8722d6310a9b9 Mon Sep 17 00:00:00 2001
2From: Mark Andrews <marka@isc.org>
3Date: Tue, 31 Jan 2017 11:20:03 +1100
4Subject: [PATCH] add a REQUIRE to catch the NULL pointer dereference that
5 triggered CVE-2017-3135
6
7CVE: CVE-2017-3135
8Upstream-Status: Backport [backport from remotes/origin/v9_10]
9
10(cherry picked from commit 1d8995d226d8bca96b8ba286316018be4b7835f2)
11Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
12---
13 lib/dns/rdataset.c | 1 +
14 1 file changed, 1 insertion(+)
15
16diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c
17index 1870394..79bcecb 100644
18--- a/lib/dns/rdataset.c
19+++ b/lib/dns/rdataset.c
20@@ -338,6 +338,7 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
21 */
22
23 REQUIRE(DNS_RDATASET_VALID(rdataset));
24+ REQUIRE(rdataset->methods != NULL);
25 REQUIRE(countp != NULL);
26 REQUIRE((order == NULL) == (order_arg == NULL));
27 REQUIRE(cctx != NULL && cctx->mctx != NULL);
28--
291.9.1
30
diff --git a/recipes-connectivity/bind/bind/CVE-2017-3136.patch b/recipes-connectivity/bind/bind/CVE-2017-3136.patch
deleted file mode 100644
index c47a6f7..0000000
--- a/recipes-connectivity/bind/bind/CVE-2017-3136.patch
+++ /dev/null
@@ -1,47 +0,0 @@
1From cdb44bbabefa96fceb9bca540f5112493756d593 Mon Sep 17 00:00:00 2001
2From: Sona Sarmadi <sona.sarmadi@enea.com>
3Date: Wed, 27 Sep 2017 09:45:10 +0200
4Subject: [PATCH] Dns64 with break-dnssec yes; can result in a assertion
5 failure.
6
7From 764240ca07ab1b796226d5402ccd9fbfa77ec32a Mon Sep 17 00:00:00 2001
8From: Mark Andrews <marka@isc.org>
9Date: Wed, 15 Feb 2017 12:18:51 +1100
10
11(cherry picked from commit 3bce12e4b6d37f570ffc7747b499f8b90e8521ac)
12
13CVE: CVE-2017-3136
14Upstream-Status: Backport [backport from remotes/origin/v9_10]
15
16Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
17---
18 CHANGES | 3 +++
19 bin/named/query.c | 1 +
20 2 files changed, 4 insertions(+)
21
22diff --git a/CHANGES b/CHANGES
23index ec11967..ba27df0 100644
24--- a/CHANGES
25+++ b/CHANGES
26@@ -1,3 +1,6 @@
27+4575. [security] Dns64 with break-dnssec yes; can result in a
28+ assertion failure. (CVE-2017-3136) [RT #44653]
29+
30 4517. [security] Named could mishandle authority sections that were
31 missing RRSIGs triggering an assertion failure.
32 (CVE-2016-9444) [RT # 43632]
33diff --git a/bin/named/query.c b/bin/named/query.c
34index 1398776..48822ff 100644
35--- a/bin/named/query.c
36+++ b/bin/named/query.c
37@@ -8149,6 +8149,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
38 result = query_dns64(client, &fname, rdataset,
39 sigrdataset, dbuf,
40 DNS_SECTION_ANSWER);
41+ noqname = NULL;
42 dns_rdataset_disassociate(rdataset);
43 dns_message_puttemprdataset(client->message, &rdataset);
44 if (result == ISC_R_NOMORE) {
45--
461.9.1
47
diff --git a/recipes-connectivity/bind/bind_%.bbappend b/recipes-connectivity/bind/bind_%.bbappend
deleted file mode 100644
index 0461313..0000000
--- a/recipes-connectivity/bind/bind_%.bbappend
+++ /dev/null
@@ -1,7 +0,0 @@
1FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
2
3SRC_URI += "file://CVE-2016-9444.patch \
4 file://0001-fix-back-port-issue.patch \
5 file://CVE-2017-3135.patch \
6 file://CVE-2017-3136.patch \
7 "
diff --git a/recipes-core/glibc/glibc/CVE-2017-1000366.patch b/recipes-core/glibc/glibc/CVE-2017-1000366.patch
deleted file mode 100644
index 8ba9c5c..0000000
--- a/recipes-core/glibc/glibc/CVE-2017-1000366.patch
+++ /dev/null
@@ -1,53 +0,0 @@
1From f6110a8fee2ca36f8e2d2abecf3cba9fa7b8ea7d Mon Sep 17 00:00:00 2001
2From: Florian Weimer <fweimer@redhat.com>
3Date: Mon, 19 Jun 2017 17:09:55 +0200
4Subject: [PATCH] CVE-2017-1000366: Ignore LD_LIBRARY_PATH for AT_SECURE=1
5 programs [BZ #21624]
6
7LD_LIBRARY_PATH can only be used to reorder system search paths, which
8is not useful functionality.
9
10This makes an exploitable unbounded alloca in _dl_init_paths unreachable
11for AT_SECURE=1 programs.
12
13CVE: CVE-2017-1000366
14Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=3c7cd21290cabdadd72984fb69bc51e64ff1002d]
15
16Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
17---
18 ChangeLog | 7 +++++++
19 elf/rtld.c | 3 ++-
20 2 files changed, 9 insertions(+), 1 deletion(-)
21
22diff --git a/ChangeLog b/ChangeLog
23index f140ee6..7bfdf45 100644
24--- a/ChangeLog
25+++ b/ChangeLog
26@@ -1,3 +1,10 @@
27+2017-06-19 Florian Weimer <fweimer@redhat.com>
28+
29+ [BZ #21624]
30+ CVE-2017-1000366
31+ * elf/rtld.c (process_envvars): Ignore LD_LIBRARY_PATH for
32+ __libc_enable_secure.
33+
34 2017-02-05 Siddhesh Poyarekar <siddhesh@sourceware.org>
35
36 * version.h (RELEASE): Set to "stable"
37diff --git a/elf/rtld.c b/elf/rtld.c
38index a036ece..2fc33a6 100644
39--- a/elf/rtld.c
40+++ b/elf/rtld.c
41@@ -2418,7 +2418,8 @@ process_envvars (enum mode *modep)
42
43 case 12:
44 /* The library search path. */
45- if (memcmp (envline, "LIBRARY_PATH", 12) == 0)
46+ if (!__libc_enable_secure
47+ && memcmp (envline, "LIBRARY_PATH", 12) == 0)
48 {
49 library_path = &envline[13];
50 break;
51--
521.9.1
53
diff --git a/recipes-core/glibc/glibc/CVE-2017-12132.patch b/recipes-core/glibc/glibc/CVE-2017-12132.patch
deleted file mode 100644
index dc184db..0000000
--- a/recipes-core/glibc/glibc/CVE-2017-12132.patch
+++ /dev/null
@@ -1,866 +0,0 @@
1From 44cf81c6c008316876cfcc8208ae982621949e0e Mon Sep 17 00:00:00 2001
2From: Sona Sarmadi <sona.sarmadi@enea.com>
3Date: Mon, 11 Sep 2017 10:55:45 +0200
4Subject: [PATCH] glibc: CVE-2017-12132
5
6From e14a27723cc3a154d67f3f26e719d08c0ba9ad25 Mon Sep 17 00:00:00 2001
7From: Florian Weimer <fweimer@redhat.com>
8Date: Thu, 13 Apr 2017 13:09:38 +0200
9Subject: [PATCH] resolv: Reduce EDNS payload size to 1200 bytes [BZ #21361]
10
11This hardens the stub resolver against fragmentation-based attacks.
12
13CVE: CVE-2017-12132
14Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=e14a27723cc3a154d67f3f26e719d08c0ba9ad25]
15
16Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
17---
18 ChangeLog | 21 ++
19 include/resolv.h | 3 -
20 resolv/Makefile | 2 +
21 resolv/res_mkquery.c | 28 ++-
22 resolv/res_query.c | 23 ++-
23 resolv/resolv-internal.h | 18 ++
24 resolv/tst-resolv-edns.c | 501 +++++++++++++++++++++++++++++++++++++++++++++++
25 support/resolv_test.c | 56 +++++-
26 support/resolv_test.h | 11 ++
27 9 files changed, 650 insertions(+), 13 deletions(-)
28 create mode 100644 resolv/tst-resolv-edns.c
29
30diff --git a/ChangeLog b/ChangeLog
31index 7bfdf45..a0c2f51 100644
32--- a/ChangeLog
33+++ b/ChangeLog
34@@ -1,3 +1,24 @@
35+2017-04-13 Florian Weimer <fweimer@redhat.com>
36+
37+ [BZ #21361]
38+ Limit EDNS buffer size to 1200 bytes.
39+ * include/resolv.h (__res_nopt): Remove declaration.
40+ * resolv/Makefile (tests): tst-resolv-edns.
41+ (tst-resolv-edns): Link with -lresolv, -lpthread.
42+ * resolv/res_mkquery.c (__res_ntop): Limit EDNS buffer size to the
43+ interval [512, 1200].
44+ * resolv/res_query.c (__libc_res_nquery): Use 1200 buffer size if
45+ we can resize the buffer.
46+ * resolv/resolv-internal.h (RESOLV_EDNS_BUFFER_SIZE): Define.
47+ (__res_nopt): Declare.
48+ * resolv/tst-resolv-edns.c: New file.
49+ * resolv/resolv_test.h (struct resolv_edns_info): Define.
50+ (struct resolv_response_context): Add edns member.
51+ * resolv/resolv_test.c (struct query_info): Add edns member.
52+ (parse_query): Extract EDNS information from the query.
53+ (server_thread_udp_process_one): Propagate EDNS data.
54+ (server_thread_tcp_client): Likewise.
55+
56 2017-06-19 Florian Weimer <fweimer@redhat.com>
57
58 [BZ #21624]
59diff --git a/include/resolv.h b/include/resolv.h
60index 95dcd3c..e8f477c 100644
61--- a/include/resolv.h
62+++ b/include/resolv.h
63@@ -37,8 +37,6 @@ extern void res_pquery (const res_state __statp, const unsigned char *__msg,
64 extern int res_ourserver_p (const res_state __statp,
65 const struct sockaddr_in6 *__inp);
66 extern void __res_iclose (res_state statp, bool free_addr);
67-extern int __res_nopt(res_state statp, int n0, unsigned char *buf, int buflen,
68- int anslen);
69 libc_hidden_proto (__res_ninit)
70 libc_hidden_proto (__res_maybe_init)
71 libc_hidden_proto (__res_nclose)
72@@ -91,7 +89,6 @@ libresolv_hidden_proto (__res_nameinquery)
73 libresolv_hidden_proto (__res_queriesmatch)
74 libresolv_hidden_proto (__res_nsend)
75 libresolv_hidden_proto (__b64_ntop)
76-libresolv_hidden_proto (__res_nopt)
77 libresolv_hidden_proto (__dn_count_labels)
78 libresolv_hidden_proto (__p_secstodate)
79
80diff --git a/resolv/Makefile b/resolv/Makefile
81index fdc37ed..01086d5 100644
82--- a/resolv/Makefile
83+++ b/resolv/Makefile
84@@ -46,6 +46,7 @@ tests += \
85 tst-res_hconf_reorder \
86 tst-res_use_inet6 \
87 tst-resolv-basic \
88+ tst-resolv-edns \
89 tst-resolv-network \
90 tst-resolv-search \
91
92@@ -124,6 +125,7 @@ $(objpfx)tst-bug18665-tcp: $(objpfx)libresolv.so $(shared-thread-library)
93 $(objpfx)tst-bug18665: $(objpfx)libresolv.so $(shared-thread-library)
94 $(objpfx)tst-res_use_inet6: $(objpfx)libresolv.so $(shared-thread-library)
95 $(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
96+$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
97 $(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
98 $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
99 $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
100diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
101index d80b531..5a0bb10 100644
102--- a/resolv/res_mkquery.c
103+++ b/resolv/res_mkquery.c
104@@ -69,7 +69,7 @@
105 #include <netinet/in.h>
106 #include <arpa/nameser.h>
107 #include <netdb.h>
108-#include <resolv.h>
109+#include <resolv/resolv-internal.h>
110 #include <stdio.h>
111 #include <string.h>
112 #include <sys/time.h>
113@@ -243,7 +243,30 @@ __res_nopt(res_state statp,
114 *cp++ = 0; /* "." */
115
116 NS_PUT16(T_OPT, cp); /* TYPE */
117- NS_PUT16(MIN(anslen, 0xffff), cp); /* CLASS = UDP payload size */
118+
119+ /* Lowering the advertised buffer size based on the actual
120+ answer buffer size is desirable because the server will
121+ minimize the reply to fit into the UDP packet (and A
122+ non-minimal response might not fit the buffer).
123+
124+ The RESOLV_EDNS_BUFFER_SIZE limit could still result in TCP
125+ fallback and a non-minimal response which has to be
126+ hard-truncated in the stub resolver, but this is price to
127+ pay for avoiding fragmentation. (This issue does not
128+ affect the nss_dns functions because they use the stub
129+ resolver in such a way that it allocates a properly sized
130+ response buffer.) */
131+ {
132+ uint16_t buffer_size;
133+ if (anslen < 512)
134+ buffer_size = 512;
135+ else if (anslen > RESOLV_EDNS_BUFFER_SIZE)
136+ buffer_size = RESOLV_EDNS_BUFFER_SIZE;
137+ else
138+ buffer_size = anslen;
139+ NS_PUT16 (buffer_size, cp);
140+ }
141+
142 *cp++ = NOERROR; /* extended RCODE */
143 *cp++ = 0; /* EDNS version */
144
145@@ -261,4 +284,3 @@ __res_nopt(res_state statp,
146
147 return cp - buf;
148 }
149-libresolv_hidden_def (__res_nopt)
150diff --git a/resolv/res_query.c b/resolv/res_query.c
151index 07dc6f6..57156d0 100644
152--- a/resolv/res_query.c
153+++ b/resolv/res_query.c
154@@ -77,6 +77,7 @@
155 #include <stdio.h>
156 #include <stdlib.h>
157 #include <string.h>
158+#include <resolv/resolv-internal.h>
159
160 /* Options. Leave them on. */
161 /* #undef DEBUG */
162@@ -146,7 +147,10 @@ __libc_res_nquery(res_state statp,
163 if ((oflags & RES_F_EDNS0ERR) == 0
164 && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
165 {
166- n = __res_nopt(statp, n, query1, bufsize, anslen / 2);
167+ /* Use RESOLV_EDNS_BUFFER_SIZE because the receive
168+ buffer can be reallocated. */
169+ n = __res_nopt (statp, n, query1, bufsize,
170+ RESOLV_EDNS_BUFFER_SIZE);
171 if (n < 0)
172 goto unspec_nomem;
173 }
174@@ -167,8 +171,10 @@ __libc_res_nquery(res_state statp,
175 if (n > 0
176 && (oflags & RES_F_EDNS0ERR) == 0
177 && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
178- n = __res_nopt(statp, n, query2, bufsize - nused - n,
179- anslen / 2);
180+ /* Use RESOLV_EDNS_BUFFER_SIZE because the receive
181+ buffer can be reallocated. */
182+ n = __res_nopt (statp, n, query2, bufsize,
183+ RESOLV_EDNS_BUFFER_SIZE);
184 nquery2 = n;
185 }
186
187@@ -182,7 +188,16 @@ __libc_res_nquery(res_state statp,
188 if (n > 0
189 && (oflags & RES_F_EDNS0ERR) == 0
190 && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
191- n = __res_nopt(statp, n, query1, bufsize, anslen);
192+ {
193+ /* Use RESOLV_EDNS_BUFFER_SIZE if the receive buffer
194+ can be reallocated. */
195+ size_t advertise;
196+ if (answerp == NULL)
197+ advertise = anslen;
198+ else
199+ advertise = RESOLV_EDNS_BUFFER_SIZE;
200+ n = __res_nopt (statp, n, query1, bufsize, advertise);
201+ }
202
203 nquery1 = n;
204 }
205diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h
206index 99fc17c..76fbe2f 100644
207--- a/resolv/resolv-internal.h
208+++ b/resolv/resolv-internal.h
209@@ -32,4 +32,22 @@ res_use_inet6 (void)
210 return _res.options & DEPRECATED_RES_USE_INET6;
211 }
212
213+enum
214+ {
215+ /* The advertized EDNS buffer size. The value 1200 is derived
216+ from the IPv6 minimum MTU (1280 bytes) minus some arbitrary
217+ space for tunneling overhead. If the DNS server does not react
218+ to ICMP Fragmentation Needed But DF Set messages, this should
219+ avoid all UDP fragments on current networks. Avoiding UDP
220+ fragments is desirable because it prevents fragmentation-based
221+ spoofing attacks because the randomness in a DNS packet is
222+ concentrated in the first fragment (with the headers) and does
223+ not protect subsequent fragments. */
224+ RESOLV_EDNS_BUFFER_SIZE = 1200,
225+ };
226+
227+/* Add an OPT record to a DNS query. */
228+int __res_nopt (res_state, int n0, unsigned char *buf, int buflen,
229+ int anslen) attribute_hidden;
230+
231 #endif /* _RESOLV_INTERNAL_H */
232diff --git a/resolv/tst-resolv-edns.c b/resolv/tst-resolv-edns.c
233new file mode 100644
234index 0000000..f17dbc3
235--- /dev/null
236+++ b/resolv/tst-resolv-edns.c
237@@ -0,0 +1,501 @@
238+/* Test EDNS handling in the stub resolver.
239+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
240+ This file is part of the GNU C Library.
241+
242+ The GNU C Library is free software; you can redistribute it and/or
243+ modify it under the terms of the GNU Lesser General Public
244+ License as published by the Free Software Foundation; either
245+ version 2.1 of the License, or (at your option) any later version.
246+
247+ The GNU C Library is distributed in the hope that it will be useful,
248+ but WITHOUT ANY WARRANTY; without even the implied warranty of
249+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
250+ Lesser General Public License for more details.
251+
252+ You should have received a copy of the GNU Lesser General Public
253+ License along with the GNU C Library; if not, see
254+ <http://www.gnu.org/licenses/>. */
255+
256+#include <errno.h>
257+#include <netdb.h>
258+#include <stdio.h>
259+#include <stdlib.h>
260+#include <string.h>
261+#include <support/check.h>
262+#include <support/resolv_test.h>
263+#include <support/support.h>
264+#include <support/test-driver.h>
265+#include <support/xthread.h>
266+
267+/* Data produced by a test query. */
268+struct response_data
269+{
270+ char *qname;
271+ uint16_t qtype;
272+ struct resolv_edns_info edns;
273+};
274+
275+/* Global array used by put_response and get_response to record
276+ response data. The test DNS server returns the index of the array
277+ element which contains the actual response data. This enables the
278+ test case to return arbitrary amounts of data with the limited
279+ number of bits which fit into an IP addres.
280+
281+ The volatile specifier is needed because the test case accesses
282+ these variables from a callback function called from a function
283+ which is marked as __THROW (i.e., a leaf function which actually is
284+ not). */
285+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
286+static struct response_data ** volatile response_data_array;
287+volatile static size_t response_data_count;
288+
289+/* Extract information from the query, store it in a struct
290+ response_data object, and return its index in the
291+ response_data_array. */
292+static unsigned int
293+put_response (const struct resolv_response_context *ctx,
294+ const char *qname, uint16_t qtype)
295+{
296+ xpthread_mutex_lock (&mutex);
297+ ++response_data_count;
298+ /* We only can represent 2**24 indexes in 10.0.0.0/8. */
299+ TEST_VERIFY (response_data_count < (1 << 24));
300+ response_data_array = xrealloc
301+ (response_data_array, sizeof (*response_data_array) * response_data_count);
302+ unsigned int index = response_data_count - 1;
303+ struct response_data *data = xmalloc (sizeof (*data));
304+ *data = (struct response_data)
305+ {
306+ .qname = xstrdup (qname),
307+ .qtype = qtype,
308+ .edns = ctx->edns,
309+ };
310+ response_data_array[index] = data;
311+ xpthread_mutex_unlock (&mutex);
312+ return index;
313+}
314+
315+/* Verify the index into the response_data array and return the data
316+ at it. */
317+static struct response_data *
318+get_response (unsigned int index)
319+{
320+ xpthread_mutex_lock (&mutex);
321+ TEST_VERIFY_EXIT (index < response_data_count);
322+ struct response_data *result = response_data_array[index];
323+ xpthread_mutex_unlock (&mutex);
324+ return result;
325+}
326+
327+/* Deallocate all response data. */
328+static void
329+free_response_data (void)
330+{
331+ xpthread_mutex_lock (&mutex);
332+ size_t count = response_data_count;
333+ struct response_data **array = response_data_array;
334+ for (unsigned int i = 0; i < count; ++i)
335+ {
336+ struct response_data *data = array[i];
337+ free (data->qname);
338+ free (data);
339+ }
340+ free (array);
341+ response_data_array = NULL;
342+ response_data_count = 0;
343+ xpthread_mutex_unlock (&mutex);
344+}
345+
346+#define EDNS_PROBE_EXAMPLE "edns-probe.example"
347+
348+static void
349+response (const struct resolv_response_context *ctx,
350+ struct resolv_response_builder *b,
351+ const char *qname, uint16_t qclass, uint16_t qtype)
352+{
353+ TEST_VERIFY_EXIT (qname != NULL);
354+
355+ /* The "tcp." prefix can be used to request TCP fallback. */
356+ const char *qname_compare = qname;
357+ bool force_tcp;
358+ if (strncmp ("tcp.", qname_compare, strlen ("tcp.")) == 0)
359+ {
360+ force_tcp = true;
361+ qname_compare += strlen ("tcp.");
362+ }
363+ else
364+ force_tcp = false;
365+
366+ enum {edns_probe} requested_qname;
367+ if (strcmp (qname_compare, EDNS_PROBE_EXAMPLE) == 0)
368+ requested_qname = edns_probe;
369+ else
370+ {
371+ support_record_failure ();
372+ printf ("error: unexpected QNAME: %s\n", qname);
373+ return;
374+ }
375+ TEST_VERIFY_EXIT (qclass == C_IN);
376+ struct resolv_response_flags flags = {.tc = force_tcp && !ctx->tcp};
377+ resolv_response_init (b, flags);
378+ resolv_response_add_question (b, qname, qclass, qtype);
379+ if (flags.tc)
380+ return;
381+
382+ if (test_verbose)
383+ printf ("info: edns=%d payload_size=%d\n",
384+ ctx->edns.active, ctx->edns.payload_size);
385+
386+ /* Encode the response_data object in multiple address records.
387+ Each record carries two bytes of payload data, and an index. */
388+ resolv_response_section (b, ns_s_an);
389+ switch (requested_qname)
390+ {
391+ case edns_probe:
392+ {
393+ unsigned int index = put_response (ctx, qname, qtype);
394+ switch (qtype)
395+ {
396+ case T_A:
397+ {
398+ uint32_t addr = htonl (0x0a000000 | index);
399+ resolv_response_open_record (b, qname, qclass, qtype, 0);
400+ resolv_response_add_data (b, &addr, sizeof (addr));
401+ resolv_response_close_record (b);
402+ }
403+ break;
404+ case T_AAAA:
405+ {
406+ char addr[16]
407+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
408+ index >> 16, index >> 8, index};
409+ resolv_response_open_record (b, qname, qclass, qtype, 0);
410+ resolv_response_add_data (b, &addr, sizeof (addr));
411+ resolv_response_close_record (b);
412+ }
413+ }
414+ }
415+ break;
416+ }
417+}
418+
419+/* Update *DATA with data from ADDRESS of SIZE. Set the corresponding
420+ flag in SHADOW for each byte written. */
421+static struct response_data *
422+decode_address (const void *address, size_t size)
423+{
424+ switch (size)
425+ {
426+ case 4:
427+ TEST_VERIFY (memcmp (address, "\x0a", 1) == 0);
428+ break;
429+ case 16:
430+ TEST_VERIFY (memcmp (address, "\x20\x01\x0d\xb8", 4) == 0);
431+ break;
432+ default:
433+ FAIL_EXIT1 ("unexpected address size %zu", size);
434+ }
435+ const unsigned char *addr = address;
436+ unsigned int index = addr[size - 3] * 256 * 256
437+ + addr[size - 2] * 256
438+ + addr[size - 1];
439+ return get_response (index);
440+}
441+
442+static struct response_data *
443+decode_hostent (struct hostent *e)
444+{
445+ TEST_VERIFY_EXIT (e != NULL);
446+ TEST_VERIFY_EXIT (e->h_addr_list[0] != NULL);
447+ TEST_VERIFY (e->h_addr_list[1] == NULL);
448+ return decode_address (e->h_addr_list[0], e->h_length);
449+}
450+
451+static struct response_data *
452+decode_addrinfo (struct addrinfo *ai, int family)
453+{
454+ struct response_data *data = NULL;
455+ while (ai != NULL)
456+ {
457+ if (ai->ai_family == family)
458+ {
459+ struct response_data *new_data;
460+ switch (family)
461+ {
462+ case AF_INET:
463+ {
464+ struct sockaddr_in *pin = (struct sockaddr_in *) ai->ai_addr;
465+ new_data = decode_address (&pin->sin_addr.s_addr, 4);
466+ }
467+ break;
468+ case AF_INET6:
469+ {
470+ struct sockaddr_in6 *pin = (struct sockaddr_in6 *) ai->ai_addr;
471+ new_data = decode_address (&pin->sin6_addr.s6_addr, 16);
472+ }
473+ break;
474+ default:
475+ FAIL_EXIT1 ("invalid address family %d", ai->ai_family);
476+ }
477+ if (data == NULL)
478+ data = new_data;
479+ else
480+ /* Check pointer equality because this should be the same
481+ response (same index). */
482+ TEST_VERIFY (data == new_data);
483+ }
484+ ai = ai->ai_next;
485+ }
486+ TEST_VERIFY_EXIT (data != NULL);
487+ return data;
488+}
489+
490+/* Updated by the main test loop in accordance with what is set in
491+ _res.options. */
492+static bool use_edns;
493+static bool use_dnssec;
494+
495+/* Verify the decoded response data against the flags above. */
496+static void
497+verify_response_data_payload (struct response_data *data,
498+ size_t expected_payload)
499+{
500+ bool edns = use_edns || use_dnssec;
501+ TEST_VERIFY (data->edns.active == edns);
502+ if (!edns)
503+ expected_payload = 0;
504+ if (data->edns.payload_size != expected_payload)
505+ {
506+ support_record_failure ();
507+ printf ("error: unexpected payload size %d (edns=%d)\n",
508+ (int) data->edns.payload_size, edns);
509+ }
510+ uint16_t expected_flags = 0;
511+ if (use_dnssec)
512+ expected_flags |= 0x8000; /* DO flag. */
513+ if (data->edns.flags != expected_flags)
514+ {
515+ support_record_failure ();
516+ printf ("error: unexpected EDNS flags 0x%04x (edns=%d)\n",
517+ (int) data->edns.flags, edns);
518+ }
519+}
520+
521+/* Same as verify_response_data_payload, but use the default
522+ payload. */
523+static void
524+verify_response_data (struct response_data *data)
525+{
526+ verify_response_data_payload (data, 1200);
527+}
528+
529+static void
530+check_hostent (struct hostent *e)
531+{
532+ TEST_VERIFY_EXIT (e != NULL);
533+ verify_response_data (decode_hostent (e));
534+}
535+
536+static void
537+do_ai (int family)
538+{
539+ struct addrinfo hints = { .ai_family = family };
540+ struct addrinfo *ai;
541+ int ret = getaddrinfo (EDNS_PROBE_EXAMPLE, "80", &hints, &ai);
542+ TEST_VERIFY_EXIT (ret == 0);
543+ switch (family)
544+ {
545+ case AF_INET:
546+ case AF_INET6:
547+ verify_response_data (decode_addrinfo (ai, family));
548+ break;
549+ case AF_UNSPEC:
550+ verify_response_data (decode_addrinfo (ai, AF_INET));
551+ verify_response_data (decode_addrinfo (ai, AF_INET6));
552+ break;
553+ default:
554+ FAIL_EXIT1 ("invalid address family %d", family);
555+ }
556+ freeaddrinfo (ai);
557+}
558+
559+enum res_op
560+{
561+ res_op_search,
562+ res_op_query,
563+ res_op_querydomain,
564+ res_op_nsearch,
565+ res_op_nquery,
566+ res_op_nquerydomain,
567+
568+ res_op_last = res_op_nquerydomain,
569+};
570+
571+static const char *
572+res_op_string (enum res_op op)
573+{
574+ switch (op)
575+ {
576+ case res_op_search:
577+ return "res_search";
578+ case res_op_query:
579+ return "res_query";
580+ case res_op_querydomain:
581+ return "res_querydomain";
582+ case res_op_nsearch:
583+ return "res_nsearch";
584+ case res_op_nquery:
585+ return "res_nquery";
586+ case res_op_nquerydomain:
587+ return "res_nquerydomain";
588+ }
589+ FAIL_EXIT1 ("invalid res_op value %d", (int) op);
590+}
591+
592+/* Call libresolv function OP to look up PROBE_NAME, with an answer
593+ buffer of SIZE bytes. Check that the advertised UDP buffer size is
594+ in fact EXPECTED_BUFFER_SIZE. */
595+static void
596+do_res_search (const char *probe_name, enum res_op op, size_t size,
597+ size_t expected_buffer_size)
598+{
599+ if (test_verbose)
600+ printf ("info: testing %s with buffer size %zu\n",
601+ res_op_string (op), size);
602+ unsigned char *buffer = xmalloc (size);
603+ int ret = -1;
604+ switch (op)
605+ {
606+ case res_op_search:
607+ ret = res_search (probe_name, C_IN, T_A, buffer, size);
608+ break;
609+ case res_op_query:
610+ ret = res_query (probe_name, C_IN, T_A, buffer, size);
611+ break;
612+ case res_op_nsearch:
613+ ret = res_nsearch (&_res, probe_name, C_IN, T_A, buffer, size);
614+ break;
615+ case res_op_nquery:
616+ ret = res_nquery (&_res, probe_name, C_IN, T_A, buffer, size);
617+ break;
618+ case res_op_querydomain:
619+ case res_op_nquerydomain:
620+ {
621+ char *example_stripped = xstrdup (probe_name);
622+ char *dot_example = strstr (example_stripped, ".example");
623+ if (dot_example != NULL && strcmp (dot_example, ".example") == 0)
624+ {
625+ /* Truncate the domain name. */
626+ *dot_example = '\0';
627+ if (op == res_op_querydomain)
628+ ret = res_querydomain
629+ (example_stripped, "example", C_IN, T_A, buffer, size);
630+ else
631+ ret = res_nquerydomain
632+ (&_res, example_stripped, "example", C_IN, T_A, buffer, size);
633+ }
634+ else
635+ FAIL_EXIT1 ("invalid probe name: %s", probe_name);
636+ free (example_stripped);
637+ }
638+ break;
639+ }
640+ TEST_VERIFY_EXIT (ret > 12);
641+ unsigned char *end = buffer + ret;
642+
643+ HEADER *hd = (HEADER *) buffer;
644+ TEST_VERIFY (ntohs (hd->qdcount) == 1);
645+ TEST_VERIFY (ntohs (hd->ancount) == 1);
646+ /* Skip over the header. */
647+ unsigned char *p = buffer + sizeof (*hd);
648+ /* Skip over the question. */
649+ ret = dn_skipname (p, end);
650+ TEST_VERIFY_EXIT (ret > 0);
651+ p += ret;
652+ TEST_VERIFY_EXIT (end - p >= 4);
653+ p += 4;
654+ /* Skip over the RNAME and the RR header, but stop at the RDATA
655+ length. */
656+ ret = dn_skipname (p, end);
657+ TEST_VERIFY_EXIT (ret > 0);
658+ p += ret;
659+ TEST_VERIFY_EXIT (end - p >= 2 + 2 + 4 + 2 + 4);
660+ p += 2 + 2 + 4;
661+ /* The IP address should be 4 bytes long. */
662+ TEST_VERIFY_EXIT (p[0] == 0);
663+ TEST_VERIFY_EXIT (p[1] == 4);
664+ /* Extract the address information. */
665+ p += 2;
666+ struct response_data *data = decode_address (p, 4);
667+
668+ verify_response_data_payload (data, expected_buffer_size);
669+
670+ free (buffer);
671+}
672+
673+static void
674+run_test (const char *probe_name)
675+{
676+ if (test_verbose)
677+ printf ("\ninfo: * use_edns=%d use_dnssec=%d\n",
678+ use_edns, use_dnssec);
679+ check_hostent (gethostbyname (probe_name));
680+ check_hostent (gethostbyname2 (probe_name, AF_INET));
681+ check_hostent (gethostbyname2 (probe_name, AF_INET6));
682+ do_ai (AF_UNSPEC);
683+ do_ai (AF_INET);
684+ do_ai (AF_INET6);
685+
686+ for (int op = 0; op <= res_op_last; ++op)
687+ {
688+ do_res_search (probe_name, op, 301, 512);
689+ do_res_search (probe_name, op, 511, 512);
690+ do_res_search (probe_name, op, 512, 512);
691+ do_res_search (probe_name, op, 513, 513);
692+ do_res_search (probe_name, op, 657, 657);
693+ do_res_search (probe_name, op, 1199, 1199);
694+ do_res_search (probe_name, op, 1200, 1200);
695+ do_res_search (probe_name, op, 1201, 1200);
696+ do_res_search (probe_name, op, 65535, 1200);
697+ }
698+}
699+
700+static int
701+do_test (void)
702+{
703+ for (int do_edns = 0; do_edns < 2; ++do_edns)
704+ for (int do_dnssec = 0; do_dnssec < 2; ++do_dnssec)
705+ for (int do_tcp = 0; do_tcp < 2; ++do_tcp)
706+ {
707+ struct resolv_test *aux = resolv_test_start
708+ ((struct resolv_redirect_config)
709+ {
710+ .response_callback = response,
711+ });
712+
713+ use_edns = do_edns;
714+ if (do_edns)
715+ _res.options |= RES_USE_EDNS0;
716+ use_dnssec = do_dnssec;
717+ if (do_dnssec)
718+ _res.options |= RES_USE_DNSSEC;
719+
720+ char *probe_name = xstrdup (EDNS_PROBE_EXAMPLE);
721+ if (do_tcp)
722+ {
723+ char *n = xasprintf ("tcp.%s", probe_name);
724+ free (probe_name);
725+ probe_name = n;
726+ }
727+
728+ run_test (probe_name);
729+
730+ free (probe_name);
731+ resolv_test_end (aux);
732+ }
733+
734+ free_response_data ();
735+ return 0;
736+}
737+
738+#include <support/test-driver.c>
739diff --git a/support/resolv_test.c b/support/resolv_test.c
740index 2d0ea3c..6b3554f 100644
741--- a/support/resolv_test.c
742+++ b/support/resolv_test.c
743@@ -428,6 +428,7 @@ struct query_info
744 char qname[MAXDNAME];
745 uint16_t qclass;
746 uint16_t qtype;
747+ struct resolv_edns_info edns;
748 };
749
750 /* Update *INFO from the specified DNS packet. */
751@@ -435,10 +436,26 @@ static void
752 parse_query (struct query_info *info,
753 const unsigned char *buffer, size_t length)
754 {
755- if (length < 12)
756+ HEADER hd;
757+ _Static_assert (sizeof (hd) == 12, "DNS header size");
758+ if (length < sizeof (hd))
759 FAIL_EXIT1 ("malformed DNS query: too short: %zu bytes", length);
760-
761- int ret = dn_expand (buffer, buffer + length, buffer + 12,
762+ memcpy (&hd, buffer, sizeof (hd));
763+
764+ if (ntohs (hd.qdcount) != 1)
765+ FAIL_EXIT1 ("malformed DNS query: wrong question count: %d",
766+ (int) ntohs (hd.qdcount));
767+ if (ntohs (hd.ancount) != 0)
768+ FAIL_EXIT1 ("malformed DNS query: wrong answer count: %d",
769+ (int) ntohs (hd.ancount));
770+ if (ntohs (hd.nscount) != 0)
771+ FAIL_EXIT1 ("malformed DNS query: wrong authority count: %d",
772+ (int) ntohs (hd.nscount));
773+ if (ntohs (hd.arcount) > 1)
774+ FAIL_EXIT1 ("malformed DNS query: wrong additional count: %d",
775+ (int) ntohs (hd.arcount));
776+
777+ int ret = dn_expand (buffer, buffer + length, buffer + sizeof (hd),
778 info->qname, sizeof (info->qname));
779 if (ret < 0)
780 FAIL_EXIT1 ("malformed DNS query: cannot uncompress QNAME");
781@@ -456,6 +473,37 @@ parse_query (struct query_info *info,
782 memcpy (&qtype_qclass, buffer + 12 + ret, sizeof (qtype_qclass));
783 info->qclass = ntohs (qtype_qclass.qclass);
784 info->qtype = ntohs (qtype_qclass.qtype);
785+
786+ memset (&info->edns, 0, sizeof (info->edns));
787+ if (ntohs (hd.arcount) > 0)
788+ {
789+ /* Parse EDNS record. */
790+ struct __attribute__ ((packed, aligned (1)))
791+ {
792+ uint8_t root;
793+ uint16_t rtype;
794+ uint16_t payload;
795+ uint8_t edns_extended_rcode;
796+ uint8_t edns_version;
797+ uint16_t flags;
798+ uint16_t rdatalen;
799+ } rr;
800+ _Static_assert (sizeof (rr) == 11, "EDNS record size");
801+
802+ if (remaining < 4 + sizeof (rr))
803+ FAIL_EXIT1 ("mailformed DNS query: no room for EDNS record");
804+ memcpy (&rr, buffer + 12 + ret + 4, sizeof (rr));
805+ if (rr.root != 0)
806+ FAIL_EXIT1 ("malformed DNS query: invalid OPT RNAME: %d\n", rr.root);
807+ if (rr.rtype != htons (41))
808+ FAIL_EXIT1 ("malformed DNS query: invalid OPT type: %d\n",
809+ ntohs (rr.rtype));
810+ info->edns.active = true;
811+ info->edns.extended_rcode = rr.edns_extended_rcode;
812+ info->edns.version = rr.edns_version;
813+ info->edns.flags = ntohs (rr.flags);
814+ info->edns.payload_size = ntohs (rr.payload);
815+ }
816 }
817
818
819@@ -585,6 +633,7 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index)
820 .query_length = length,
821 .server_index = server_index,
822 .tcp = false,
823+ .edns = qinfo.edns,
824 };
825 struct resolv_response_builder *b = response_builder_allocate (query, length);
826 obj->config.response_callback
827@@ -820,6 +869,7 @@ server_thread_tcp_client (void *arg)
828 .query_length = query_length,
829 .server_index = closure->server_index,
830 .tcp = true,
831+ .edns = qinfo.edns,
832 };
833 struct resolv_response_builder *b = response_builder_allocate
834 (query_buffer, query_length);
835diff --git a/support/resolv_test.h b/support/resolv_test.h
836index 7a9f1f7..6498751 100644
837--- a/support/resolv_test.h
838+++ b/support/resolv_test.h
839@@ -25,6 +25,16 @@
840
841 __BEGIN_DECLS
842
843+/* Information about EDNS properties of a DNS query. */
844+struct resolv_edns_info
845+{
846+ bool active;
847+ uint8_t extended_rcode;
848+ uint8_t version;
849+ uint16_t flags;
850+ uint16_t payload_size;
851+};
852+
853 /* This struct provides context information when the response callback
854 specified in struct resolv_redirect_config is invoked. */
855 struct resolv_response_context
856@@ -33,6 +43,7 @@ struct resolv_response_context
857 size_t query_length;
858 int server_index;
859 bool tcp;
860+ struct resolv_edns_info edns;
861 };
862
863 /* This opaque struct is used to construct responses from within the
864--
8651.9.1
866
diff --git a/recipes-core/glibc/glibc/CVE-2017-8804.patch b/recipes-core/glibc/glibc/CVE-2017-8804.patch
deleted file mode 100644
index ae21ad0..0000000
--- a/recipes-core/glibc/glibc/CVE-2017-8804.patch
+++ /dev/null
@@ -1,225 +0,0 @@
1From 45619a54f7d751a2a7dec7d7ee323e1545b881af Mon Sep 17 00:00:00 2001
2From: Sona Sarmadi <sona.sarmadi@enea.com>
3Date: Mon, 11 Sep 2017 13:35:44 +0200
4Subject: [PATCH] CVE-2017-8804
5
6The xdr_bytes and xdr_string functions in the glibc or libc6 2.25 mishandle
7failures of buffer deserialization, which allows remote attackers to cause
8a denial of service (virtual memory allocation, or memory consumption if an
9overcommit setting is not used) via a crafted UDP packet to port 111, a
10related issue to CVE-2017-8779.
11
12CVE: CVE-2017-8804
13Upstream-Status: Backport [https://sourceware.org/ml/libc-alpha/2017-05/msg00105.html]
14
15Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
16---
17 NEWS | 3 ++
18 sunrpc/Makefile | 10 ++++++-
19 sunrpc/tst-xdrmem3.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++
20 sunrpc/xdr.c | 41 ++++++++++++++++++++------
21 4 files changed, 127 insertions(+), 10 deletions(-)
22 create mode 100644 sunrpc/tst-xdrmem3.c
23
24diff --git a/NEWS b/NEWS
25index ec15dde..29e795a 100644
26--- a/NEWS
27+++ b/NEWS
28@@ -211,6 +211,9 @@ Security related changes:
29 question type which is outside the range of valid question type values.
30 (CVE-2015-5180)
31
32+* The xdr_bytes and xdr_string routines free the internally allocated buffer
33+ if deserialization of the buffer contents fails for any reason.
34+
35 The following bugs are resolved with this release:
36
37 [4099] stdio: Overly agressive caching by stream i/o functions.
38diff --git a/sunrpc/Makefile b/sunrpc/Makefile
39index 0c1e612..12ec2e7 100644
40--- a/sunrpc/Makefile
41+++ b/sunrpc/Makefile
42@@ -93,9 +93,16 @@ rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \
43 extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs))
44 others += rpcgen
45
46-tests = tst-xdrmem tst-xdrmem2 test-rpcent
47+tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-xdrmem3
48 xtests := tst-getmyaddr
49
50+tests-special += $(objpfx)mtrace-tst-xdrmem3.out
51+generated += mtrace-tst-xdrmem3.out tst-xdrmem3.mtrace
52+tst-xdrmem3-ENV = MALLOC_TRACE=$(objpfx)tst-xdrmem3.mtrace
53+$(objpfx)mtrace-tst-xdrmem3.out: $(objpfx)tst-xdrmem3.out
54+ $(common-objpfx)malloc/mtrace $(objpfx)tst-xdrmem3.mtrace > $@; \
55+ $(evaluate-test)
56+
57 ifeq ($(have-thread-library),yes)
58 xtests += thrsvc
59 endif
60@@ -155,6 +162,7 @@ BUILD_CPPFLAGS += $(sunrpc-CPPFLAGS)
61 $(objpfx)tst-getmyaddr: $(common-objpfx)linkobj/libc.so
62 $(objpfx)tst-xdrmem: $(common-objpfx)linkobj/libc.so
63 $(objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so
64+(objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so
65
66 $(objpfx)rpcgen: $(addprefix $(objpfx),$(rpcgen-objs))
67
68diff --git a/sunrpc/tst-xdrmem3.c b/sunrpc/tst-xdrmem3.c
69new file mode 100644
70index 0000000..b3c72ae
71--- /dev/null
72+++ b/sunrpc/tst-xdrmem3.c
73@@ -0,0 +1,83 @@
74+/* Test xdr_bytes, xdr_string behavior on deserialization failure.
75+ Copyright (C) 2017 Free Software Foundation, Inc.
76+ This file is part of the GNU C Library.
77+
78+ The GNU C Library is free software; you can redistribute it and/or
79+ modify it under the terms of the GNU Lesser General Public
80+ License as published by the Free Software Foundation; either
81+ version 2.1 of the License, or (at your option) any later version.
82+
83+ The GNU C Library is distributed in the hope that it will be useful,
84+ but WITHOUT ANY WARRANTY; without even the implied warranty of
85+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
86+ Lesser General Public License for more details.
87+
88+ You should have received a copy of the GNU Lesser General Public
89+ License along with the GNU C Library; if not, see
90+ <http://www.gnu.org/licenses/>. */
91+
92+#include <mcheck.h>
93+#include <rpc/rpc.h>
94+#include <support/check.h>
95+#include <support/support.h>
96+
97+static int
98+do_test (void)
99+{
100+ mtrace ();
101+
102+ /* If do_own_buffer, allocate the buffer and pass it to the
103+ deserialization routine. Otherwise the routine is requested to
104+ allocate the buffer. */
105+ for (int do_own_buffer = 0; do_own_buffer < 2; ++do_own_buffer)
106+ {
107+ /* Length 16 MiB, but only 2 bytes of data in the packet. */
108+ unsigned char buf[] = "\x01\x00\x00\x00\xff";
109+ XDR xdrs;
110+ char *result;
111+ unsigned int result_len;
112+
113+ /* Test xdr_bytes. */
114+ xdrmem_create (&xdrs, (char *) buf, sizeof (buf), XDR_DECODE);
115+ result_len = 0;
116+ if (do_own_buffer)
117+ {
118+ char *own_buffer = xmalloc (10);
119+ result = own_buffer;
120+ TEST_VERIFY (!xdr_bytes (&xdrs, &result, &result_len, 10));
121+ TEST_VERIFY (result == own_buffer);
122+ free (own_buffer);
123+ }
124+ else
125+ {
126+ result = NULL;
127+ TEST_VERIFY (!xdr_bytes (&xdrs, &result, &result_len, -1));
128+ TEST_VERIFY (result == NULL);
129+ }
130+ TEST_VERIFY (result_len == 16 * 1024 * 1024);
131+ xdr_destroy (&xdrs);
132+
133+ /* Test xdr_string. */
134+ xdrmem_create (&xdrs, (char *) buf, sizeof (buf), XDR_DECODE);
135+ if (do_own_buffer)
136+ {
137+ char *own_buffer = xmalloc (10);
138+ result = own_buffer;
139+ TEST_VERIFY (!xdr_string (&xdrs, &result, 10));
140+ TEST_VERIFY (result == own_buffer);
141+ free (own_buffer);
142+ }
143+ else
144+ {
145+ result = NULL;
146+ TEST_VERIFY (!xdr_string (&xdrs, &result, -1));
147+ TEST_VERIFY (result == NULL);
148+ }
149+ xdr_destroy (&xdrs);
150+ }
151+
152+ return 0;
153+}
154+
155+#include <support/test-driver.c>
156+
157diff --git a/sunrpc/xdr.c b/sunrpc/xdr.c
158index bfabf33..857f7c8 100644
159--- a/sunrpc/xdr.c
160+++ b/sunrpc/xdr.c
161@@ -620,14 +620,24 @@ xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize)
162 }
163 if (sp == NULL)
164 {
165- *cpp = sp = (char *) mem_alloc (nodesize);
166+ sp = (char *) mem_alloc (nodesize);
167+ if (sp == NULL)
168+ {
169+ (void) __fxprintf (NULL, "%s: %s", __func__,
170+ _("out of memory\n"));
171+ return FALSE;
172+ }
173 }
174- if (sp == NULL)
175+ if (!xdr_opaque (xdrs, sp, nodesize))
176 {
177- (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
178+ if (sp != *cpp)
179+ /* *cpp was NULL, so this function allocated a new
180+ buffer. */
181+ free (sp);
182 return FALSE;
183 }
184- /* fall into ... */
185+ *cpp = sp;
186+ return TRUE;
187
188 case XDR_ENCODE:
189 return xdr_opaque (xdrs, sp, nodesize);
190@@ -781,14 +791,27 @@ xdr_string (XDR *xdrs, char **cpp, u_int maxsize)
191 {
192 case XDR_DECODE:
193 if (sp == NULL)
194- *cpp = sp = (char *) mem_alloc (nodesize);
195- if (sp == NULL)
196 {
197- (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
198- return FALSE;
199+ sp = (char *) mem_alloc (nodesize);
200+ if (sp == NULL)
201+ {
202+ (void) __fxprintf (NULL, "%s: %s", __func__,
203+ _("out of memory\n"));
204+ return FALSE;
205+ }
206 }
207 sp[size] = 0;
208- /* fall into ... */
209+
210+ if (!xdr_opaque (xdrs, sp, size))
211+ {
212+ if (sp != *cpp)
213+ /* *cpp was NULL, so this function allocated a new
214+ buffer. */
215+ free (sp);
216+ return FALSE;
217+ }
218+ *cpp = sp;
219+ return TRUE;
220
221 case XDR_ENCODE:
222 return xdr_opaque (xdrs, sp, size);
223--
2241.9.1
225
diff --git a/recipes-core/glibc/glibc_%.bbappend b/recipes-core/glibc/glibc_%.bbappend
deleted file mode 100644
index f2c9a31..0000000
--- a/recipes-core/glibc/glibc_%.bbappend
+++ /dev/null
@@ -1,8 +0,0 @@
1# look for files in the layer first
2FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
3
4SRC_URI += "file://CVE-2017-1000366.patch \
5 file://CVE-2017-12132.patch \
6 file://CVE-2017-8804.patch \
7 "
8
diff --git a/recipes-core/systemd/systemd/CVE-2017-9445.patch b/recipes-core/systemd/systemd/CVE-2017-9445.patch
deleted file mode 100644
index 031901d..0000000
--- a/recipes-core/systemd/systemd/CVE-2017-9445.patch
+++ /dev/null
@@ -1,56 +0,0 @@
1From db848813bae4d28c524b3b6a7dad135e426659ce Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
3Date: Sun, 18 Jun 2017 16:07:57 -0400
4Subject: [PATCH] resolved: simplify alloc size calculation
5
6The allocation size was calculated in a complicated way, and for values
7close to the page size we would actually allocate less than requested.
8
9Reported by Chris Coulson <chris.coulson@canonical.com>.
10
11CVE-2017-9445
12
13CVE: CVE-2017-8872
14Upstream-Status: Backport
15
16Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
17---
18 src/resolve/resolved-dns-packet.c | 8 +-------
19 src/resolve/resolved-dns-packet.h | 2 --
20 2 files changed, 1 insertion(+), 9 deletions(-)
21
22diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
23index 240ee44..821b66e 100644
24--- a/src/resolve/resolved-dns-packet.c
25+++ b/src/resolve/resolved-dns-packet.c
26@@ -47,13 +47,7 @@ int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
27
28 assert(ret);
29
30- if (mtu <= UDP_PACKET_HEADER_SIZE)
31- a = DNS_PACKET_SIZE_START;
32- else
33- a = mtu - UDP_PACKET_HEADER_SIZE;
34-
35- if (a < DNS_PACKET_HEADER_SIZE)
36- a = DNS_PACKET_HEADER_SIZE;
37+ a = MAX(mtu, DNS_PACKET_HEADER_SIZE);
38
39 /* round up to next page size */
40 a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
41diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h
42index 2c92392..3abcaf8 100644
43--- a/src/resolve/resolved-dns-packet.h
44+++ b/src/resolve/resolved-dns-packet.h
45@@ -66,8 +66,6 @@ struct DnsPacketHeader {
46 /* With EDNS0 we can use larger packets, default to 4096, which is what is commonly used */
47 #define DNS_PACKET_UNICAST_SIZE_LARGE_MAX 4096
48
49-#define DNS_PACKET_SIZE_START 512
50-
51 struct DnsPacket {
52 int n_ref;
53 DnsProtocol protocol;
54--
551.9.1
56
diff --git a/recipes-core/systemd/systemd_%.bbappend b/recipes-core/systemd/systemd_%.bbappend
deleted file mode 100644
index e07dbe1..0000000
--- a/recipes-core/systemd/systemd_%.bbappend
+++ /dev/null
@@ -1,6 +0,0 @@
1# look for files in the layer first
2FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
3
4SRC_URI += "file://CVE-2017-9445.patch \
5 "
6
diff --git a/recipes-devtools/dpkg/dpkg/CVE-2017-8283.patch b/recipes-devtools/dpkg/dpkg/CVE-2017-8283.patch
deleted file mode 100644
index b4c8df1..0000000
--- a/recipes-devtools/dpkg/dpkg/CVE-2017-8283.patch
+++ /dev/null
@@ -1,190 +0,0 @@
1From 67f2bc55ec79926f3334eb2956a62719f824e85b Mon Sep 17 00:00:00 2001
2From: Sona Sarmadi <sona.sarmadi@enea.com>
3Date: Thu, 14 Dec 2017 10:21:01 +0100
4Subject: [PATCH] build: Detect the required GNU patch
5
6This makes sure the perl module is using a directory traversal resistant
7patch implementation, currently that's only GNU patch.
8
9CVE: CVE-2017-8283
10Upstream-Status: Backport [remotes/origin/1.18.x: 8ba04d41c839318b5a024f6c5298848d3b54c723]
11
12Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
13---
14 configure.ac | 1 +
15 debian/changelog | 5 +++++
16 m4/dpkg-progs.m4 | 15 +++++++++++++++
17 scripts/Dpkg.pm | 13 ++++++++++++-
18 scripts/Dpkg/Source/Patch.pm | 9 +++++----
19 scripts/Makefile.am | 4 +++-
20 6 files changed, 41 insertions(+), 6 deletions(-)
21
22diff --git a/configure.ac b/configure.ac
23index 3123d0c..0112d4d 100644
24--- a/configure.ac
25+++ b/configure.ac
26@@ -61,6 +61,7 @@ AC_PROG_CC
27 DPKG_C_C99
28 AC_PROG_CXX
29 DPKG_CXX_CXX11
30+DPKG_PROG_PATCH
31 AC_CHECK_PROGS([DOXYGEN], [doxygen])
32 AC_CHECK_PROG([HAVE_DOT], [dot], [YES], [NO])
33 DPKG_PROG_PO4A
34diff --git a/debian/changelog b/debian/changelog
35index 695c55d..4b5b36b 100644
36--- a/debian/changelog
37+++ b/debian/changelog
38@@ -1,3 +1,8 @@
39+ - Check that the detected patch is a GNU patch, so that we get a directory
40+ traversal resistant patch implementation. This fixes CVE-2017-8283 by
41+ delegating those checks to patch(1), so that we trap blank-indented
42+ diff hunks trying to escape from the source tree.
43+
44 dpkg (1.18.10) unstable; urgency=medium
45
46 [ Guillem Jover ]
47diff --git a/m4/dpkg-progs.m4 b/m4/dpkg-progs.m4
48index c59f595..577d50d 100644
49--- a/m4/dpkg-progs.m4
50+++ b/m4/dpkg-progs.m4
51@@ -49,3 +49,18 @@ AC_ARG_VAR([TAR], [GNU tar program])
52 AC_CHECK_PROGS([TAR], [gnutar gtar tar], [tar])
53 AC_DEFINE_UNQUOTED([TAR], ["$TAR"], [GNU tar program])
54 ])# DPKG_DEB_PROG_TAR
55+
56+# DPKG_PROG_PATCH
57+# ---------------
58+# Specify GNU patch program name to use by dpkg-source. On GNU systems this
59+# is usually simply patch, on BSD systems this is usually gpatch.
60+# Even though most invocations would work with other patch implementations,
61+# currently only GNU patch is directory traversal resistant.
62+AC_DEFUN([DPKG_PROG_PATCH], [
63+ AC_ARG_VAR([PATCH], [GNU patch program])
64+ AC_CHECK_PROGS([PATCH], [gpatch patch], [patch])
65+ AS_IF([! $PATCH --version 2>/dev/null | grep -q '^GNU patch'], [
66+ AC_MSG_ERROR([cannot find a GNU patch program])
67+ ])
68+ AC_DEFINE_UNQUOTED([PATCH], ["$PATCH"], [GNU patch program])
69+])# DPKG_PROG_PATCH
70diff --git a/scripts/Dpkg.pm b/scripts/Dpkg.pm
71index deecfb3..4905ab8 100644
72--- a/scripts/Dpkg.pm
73+++ b/scripts/Dpkg.pm
74@@ -29,10 +29,11 @@ this system installation.
75 use strict;
76 use warnings;
77
78-our $VERSION = '1.01';
79+our $VERSION = '1.03';
80 our @EXPORT_OK = qw(
81 $PROGNAME
82 $PROGVERSION
83+ $PROGPATCH
84 $CONFDIR
85 $ADMINDIR
86 $LIBDIR
87@@ -60,6 +61,11 @@ Contains the name of the current program.
88
89 Contains the version of the dpkg suite.
90
91+=item $Dpkg::PROGPATCH
92+
93+Contains the name of the system GNU patch program (or another implementation
94+that is directory traversal resistant).
95+
96 =item $Dpkg::CONFDIR
97
98 Contains the path to the dpkg system configuration directory.
99@@ -84,6 +90,7 @@ our ($PROGNAME) = $0 =~ m{(?:.*/)?([^/]*)};
100
101 # The following lines are automatically fixed at install time
102 our $PROGVERSION = '1.18.x';
103+our $PROGPATCH = $ENV{DPKG_PROGPATCH} // 'patch';
104 our $CONFDIR = '/etc/dpkg';
105 our $ADMINDIR = '/var/lib/dpkg';
106 our $LIBDIR = '.';
107@@ -100,6 +107,10 @@ our $pkgdatadir = $DATADIR;
108
109 =head1 CHANGES
110
111+=head2 Version 1.03 (dpkg 1.18.10)
112+
113+New variable: $PROGPATCH.
114+
115 =head2 Version 1.01 (dpkg 1.17.0)
116
117 New variables: $PROGNAME, $PROGVERSION, $CONFDIR, $ADMINDIR, $LIBDIR and
118diff --git a/scripts/Dpkg/Source/Patch.pm b/scripts/Dpkg/Source/Patch.pm
119index ee5e114..22e9d21 100644
120--- a/scripts/Dpkg/Source/Patch.pm
121+++ b/scripts/Dpkg/Source/Patch.pm
122@@ -30,6 +30,7 @@ use File::Compare;
123 use Fcntl ':mode';
124 use Time::HiRes qw(stat);
125
126+use Dpkg;
127 use Dpkg::Gettext;
128 use Dpkg::ErrorHandling;
129 use Dpkg::IPC;
130@@ -582,7 +583,7 @@ sub apply {
131 $self->ensure_open('r');
132 my ($stdout, $stderr) = ('', '');
133 spawn(
134- exec => [ 'patch', @{$opts{options}} ],
135+ exec => [ $Dpkg::PROGPATCH, @{$opts{options}} ],
136 chdir => $destdir,
137 env => { LC_ALL => 'C', LANG => 'C', PATCH_GET => '0' },
138 delete_env => [ 'POSIXLY_CORRECT' ], # ensure expected patch behaviour
139@@ -595,7 +596,7 @@ sub apply {
140 if ($?) {
141 print { *STDOUT } $stdout;
142 print { *STDERR } $stderr;
143- subprocerr('LC_ALL=C patch ' . join(' ', @{$opts{options}}) .
144+ subprocerr("LC_ALL=C $Dpkg::PROGPATCH " . join(' ', @{$opts{options}}) .
145 ' < ' . $self->get_filename());
146 }
147 $self->close();
148@@ -632,7 +633,7 @@ sub check_apply {
149 # Apply the patch
150 $self->ensure_open('r');
151 my $patch_pid = spawn(
152- exec => [ 'patch', @{$opts{options}} ],
153+ exec => [ $Dpkg::PROGPATCH, @{$opts{options}} ],
154 chdir => $destdir,
155 env => { LC_ALL => 'C', LANG => 'C', PATCH_GET => '0' },
156 delete_env => [ 'POSIXLY_CORRECT' ], # ensure expected patch behaviour
157@@ -642,7 +643,7 @@ sub check_apply {
158 );
159 wait_child($patch_pid, nocheck => 1);
160 my $exit = WEXITSTATUS($?);
161- subprocerr('patch --dry-run') unless WIFEXITED($?);
162+ subprocerr("$Dpkg::PROGPATCH --dry-run") unless WIFEXITED($?);
163 $self->close();
164 return ($exit == 0);
165 }
166diff --git a/scripts/Makefile.am b/scripts/Makefile.am
167index 7b1ac36..84059c1 100644
168--- a/scripts/Makefile.am
169+++ b/scripts/Makefile.am
170@@ -127,6 +127,7 @@ do_perl_subst = $(AM_V_GEN) \
171 -e "s:\$$ADMINDIR[[:space:]]*=[[:space:]]*['\"][^'\"]*['\"]:\$$ADMINDIR='$(admindir)':" \
172 -e "s:\$$LIBDIR[[:space:]]*=[[:space:]]*['\"][^'\"]*['\"]:\$$LIBDIR='$(pkglibdir)':" \
173 -e "s:\$$DATADIR[[:space:]]*=[[:space:]]*['\"][^'\"]*['\"]:\$$DATADIR='$(pkgdatadir)':" \
174+ -e "s:our \$$PROGPATCH = .*;:our \$$PROGPATCH = '$(PATCH)';:" \
175 -e "s:\$$PROGVERSION[[:space:]]*=[[:space:]]*['\"][^'\"]*[\"']:\$$PROGVERSION='$(PACKAGE_VERSION)':"
176
177 do_shell_subst = $(AM_V_GEN) \
178@@ -187,7 +188,8 @@ coverage-clean:
179 rm -rf cover_db
180
181 TEST_ENV_VARS = \
182- DPKG_DATADIR=$(srcdir)/.. \
183+ DPKG_PROGPATCH=$(PATCH) \
184+ DPKG_DATADIR=$(srcdir)/.. \
185 DPKG_ORIGINS_DIR=$(srcdir)/t/origins
186 TEST_COVERAGE = $(PERL_COVERAGE)
187
188--
1891.9.1
190
diff --git a/recipes-devtools/dpkg/dpkg/test-case-for-CVE-2017-8283.patch b/recipes-devtools/dpkg/dpkg/test-case-for-CVE-2017-8283.patch
deleted file mode 100644
index 5632d8f..0000000
--- a/recipes-devtools/dpkg/dpkg/test-case-for-CVE-2017-8283.patch
+++ /dev/null
@@ -1,83 +0,0 @@
1From 57a3daba4d3dee1c33571e84f160aa1c67aece4c Mon Sep 17 00:00:00 2001
2From: Sona Sarmadi <sona.sarmadi@enea.com>
3Date: Thu, 14 Dec 2017 10:40:42 +0100
4Subject: [PATCH] Dpkg::Source::Patch: Indented patch test-case
5
6POSIX specifies that a diff hunk can be indented by spaces or tabs
7(while the original patch(1) by Larry Wall also accepts 'X'), as long
8as the amount of spaces is consistent for all subsequent lines. And as
9we are not checking for this condition at all, any such indented hunk
10can avoid the sanity checks performed by Dpkg::Source::Patch.
11
12On systems using GNU patch >= 2.7.5, this should, in principle, not be
13a problem anymore, as that implementation protects against directory
14traversal issue. But on other systems where the patch implementation
15does not perform such checks (such as the BSDs) this is an issue, so
16check for this in the test-suite.
17
18Those are arguably all security issues in these various patch
19implementations, but given that we are performing sanity checks and that
20those implementations are currently very lax, it seems prudent to do the
21heavy lifting ourselves and also take the possible blame too.
22
23Ref: test-case for CVE-2017-8283
24Upstream-Status: Backport
25
26Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
27---
28 debian/changelog | 3 +++
29 scripts/Makefile.am | 1 +
30 scripts/t/Dpkg_Source_Patch.t | 6 +++++-
31 3 files changed, 9 insertions(+), 1 deletion(-)
32
33diff --git a/debian/changelog b/debian/changelog
34index 4b5b36b..596a59e 100644
35--- a/debian/changelog
36+++ b/debian/changelog
37@@ -2,6 +2,9 @@
38 traversal resistant patch implementation. This fixes CVE-2017-8283 by
39 delegating those checks to patch(1), so that we trap blank-indented
40 diff hunks trying to escape from the source tree.
41+ * Test suite:
42+ - Add a test case for blank-indented patches which were the cause for
43+ CVE-2017-8283.
44
45 dpkg (1.18.10) unstable; urgency=medium
46
47diff --git a/scripts/Makefile.am b/scripts/Makefile.am
48index 84059c1..6ce0ad6 100644
49--- a/scripts/Makefile.am
50+++ b/scripts/Makefile.am
51@@ -275,6 +275,7 @@ test_data = \
52 t/Dpkg_Shlibs/spacesyms-o-map.pl \
53 t/Dpkg_Source_Patch/c-style.patch \
54 t/Dpkg_Source_Patch/ghost-hunk.patch \
55+ t/Dpkg_Source_Patch/indent-header.patch \
56 t/Dpkg_Source_Patch/index-+++.patch \
57 t/Dpkg_Source_Patch/index-alone.patch \
58 t/Dpkg_Source_Patch/index-inert.patch \
59diff --git a/scripts/t/Dpkg_Source_Patch.t b/scripts/t/Dpkg_Source_Patch.t
60index 258a9aa..30be77a 100644
61--- a/scripts/t/Dpkg_Source_Patch.t
62+++ b/scripts/t/Dpkg_Source_Patch.t
63@@ -16,7 +16,7 @@
64 use strict;
65 use warnings;
66
67-use Test::More tests => 9;
68+use Test::More tests => 10;
69
70 use File::Path qw(make_path);
71
72@@ -67,4 +67,8 @@ test_patch_escape('partial', 'symlink', 'partial.patch',
73 test_patch_escape('ghost-hunk', 'symlink', 'ghost-hunk.patch',
74 'Patch cannot escape using a disabling hunk');
75
76+# This is CVE-2017-8283
77+test_patch_escape('indent-header', 'symlink', 'indent-header.patch',
78+ 'Patch cannot escape indented hunks');
79+
80 1;
81--
821.9.1
83
diff --git a/recipes-devtools/dpkg/dpkg_%.bbappend b/recipes-devtools/dpkg/dpkg_%.bbappend
deleted file mode 100644
index 65d380e..0000000
--- a/recipes-devtools/dpkg/dpkg_%.bbappend
+++ /dev/null
@@ -1,6 +0,0 @@
1# look for files in the layer first
2FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
3
4SRC_URI += "file://CVE-2017-8283.patch \
5 file://test-case-for-CVE-2017-8283.patch \
6 "
diff --git a/recipes-networking/dnsmasq/dnsmasq/0001-CVE-2017-14491.patch b/recipes-networking/dnsmasq/dnsmasq/0001-CVE-2017-14491.patch
deleted file mode 100644
index 1eda591..0000000
--- a/recipes-networking/dnsmasq/dnsmasq/0001-CVE-2017-14491.patch
+++ /dev/null
@@ -1,269 +0,0 @@
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
deleted file mode 100644
index 6f27667..0000000
--- a/recipes-networking/dnsmasq/dnsmasq/0002-CVE-2017-14491.patch
+++ /dev/null
@@ -1,73 +0,0 @@
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/CVE-2017-14492.patch b/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14492.patch
deleted file mode 100644
index 5b66944..0000000
--- a/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14492.patch
+++ /dev/null
@@ -1,57 +0,0 @@
1From 24036ea507862c7b7898b68289c8130f85599c10 Mon Sep 17 00:00:00 2001
2From: Simon Kelley <simon@thekelleys.org.uk>
3Date: Mon, 25 Sep 2017 18:47:15 +0100
4Subject: [PATCH] Security fix, CVE-2017-14492, DHCPv6 RA heap overflow.
5
6Fix heap overflow in IPv6 router advertisement code.
7This is a potentially serious security hole, as a
8crafted RA request can overflow a buffer and crash or
9control dnsmasq. Attacker must be on the local network.
10
11CVE: CVE-2017-14492
12Upstream-Status: Backport
13
14Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
15---
16 CHANGELOG | 10 +++++++++-
17 src/radv.c | 3 +++
18 2 files changed, 12 insertions(+), 1 deletion(-)
19
20diff --git a/CHANGELOG b/CHANGELOG
21index a7c2f35..df6c157 100644
22--- a/CHANGELOG
23+++ b/CHANGELOG
24@@ -35,7 +35,15 @@ version 2.78
25 and Kevin Hamacher of the Google Security Team for
26 finding this.
27
28-
29+ Fix heap overflow in IPv6 router advertisement code.
30+ This is a potentially serious security hole, as a
31+ crafted RA request can overflow a buffer and crash or
32+ control dnsmasq. Attacker must be on the local network.
33+ CVE-2017-14492 applies.
34+ Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
35+ and Kevin Hamacher of the Google Security Team for
36+ finding this.
37+
38
39 version 2.77
40 Generate an error when configured with a CNAME loop,
41diff --git a/src/radv.c b/src/radv.c
42index 1032189..9b7e52c 100644
43--- a/src/radv.c
44+++ b/src/radv.c
45@@ -198,6 +198,9 @@ void icmp6_packet(time_t now)
46 /* look for link-layer address option for logging */
47 if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
48 {
49+ if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) {
50+ return;
51+ }
52 print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
53 mac = daemon->namebuff;
54 }
55--
561.7.10.4
57
diff --git a/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14493.patch b/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14493.patch
deleted file mode 100644
index fedb825..0000000
--- a/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14493.patch
+++ /dev/null
@@ -1,55 +0,0 @@
1From 3d4ff1ba8419546490b464418223132529514033 Mon Sep 17 00:00:00 2001
2From: Simon Kelley <simon@thekelleys.org.uk>
3Date: Mon, 25 Sep 2017 18:52:50 +0100
4Subject: [PATCH] Security fix, CVE-2017-14493, DHCPv6 - Stack buffer
5 overflow.
6
7Fix stack overflow in DHCPv6 code. An attacker who can send
8a DHCPv6 request to dnsmasq can overflow the stack frame and
9crash or control dnsmasq.
10
11CVE: CVE-2017-14493
12Upstream-Status: Backport
13
14Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
15---
16 CHANGELOG | 8 ++++++++
17 src/rfc3315.c | 3 +++
18 2 files changed, 11 insertions(+)
19
20diff --git a/CHANGELOG b/CHANGELOG
21index df6c157..c48378f 100644
22--- a/CHANGELOG
23+++ b/CHANGELOG
24@@ -43,6 +43,14 @@ version 2.78
25 Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
26 and Kevin Hamacher of the Google Security Team for
27 finding this.
28+
29+ Fix stack overflow in DHCPv6 code. An attacker who can send
30+ a DHCPv6 request to dnsmasq can overflow the stack frame and
31+ crash or control dnsmasq.
32+ CVE-2017-14493 applies.
33+ Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
34+ and Kevin Hamacher of the Google Security Team for
35+ finding this.
36
37
38 version 2.77
39diff --git a/src/rfc3315.c b/src/rfc3315.c
40index 1687931..920907c 100644
41--- a/src/rfc3315.c
42+++ b/src/rfc3315.c
43@@ -206,6 +206,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
44 /* RFC-6939 */
45 if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
46 {
47+ if (opt6_len(opt) - 2 > DHCP_CHADDR_MAX) {
48+ return 0;
49+ }
50 state->mac_type = opt6_uint(opt, 0, 2);
51 state->mac_len = opt6_len(opt) - 2;
52 memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
53--
541.7.10.4
55
diff --git a/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14494.patch b/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14494.patch
deleted file mode 100644
index d32f713..0000000
--- a/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14494.patch
+++ /dev/null
@@ -1,55 +0,0 @@
1From 33e3f1029c9ec6c63e430ff51063a6301d4b2262 Mon Sep 17 00:00:00 2001
2From: Simon Kelley <simon@thekelleys.org.uk>
3Date: Mon, 25 Sep 2017 20:05:11 +0100
4Subject: [PATCH] Security fix, CVE-2017-14494, Infoleak handling DHCPv6
5 forwarded requests.
6
7Fix information leak in DHCPv6. A crafted DHCPv6 packet can
8cause dnsmasq to forward memory from outside the packet
9buffer to a DHCPv6 server when acting as a relay.
10
11CVE: CVE-2017-14494
12Upstream-Status: Backport
13
14Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
15---
16 CHANGELOG | 8 ++++++++
17 src/rfc3315.c | 3 +++
18 2 files changed, 11 insertions(+)
19
20diff --git a/CHANGELOG b/CHANGELOG
21index c48378f..d1cc074 100644
22--- a/CHANGELOG
23+++ b/CHANGELOG
24@@ -51,6 +51,14 @@ version 2.78
25 Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
26 and Kevin Hamacher of the Google Security Team for
27 finding this.
28+
29+ Fix information leak in DHCPv6. A crafted DHCPv6 packet can
30+ cause dnsmasq to forward memory from outside the packet
31+ buffer to a DHCPv6 server when acting as a relay.
32+ CVE-2017-14494 applies.
33+ Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
34+ and Kevin Hamacher of the Google Security Team for
35+ finding this.
36
37
38 version 2.77
39diff --git a/src/rfc3315.c b/src/rfc3315.c
40index 920907c..4ca43e0 100644
41--- a/src/rfc3315.c
42+++ b/src/rfc3315.c
43@@ -216,6 +216,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
44
45 for (opt = opts; opt; opt = opt6_next(opt, end))
46 {
47+ if (opt6_ptr(opt, 0) + opt6_len(opt) >= end) {
48+ return 0;
49+ }
50 int o = new_opt6(opt6_type(opt));
51 if (opt6_type(opt) == OPTION6_RELAY_MSG)
52 {
53--
541.7.10.4
55
diff --git a/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14495.patch b/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14495.patch
deleted file mode 100644
index ba176a8..0000000
--- a/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14495.patch
+++ /dev/null
@@ -1,69 +0,0 @@
1From 51eadb692a5123b9838e5a68ecace3ac579a3a45 Mon Sep 17 00:00:00 2001
2From: Simon Kelley <simon@thekelleys.org.uk>
3Date: Mon, 25 Sep 2017 20:16:50 +0100
4Subject: [PATCH] Security fix, CVE-2017-14495, OOM in DNS response creation.
5
6Fix out-of-memory Dos vulnerability. An attacker which can
7send malicious DNS queries to dnsmasq can trigger memory
8allocations in the add_pseudoheader function
9The allocated memory is never freed which leads to a DoS
10through memory exhaustion. dnsmasq is vulnerable only
11if one of the following option is specified:
12--add-mac, --add-cpe-id or --add-subnet.
13
14CVE: CVE-2017-14495
15Upstream-Status: Backport
16
17Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
18---
19 CHANGELOG | 12 ++++++++++++
20 src/edns0.c | 8 +++++++-
21 2 files changed, 19 insertions(+), 1 deletion(-)
22
23diff --git a/CHANGELOG b/CHANGELOG
24index 8fe00ed..9523329 100644
25--- a/CHANGELOG
26+++ b/CHANGELOG
27@@ -70,6 +70,18 @@ version 2.78
28 Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
29 and Kevin Hamacher of the Google Security Team for
30 finding this.
31+
32+ Fix out-of-memory Dos vulnerability. An attacker which can
33+ send malicious DNS queries to dnsmasq can trigger memory
34+ allocations in the add_pseudoheader function
35+ The allocated memory is never freed which leads to a DoS
36+ through memory exhaustion. dnsmasq is vulnerable only
37+ if one of the following option is specified:
38+ --add-mac, --add-cpe-id or --add-subnet.
39+ CVE-2017-14495 applies.
40+ Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
41+ and Kevin Hamacher of the Google Security Team for
42+ finding this.
43
44
45 version 2.77
46diff --git a/src/edns0.c b/src/edns0.c
47index 95b74ee..89b2692 100644
48--- a/src/edns0.c
49+++ b/src/edns0.c
50@@ -192,9 +192,15 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
51 !(p = skip_section(p,
52 ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
53 header, plen)))
54+ {
55+ free(buff);
56 return plen;
57+ }
58 if (p + 11 > limit)
59- return plen; /* Too big */
60+ {
61+ free(buff);
62+ return plen; /* Too big */
63+ }
64 *p++ = 0; /* empty name */
65 PUTSHORT(T_OPT, p);
66 PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
67--
681.7.10.4
69
diff --git a/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14496.patch b/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14496.patch
deleted file mode 100644
index 333a890..0000000
--- a/recipes-networking/dnsmasq/dnsmasq/CVE-2017-14496.patch
+++ /dev/null
@@ -1,94 +0,0 @@
1From 897c113fda0886a28a986cc6ba17bb93bd6cb1c7 Mon Sep 17 00:00:00 2001
2From: Simon Kelley <simon@thekelleys.org.uk>
3Date: Mon, 25 Sep 2017 20:11:58 +0100
4Subject: [PATCH] Security fix, CVE-2017-14496, Integer underflow in DNS
5 response creation.
6
7Fix DoS in DNS. Invalid boundary checks in the
8add_pseudoheader function allows a memcpy call with negative
9size An attacker which can send malicious DNS queries
10to dnsmasq can trigger a DoS remotely.
11dnsmasq is vulnerable only if one of the following option is
12specified: --add-mac, --add-cpe-id or --add-subnet.
13
14CVE: CVE-2017-14496
15Upstream-Status: Backport
16
17Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
18---
19 CHANGELOG | 11 +++++++++++
20 src/edns0.c | 13 ++++++++++++-
21 2 files changed, 23 insertions(+), 1 deletion(-)
22
23diff --git a/CHANGELOG b/CHANGELOG
24index d1cc074..8fe00ed 100644
25--- a/CHANGELOG
26+++ b/CHANGELOG
27@@ -60,6 +60,17 @@ version 2.78
28 and Kevin Hamacher of the Google Security Team for
29 finding this.
30
31+ Fix DoS in DNS. Invalid boundary checks in the
32+ add_pseudoheader function allows a memcpy call with negative
33+ size An attacker which can send malicious DNS queries
34+ to dnsmasq can trigger a DoS remotely.
35+ dnsmasq is vulnerable only if one of the following option is
36+ specified: --add-mac, --add-cpe-id or --add-subnet.
37+ CVE-2017-14496 applies.
38+ Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
39+ and Kevin Hamacher of the Google Security Team for
40+ finding this.
41+
42
43 version 2.77
44 Generate an error when configured with a CNAME loop,
45diff --git a/src/edns0.c b/src/edns0.c
46index f5b798c..95b74ee 100644
47--- a/src/edns0.c
48+++ b/src/edns0.c
49@@ -144,7 +144,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
50 GETSHORT(len, p);
51
52 /* malformed option, delete the whole OPT RR and start again. */
53- if (i + len > rdlen)
54+ if (i + 4 + len > rdlen)
55 {
56 rdlen = 0;
57 is_last = 0;
58@@ -193,6 +193,8 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
59 ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
60 header, plen)))
61 return plen;
62+ if (p + 11 > limit)
63+ return plen; /* Too big */
64 *p++ = 0; /* empty name */
65 PUTSHORT(T_OPT, p);
66 PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
67@@ -204,6 +206,11 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
68 /* Copy back any options */
69 if (buff)
70 {
71+ if (p + rdlen > limit)
72+ {
73+ free(buff);
74+ return plen; /* Too big */
75+ }
76 memcpy(p, buff, rdlen);
77 free(buff);
78 p += rdlen;
79@@ -220,8 +227,12 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
80 /* Add new option */
81 if (optno != 0 && replace != 2)
82 {
83+ if (p + 4 > limit)
84+ return plen; /* Too big */
85 PUTSHORT(optno, p);
86 PUTSHORT(optlen, p);
87+ if (p + optlen > limit)
88+ return plen; /* Too big */
89 memcpy(p, opt, optlen);
90 p += optlen;
91 PUTSHORT(p - datap, lenp);
92--
931.7.10.4
94
diff --git a/recipes-networking/dnsmasq/dnsmasq_%.bbappend b/recipes-networking/dnsmasq/dnsmasq_%.bbappend
deleted file mode 100644
index ee31536..0000000
--- a/recipes-networking/dnsmasq/dnsmasq_%.bbappend
+++ /dev/null
@@ -1,11 +0,0 @@
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 file://CVE-2017-14492.patch \
7 file://CVE-2017-14493.patch \
8 file://CVE-2017-14494.patch \
9 file://CVE-2017-14496.patch \
10 file://CVE-2017-14495.patch \
11"