diff options
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 @@ | |||
1 | From 6bed6ea11b1880e0a078bd02c1d31d21f0540583 Mon Sep 17 00:00:00 2001 | ||
2 | From: Mark Andrews <marka@isc.org> | ||
3 | Date: Thu, 29 Dec 2016 10:48:46 +1100 | ||
4 | Subject: [PATCH] fix back port issue | ||
5 | |||
6 | This patch is needed for CVE-2016-9444 fix. | ||
7 | Upstream-Status: Backport [backport from v9_10_6_patch: https://source.isc.org/cgi-bin/gitweb.cgi?p=bind9.git;a=patch;h=6bed6ea11b1880e0a078bd02c1d31d21f0540583] | ||
8 | |||
9 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
10 | --- | ||
11 | lib/dns/message.c | 2 +- | ||
12 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
13 | |||
14 | diff --git a/lib/dns/message.c b/lib/dns/message.c | ||
15 | index 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 | -- | ||
28 | 1.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 @@ | |||
1 | From 254d55749ccb1129e7d021a51d0c3b7d3da26ee1 Mon Sep 17 00:00:00 2001 | ||
2 | From: Sona Sarmadi <sona.sarmadi@enea.com> | ||
3 | Date: Tue, 12 Sep 2017 14:13:28 +0200 | ||
4 | Subject: [PATCH] CVE-2016-9444 | ||
5 | |||
6 | An unusually-formed DS record response could cause an assertion failure | ||
7 | |||
8 | CVE: CVE-2016-9444 | ||
9 | Upstream-Status: Backport [backport from remotes/origin/v9_10_6_patch | ||
10 | https://source.isc.org/cgi-bin/gitweb.cgi?p=bind9.git;a=commit;h=04c7ee66b1eda851737cc7582a2a88193a0b4118] | ||
11 | |||
12 | Signed-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 | |||
19 | diff --git a/CHANGES b/CHANGES | ||
20 | index 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] | ||
31 | diff --git a/lib/dns/message.c b/lib/dns/message.c | ||
32 | index 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); | ||
143 | diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c | ||
144 | index 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 | -- | ||
185 | 1.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 @@ | |||
1 | From 6106ed6841b253c78c6120be24c8722d6310a9b9 Mon Sep 17 00:00:00 2001 | ||
2 | From: Mark Andrews <marka@isc.org> | ||
3 | Date: Tue, 31 Jan 2017 11:20:03 +1100 | ||
4 | Subject: [PATCH] add a REQUIRE to catch the NULL pointer dereference that | ||
5 | triggered CVE-2017-3135 | ||
6 | |||
7 | CVE: CVE-2017-3135 | ||
8 | Upstream-Status: Backport [backport from remotes/origin/v9_10] | ||
9 | |||
10 | (cherry picked from commit 1d8995d226d8bca96b8ba286316018be4b7835f2) | ||
11 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
12 | --- | ||
13 | lib/dns/rdataset.c | 1 + | ||
14 | 1 file changed, 1 insertion(+) | ||
15 | |||
16 | diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c | ||
17 | index 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 | -- | ||
29 | 1.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 @@ | |||
1 | From cdb44bbabefa96fceb9bca540f5112493756d593 Mon Sep 17 00:00:00 2001 | ||
2 | From: Sona Sarmadi <sona.sarmadi@enea.com> | ||
3 | Date: Wed, 27 Sep 2017 09:45:10 +0200 | ||
4 | Subject: [PATCH] Dns64 with break-dnssec yes; can result in a assertion | ||
5 | failure. | ||
6 | |||
7 | From 764240ca07ab1b796226d5402ccd9fbfa77ec32a Mon Sep 17 00:00:00 2001 | ||
8 | From: Mark Andrews <marka@isc.org> | ||
9 | Date: Wed, 15 Feb 2017 12:18:51 +1100 | ||
10 | |||
11 | (cherry picked from commit 3bce12e4b6d37f570ffc7747b499f8b90e8521ac) | ||
12 | |||
13 | CVE: CVE-2017-3136 | ||
14 | Upstream-Status: Backport [backport from remotes/origin/v9_10] | ||
15 | |||
16 | Signed-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 | |||
22 | diff --git a/CHANGES b/CHANGES | ||
23 | index 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] | ||
33 | diff --git a/bin/named/query.c b/bin/named/query.c | ||
34 | index 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 | -- | ||
46 | 1.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 @@ | |||
1 | FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" | ||
2 | |||
3 | SRC_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 @@ | |||
1 | From f6110a8fee2ca36f8e2d2abecf3cba9fa7b8ea7d Mon Sep 17 00:00:00 2001 | ||
2 | From: Florian Weimer <fweimer@redhat.com> | ||
3 | Date: Mon, 19 Jun 2017 17:09:55 +0200 | ||
4 | Subject: [PATCH] CVE-2017-1000366: Ignore LD_LIBRARY_PATH for AT_SECURE=1 | ||
5 | programs [BZ #21624] | ||
6 | |||
7 | LD_LIBRARY_PATH can only be used to reorder system search paths, which | ||
8 | is not useful functionality. | ||
9 | |||
10 | This makes an exploitable unbounded alloca in _dl_init_paths unreachable | ||
11 | for AT_SECURE=1 programs. | ||
12 | |||
13 | CVE: CVE-2017-1000366 | ||
14 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=3c7cd21290cabdadd72984fb69bc51e64ff1002d] | ||
15 | |||
16 | Signed-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 | |||
22 | diff --git a/ChangeLog b/ChangeLog | ||
23 | index 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" | ||
37 | diff --git a/elf/rtld.c b/elf/rtld.c | ||
38 | index 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 | -- | ||
52 | 1.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 @@ | |||
1 | From 44cf81c6c008316876cfcc8208ae982621949e0e Mon Sep 17 00:00:00 2001 | ||
2 | From: Sona Sarmadi <sona.sarmadi@enea.com> | ||
3 | Date: Mon, 11 Sep 2017 10:55:45 +0200 | ||
4 | Subject: [PATCH] glibc: CVE-2017-12132 | ||
5 | |||
6 | From e14a27723cc3a154d67f3f26e719d08c0ba9ad25 Mon Sep 17 00:00:00 2001 | ||
7 | From: Florian Weimer <fweimer@redhat.com> | ||
8 | Date: Thu, 13 Apr 2017 13:09:38 +0200 | ||
9 | Subject: [PATCH] resolv: Reduce EDNS payload size to 1200 bytes [BZ #21361] | ||
10 | |||
11 | This hardens the stub resolver against fragmentation-based attacks. | ||
12 | |||
13 | CVE: CVE-2017-12132 | ||
14 | Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=e14a27723cc3a154d67f3f26e719d08c0ba9ad25] | ||
15 | |||
16 | Signed-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 | |||
30 | diff --git a/ChangeLog b/ChangeLog | ||
31 | index 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] | ||
59 | diff --git a/include/resolv.h b/include/resolv.h | ||
60 | index 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 | |||
80 | diff --git a/resolv/Makefile b/resolv/Makefile | ||
81 | index 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) | ||
100 | diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c | ||
101 | index 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) | ||
150 | diff --git a/resolv/res_query.c b/resolv/res_query.c | ||
151 | index 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 | } | ||
205 | diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h | ||
206 | index 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 */ | ||
232 | diff --git a/resolv/tst-resolv-edns.c b/resolv/tst-resolv-edns.c | ||
233 | new file mode 100644 | ||
234 | index 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> | ||
739 | diff --git a/support/resolv_test.c b/support/resolv_test.c | ||
740 | index 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); | ||
835 | diff --git a/support/resolv_test.h b/support/resolv_test.h | ||
836 | index 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 | -- | ||
865 | 1.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 @@ | |||
1 | From 45619a54f7d751a2a7dec7d7ee323e1545b881af Mon Sep 17 00:00:00 2001 | ||
2 | From: Sona Sarmadi <sona.sarmadi@enea.com> | ||
3 | Date: Mon, 11 Sep 2017 13:35:44 +0200 | ||
4 | Subject: [PATCH] CVE-2017-8804 | ||
5 | |||
6 | The xdr_bytes and xdr_string functions in the glibc or libc6 2.25 mishandle | ||
7 | failures of buffer deserialization, which allows remote attackers to cause | ||
8 | a denial of service (virtual memory allocation, or memory consumption if an | ||
9 | overcommit setting is not used) via a crafted UDP packet to port 111, a | ||
10 | related issue to CVE-2017-8779. | ||
11 | |||
12 | CVE: CVE-2017-8804 | ||
13 | Upstream-Status: Backport [https://sourceware.org/ml/libc-alpha/2017-05/msg00105.html] | ||
14 | |||
15 | Signed-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 | |||
24 | diff --git a/NEWS b/NEWS | ||
25 | index 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. | ||
38 | diff --git a/sunrpc/Makefile b/sunrpc/Makefile | ||
39 | index 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 | |||
68 | diff --git a/sunrpc/tst-xdrmem3.c b/sunrpc/tst-xdrmem3.c | ||
69 | new file mode 100644 | ||
70 | index 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 | + | ||
157 | diff --git a/sunrpc/xdr.c b/sunrpc/xdr.c | ||
158 | index 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 | -- | ||
224 | 1.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 | ||
2 | FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" | ||
3 | |||
4 | SRC_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 @@ | |||
1 | From db848813bae4d28c524b3b6a7dad135e426659ce Mon Sep 17 00:00:00 2001 | ||
2 | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||
3 | Date: Sun, 18 Jun 2017 16:07:57 -0400 | ||
4 | Subject: [PATCH] resolved: simplify alloc size calculation | ||
5 | |||
6 | The allocation size was calculated in a complicated way, and for values | ||
7 | close to the page size we would actually allocate less than requested. | ||
8 | |||
9 | Reported by Chris Coulson <chris.coulson@canonical.com>. | ||
10 | |||
11 | CVE-2017-9445 | ||
12 | |||
13 | CVE: CVE-2017-8872 | ||
14 | Upstream-Status: Backport | ||
15 | |||
16 | Signed-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 | |||
22 | diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c | ||
23 | index 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)); | ||
41 | diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h | ||
42 | index 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 | -- | ||
55 | 1.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 | ||
2 | FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" | ||
3 | |||
4 | SRC_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 @@ | |||
1 | From 67f2bc55ec79926f3334eb2956a62719f824e85b Mon Sep 17 00:00:00 2001 | ||
2 | From: Sona Sarmadi <sona.sarmadi@enea.com> | ||
3 | Date: Thu, 14 Dec 2017 10:21:01 +0100 | ||
4 | Subject: [PATCH] build: Detect the required GNU patch | ||
5 | |||
6 | This makes sure the perl module is using a directory traversal resistant | ||
7 | patch implementation, currently that's only GNU patch. | ||
8 | |||
9 | CVE: CVE-2017-8283 | ||
10 | Upstream-Status: Backport [remotes/origin/1.18.x: 8ba04d41c839318b5a024f6c5298848d3b54c723] | ||
11 | |||
12 | Signed-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 | |||
22 | diff --git a/configure.ac b/configure.ac | ||
23 | index 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 | ||
34 | diff --git a/debian/changelog b/debian/changelog | ||
35 | index 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 ] | ||
47 | diff --git a/m4/dpkg-progs.m4 b/m4/dpkg-progs.m4 | ||
48 | index 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 | ||
70 | diff --git a/scripts/Dpkg.pm b/scripts/Dpkg.pm | ||
71 | index 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 | ||
118 | diff --git a/scripts/Dpkg/Source/Patch.pm b/scripts/Dpkg/Source/Patch.pm | ||
119 | index 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 | } | ||
166 | diff --git a/scripts/Makefile.am b/scripts/Makefile.am | ||
167 | index 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 | -- | ||
189 | 1.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 @@ | |||
1 | From 57a3daba4d3dee1c33571e84f160aa1c67aece4c Mon Sep 17 00:00:00 2001 | ||
2 | From: Sona Sarmadi <sona.sarmadi@enea.com> | ||
3 | Date: Thu, 14 Dec 2017 10:40:42 +0100 | ||
4 | Subject: [PATCH] Dpkg::Source::Patch: Indented patch test-case | ||
5 | |||
6 | POSIX 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 | ||
8 | as the amount of spaces is consistent for all subsequent lines. And as | ||
9 | we are not checking for this condition at all, any such indented hunk | ||
10 | can avoid the sanity checks performed by Dpkg::Source::Patch. | ||
11 | |||
12 | On systems using GNU patch >= 2.7.5, this should, in principle, not be | ||
13 | a problem anymore, as that implementation protects against directory | ||
14 | traversal issue. But on other systems where the patch implementation | ||
15 | does not perform such checks (such as the BSDs) this is an issue, so | ||
16 | check for this in the test-suite. | ||
17 | |||
18 | Those are arguably all security issues in these various patch | ||
19 | implementations, but given that we are performing sanity checks and that | ||
20 | those implementations are currently very lax, it seems prudent to do the | ||
21 | heavy lifting ourselves and also take the possible blame too. | ||
22 | |||
23 | Ref: test-case for CVE-2017-8283 | ||
24 | Upstream-Status: Backport | ||
25 | |||
26 | Signed-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 | |||
33 | diff --git a/debian/changelog b/debian/changelog | ||
34 | index 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 | |||
47 | diff --git a/scripts/Makefile.am b/scripts/Makefile.am | ||
48 | index 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 \ | ||
59 | diff --git a/scripts/t/Dpkg_Source_Patch.t b/scripts/t/Dpkg_Source_Patch.t | ||
60 | index 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 | -- | ||
82 | 1.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 | ||
2 | FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" | ||
3 | |||
4 | SRC_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 @@ | |||
1 | From 0549c73b7ea6b22a3c49beb4d432f185a81efcbc Mon Sep 17 00:00:00 2001 | ||
2 | From: Simon Kelley <simon@thekelleys.org.uk> | ||
3 | Date: Mon, 25 Sep 2017 18:17:11 +0100 | ||
4 | Subject: [PATCH] Security fix, CVE-2017-14491 DNS heap buffer overflow. | ||
5 | |||
6 | Fix heap overflow in DNS code. This is a potentially serious | ||
7 | security hole. It allows an attacker who can make DNS | ||
8 | requests to dnsmasq, and who controls the contents of | ||
9 | a domain, which is thereby queried, to overflow | ||
10 | (by 2 bytes) a heap buffer and either crash, or | ||
11 | even take control of, dnsmasq. | ||
12 | |||
13 | CVE: CVE-2017-14491 | ||
14 | Upstream-Status: Backport [src/dnsmasq.h patch failed, modified manually] | ||
15 | |||
16 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
17 | |||
18 | diff -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 | ||
40 | diff -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); | ||
52 | diff -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); | ||
64 | diff -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); | ||
76 | diff -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; | ||
213 | diff -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 | } | ||
229 | diff -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 | } | ||
245 | diff -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 @@ | |||
1 | From 62cb936cb7ad5f219715515ae7d32dd281a5aa1f Mon Sep 17 00:00:00 2001 | ||
2 | From: Simon Kelley <simon@thekelleys.org.uk> | ||
3 | Date: Tue, 26 Sep 2017 22:00:11 +0100 | ||
4 | Subject: [PATCH] Security fix, CVE-2017-14491, DNS heap buffer overflow. | ||
5 | |||
6 | Further fix to 0549c73b7ea6b22a3c49beb4d432f185a81efcbc | ||
7 | Handles case when RR name is not a pointer to the question, | ||
8 | only occurs for some auth-mode replies, therefore not | ||
9 | detected by fuzzing (?) | ||
10 | |||
11 | CVE: CVE-2017-14491 | ||
12 | Upstream-Status: Backport | ||
13 | |||
14 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
15 | --- | ||
16 | src/rfc1035.c | 27 +++++++++++++++------------ | ||
17 | 1 file changed, 15 insertions(+), 12 deletions(-) | ||
18 | |||
19 | diff --git a/src/rfc1035.c b/src/rfc1035.c | ||
20 | index 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 | -- | ||
72 | 1.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 @@ | |||
1 | From 24036ea507862c7b7898b68289c8130f85599c10 Mon Sep 17 00:00:00 2001 | ||
2 | From: Simon Kelley <simon@thekelleys.org.uk> | ||
3 | Date: Mon, 25 Sep 2017 18:47:15 +0100 | ||
4 | Subject: [PATCH] Security fix, CVE-2017-14492, DHCPv6 RA heap overflow. | ||
5 | |||
6 | Fix heap overflow in IPv6 router advertisement code. | ||
7 | This is a potentially serious security hole, as a | ||
8 | crafted RA request can overflow a buffer and crash or | ||
9 | control dnsmasq. Attacker must be on the local network. | ||
10 | |||
11 | CVE: CVE-2017-14492 | ||
12 | Upstream-Status: Backport | ||
13 | |||
14 | Signed-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 | |||
20 | diff --git a/CHANGELOG b/CHANGELOG | ||
21 | index 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, | ||
41 | diff --git a/src/radv.c b/src/radv.c | ||
42 | index 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 | -- | ||
56 | 1.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 @@ | |||
1 | From 3d4ff1ba8419546490b464418223132529514033 Mon Sep 17 00:00:00 2001 | ||
2 | From: Simon Kelley <simon@thekelleys.org.uk> | ||
3 | Date: Mon, 25 Sep 2017 18:52:50 +0100 | ||
4 | Subject: [PATCH] Security fix, CVE-2017-14493, DHCPv6 - Stack buffer | ||
5 | overflow. | ||
6 | |||
7 | Fix stack overflow in DHCPv6 code. An attacker who can send | ||
8 | a DHCPv6 request to dnsmasq can overflow the stack frame and | ||
9 | crash or control dnsmasq. | ||
10 | |||
11 | CVE: CVE-2017-14493 | ||
12 | Upstream-Status: Backport | ||
13 | |||
14 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
15 | --- | ||
16 | CHANGELOG | 8 ++++++++ | ||
17 | src/rfc3315.c | 3 +++ | ||
18 | 2 files changed, 11 insertions(+) | ||
19 | |||
20 | diff --git a/CHANGELOG b/CHANGELOG | ||
21 | index 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 | ||
39 | diff --git a/src/rfc3315.c b/src/rfc3315.c | ||
40 | index 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 | -- | ||
54 | 1.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 @@ | |||
1 | From 33e3f1029c9ec6c63e430ff51063a6301d4b2262 Mon Sep 17 00:00:00 2001 | ||
2 | From: Simon Kelley <simon@thekelleys.org.uk> | ||
3 | Date: Mon, 25 Sep 2017 20:05:11 +0100 | ||
4 | Subject: [PATCH] Security fix, CVE-2017-14494, Infoleak handling DHCPv6 | ||
5 | forwarded requests. | ||
6 | |||
7 | Fix information leak in DHCPv6. A crafted DHCPv6 packet can | ||
8 | cause dnsmasq to forward memory from outside the packet | ||
9 | buffer to a DHCPv6 server when acting as a relay. | ||
10 | |||
11 | CVE: CVE-2017-14494 | ||
12 | Upstream-Status: Backport | ||
13 | |||
14 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
15 | --- | ||
16 | CHANGELOG | 8 ++++++++ | ||
17 | src/rfc3315.c | 3 +++ | ||
18 | 2 files changed, 11 insertions(+) | ||
19 | |||
20 | diff --git a/CHANGELOG b/CHANGELOG | ||
21 | index 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 | ||
39 | diff --git a/src/rfc3315.c b/src/rfc3315.c | ||
40 | index 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 | -- | ||
54 | 1.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 @@ | |||
1 | From 51eadb692a5123b9838e5a68ecace3ac579a3a45 Mon Sep 17 00:00:00 2001 | ||
2 | From: Simon Kelley <simon@thekelleys.org.uk> | ||
3 | Date: Mon, 25 Sep 2017 20:16:50 +0100 | ||
4 | Subject: [PATCH] Security fix, CVE-2017-14495, OOM in DNS response creation. | ||
5 | |||
6 | Fix out-of-memory Dos vulnerability. An attacker which can | ||
7 | send malicious DNS queries to dnsmasq can trigger memory | ||
8 | allocations in the add_pseudoheader function | ||
9 | The allocated memory is never freed which leads to a DoS | ||
10 | through memory exhaustion. dnsmasq is vulnerable only | ||
11 | if one of the following option is specified: | ||
12 | --add-mac, --add-cpe-id or --add-subnet. | ||
13 | |||
14 | CVE: CVE-2017-14495 | ||
15 | Upstream-Status: Backport | ||
16 | |||
17 | Signed-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 | |||
23 | diff --git a/CHANGELOG b/CHANGELOG | ||
24 | index 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 | ||
46 | diff --git a/src/edns0.c b/src/edns0.c | ||
47 | index 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 | -- | ||
68 | 1.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 @@ | |||
1 | From 897c113fda0886a28a986cc6ba17bb93bd6cb1c7 Mon Sep 17 00:00:00 2001 | ||
2 | From: Simon Kelley <simon@thekelleys.org.uk> | ||
3 | Date: Mon, 25 Sep 2017 20:11:58 +0100 | ||
4 | Subject: [PATCH] Security fix, CVE-2017-14496, Integer underflow in DNS | ||
5 | response creation. | ||
6 | |||
7 | Fix DoS in DNS. Invalid boundary checks in the | ||
8 | add_pseudoheader function allows a memcpy call with negative | ||
9 | size An attacker which can send malicious DNS queries | ||
10 | to dnsmasq can trigger a DoS remotely. | ||
11 | dnsmasq is vulnerable only if one of the following option is | ||
12 | specified: --add-mac, --add-cpe-id or --add-subnet. | ||
13 | |||
14 | CVE: CVE-2017-14496 | ||
15 | Upstream-Status: Backport | ||
16 | |||
17 | Signed-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 | |||
23 | diff --git a/CHANGELOG b/CHANGELOG | ||
24 | index 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, | ||
45 | diff --git a/src/edns0.c b/src/edns0.c | ||
46 | index 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 | -- | ||
93 | 1.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 | ||
2 | FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" | ||
3 | |||
4 | SRC_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 | " | ||