diff options
author | Yi Zhao <yi.zhao@windriver.com> | 2017-04-13 13:48:13 +0800 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-04-29 11:17:23 +0100 |
commit | 8913e94511812c44a9847bb9ea17af2469923187 (patch) | |
tree | 33c02cf052eb2313d72806627a52e95bee3ba540 /meta/recipes-connectivity | |
parent | e9c8cbdf020296325b275b10e36e5227173339ee (diff) | |
download | poky-8913e94511812c44a9847bb9ea17af2469923187.tar.gz |
bind: Security fix CVE-2016-6170
CVE-2016-6170: ISC BIND through 9.9.9-P1, 9.10.x through 9.10.4-P1, and
9.11.x through 9.11.0b1 allows primary DNS servers to cause a denial of
service (secondary DNS server crash) via a large AXFR response, and
possibly allows IXFR servers to cause a denial of service (IXFR client
crash) via a large IXFR response and allows remote authenticated users
to cause a denial of service (primary DNS server crash) via a large
UPDATE message.
External References:
https://nvd.nist.gov/vuln/detail/CVE-2016-6170
Patch from:
https://source.isc.org/cgi-bin/gitweb.cgi?p=bind9.git;a=commit;h=1bbcfe2fc84f57b1e4e075fb3bc2a1dd0a3a851f
(From OE-Core rev: 14abd767349bc868ca59838f1af3aaf17dfe4350)
Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-connectivity')
-rw-r--r-- | meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch | 1090 | ||||
-rw-r--r-- | meta/recipes-connectivity/bind/bind_9.10.3-P3.bb | 1 |
2 files changed, 1091 insertions, 0 deletions
diff --git a/meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch b/meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch new file mode 100644 index 0000000000..75bc211cb6 --- /dev/null +++ b/meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch | |||
@@ -0,0 +1,1090 @@ | |||
1 | From 1bbcfe2fc84f57b1e4e075fb3bc2a1dd0a3a851f Mon Sep 17 00:00:00 2001 | ||
2 | From: Mark Andrews <marka@isc.org> | ||
3 | Date: Wed, 2 Nov 2016 17:31:27 +1100 | ||
4 | Subject: [PATCH] 4504. [security] Allow the maximum number of records in a | ||
5 | zone to be specified. This provides a control for issues raised in | ||
6 | CVE-2016-6170. [RT #42143] | ||
7 | |||
8 | (cherry picked from commit 5f8412a4cb5ee14a0e8cddd4107854b40ee3291e) | ||
9 | |||
10 | Upstream-Status: Backport | ||
11 | [https://source.isc.org/cgi-bin/gitweb.cgi?p=bind9.git;a=commit;h=1bbcfe2fc84f57b1e4e075fb3bc2a1dd0a3a851f] | ||
12 | |||
13 | CVE: CVE-2016-6170 | ||
14 | |||
15 | Signed-off-by: Yi Zhao <yi.zhao@windriver.com> | ||
16 | --- | ||
17 | CHANGES | 4 + | ||
18 | bin/named/config.c | 1 + | ||
19 | bin/named/named.conf.docbook | 3 + | ||
20 | bin/named/update.c | 16 +++ | ||
21 | bin/named/zoneconf.c | 7 ++ | ||
22 | bin/tests/system/nsupdate/clean.sh | 1 + | ||
23 | bin/tests/system/nsupdate/ns3/named.conf | 7 ++ | ||
24 | bin/tests/system/nsupdate/ns3/too-big.test.db.in | 10 ++ | ||
25 | bin/tests/system/nsupdate/setup.sh | 2 + | ||
26 | bin/tests/system/nsupdate/tests.sh | 15 +++ | ||
27 | bin/tests/system/xfer/clean.sh | 1 + | ||
28 | bin/tests/system/xfer/ns1/axfr-too-big.db | 10 ++ | ||
29 | bin/tests/system/xfer/ns1/ixfr-too-big.db.in | 13 +++ | ||
30 | bin/tests/system/xfer/ns1/named.conf | 11 ++ | ||
31 | bin/tests/system/xfer/ns6/named.conf | 14 +++ | ||
32 | bin/tests/system/xfer/setup.sh | 2 + | ||
33 | bin/tests/system/xfer/tests.sh | 26 +++++ | ||
34 | doc/arm/Bv9ARM-book.xml | 21 ++++ | ||
35 | doc/arm/notes.xml | 9 ++ | ||
36 | lib/bind9/check.c | 2 + | ||
37 | lib/dns/db.c | 13 +++ | ||
38 | lib/dns/ecdb.c | 3 +- | ||
39 | lib/dns/include/dns/db.h | 20 ++++ | ||
40 | lib/dns/include/dns/rdataslab.h | 13 +++ | ||
41 | lib/dns/include/dns/result.h | 6 +- | ||
42 | lib/dns/include/dns/zone.h | 28 ++++- | ||
43 | lib/dns/rbtdb.c | 127 +++++++++++++++++++++-- | ||
44 | lib/dns/rdataslab.c | 13 +++ | ||
45 | lib/dns/result.c | 9 +- | ||
46 | lib/dns/sdb.c | 3 +- | ||
47 | lib/dns/sdlz.c | 3 +- | ||
48 | lib/dns/xfrin.c | 22 +++- | ||
49 | lib/dns/zone.c | 23 +++- | ||
50 | lib/isccfg/namedconf.c | 1 + | ||
51 | 34 files changed, 444 insertions(+), 15 deletions(-) | ||
52 | create mode 100644 bin/tests/system/nsupdate/ns3/too-big.test.db.in | ||
53 | create mode 100644 bin/tests/system/xfer/ns1/axfr-too-big.db | ||
54 | create mode 100644 bin/tests/system/xfer/ns1/ixfr-too-big.db.in | ||
55 | |||
56 | diff --git a/CHANGES b/CHANGES | ||
57 | index 41cfce5..97d2e60 100644 | ||
58 | --- a/CHANGES | ||
59 | +++ b/CHANGES | ||
60 | @@ -1,3 +1,7 @@ | ||
61 | +4504. [security] Allow the maximum number of records in a zone to | ||
62 | + be specified. This provides a control for issues | ||
63 | + raised in CVE-2016-6170. [RT #42143] | ||
64 | + | ||
65 | 4489. [security] It was possible to trigger assertions when processing | ||
66 | a response. (CVE-2016-8864) [RT #43465] | ||
67 | |||
68 | diff --git a/bin/named/config.c b/bin/named/config.c | ||
69 | index f06348c..c24e334 100644 | ||
70 | --- a/bin/named/config.c | ||
71 | +++ b/bin/named/config.c | ||
72 | @@ -209,6 +209,7 @@ options {\n\ | ||
73 | max-transfer-time-out 120;\n\ | ||
74 | max-transfer-idle-in 60;\n\ | ||
75 | max-transfer-idle-out 60;\n\ | ||
76 | + max-records 0;\n\ | ||
77 | max-retry-time 1209600; /* 2 weeks */\n\ | ||
78 | min-retry-time 500;\n\ | ||
79 | max-refresh-time 2419200; /* 4 weeks */\n\ | ||
80 | diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook | ||
81 | index 4c99a61..c2d173a 100644 | ||
82 | --- a/bin/named/named.conf.docbook | ||
83 | +++ b/bin/named/named.conf.docbook | ||
84 | @@ -338,6 +338,7 @@ options { | ||
85 | }; | ||
86 | |||
87 | max-journal-size <replaceable>size_no_default</replaceable>; | ||
88 | + max-records <replaceable>integer</replaceable>; | ||
89 | max-transfer-time-in <replaceable>integer</replaceable>; | ||
90 | max-transfer-time-out <replaceable>integer</replaceable>; | ||
91 | max-transfer-idle-in <replaceable>integer</replaceable>; | ||
92 | @@ -527,6 +528,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable> | ||
93 | }; | ||
94 | |||
95 | max-journal-size <replaceable>size_no_default</replaceable>; | ||
96 | + max-records <replaceable>integer</replaceable>; | ||
97 | max-transfer-time-in <replaceable>integer</replaceable>; | ||
98 | max-transfer-time-out <replaceable>integer</replaceable>; | ||
99 | max-transfer-idle-in <replaceable>integer</replaceable>; | ||
100 | @@ -624,6 +626,7 @@ zone <replaceable>string</replaceable> <replaceable>optional_class</replaceable> | ||
101 | }; | ||
102 | |||
103 | max-journal-size <replaceable>size_no_default</replaceable>; | ||
104 | + max-records <replaceable>integer</replaceable>; | ||
105 | max-transfer-time-in <replaceable>integer</replaceable>; | ||
106 | max-transfer-time-out <replaceable>integer</replaceable>; | ||
107 | max-transfer-idle-in <replaceable>integer</replaceable>; | ||
108 | diff --git a/bin/named/update.c b/bin/named/update.c | ||
109 | index 83b1a05..cc2a611 100644 | ||
110 | --- a/bin/named/update.c | ||
111 | +++ b/bin/named/update.c | ||
112 | @@ -2455,6 +2455,8 @@ update_action(isc_task_t *task, isc_event_t *event) { | ||
113 | isc_boolean_t had_dnskey; | ||
114 | dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); | ||
115 | dns_ttl_t maxttl = 0; | ||
116 | + isc_uint32_t maxrecords; | ||
117 | + isc_uint64_t records; | ||
118 | |||
119 | INSIST(event->ev_type == DNS_EVENT_UPDATE); | ||
120 | |||
121 | @@ -3138,6 +3140,20 @@ update_action(isc_task_t *task, isc_event_t *event) { | ||
122 | } | ||
123 | } | ||
124 | |||
125 | + maxrecords = dns_zone_getmaxrecords(zone); | ||
126 | + if (maxrecords != 0U) { | ||
127 | + result = dns_db_getsize(db, ver, &records, NULL); | ||
128 | + if (result == ISC_R_SUCCESS && records > maxrecords) { | ||
129 | + update_log(client, zone, ISC_LOG_ERROR, | ||
130 | + "records in zone (%" | ||
131 | + ISC_PRINT_QUADFORMAT | ||
132 | + "u) exceeds max-records (%u)", | ||
133 | + records, maxrecords); | ||
134 | + result = DNS_R_TOOMANYRECORDS; | ||
135 | + goto failure; | ||
136 | + } | ||
137 | + } | ||
138 | + | ||
139 | journalfile = dns_zone_getjournal(zone); | ||
140 | if (journalfile != NULL) { | ||
141 | update_log(client, zone, LOGLEVEL_DEBUG, | ||
142 | diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c | ||
143 | index 4ee3dfe..14dd8ce 100644 | ||
144 | --- a/bin/named/zoneconf.c | ||
145 | +++ b/bin/named/zoneconf.c | ||
146 | @@ -978,6 +978,13 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, | ||
147 | dns_zone_setmaxttl(raw, maxttl); | ||
148 | } | ||
149 | |||
150 | + obj = NULL; | ||
151 | + result = ns_config_get(maps, "max-records", &obj); | ||
152 | + INSIST(result == ISC_R_SUCCESS && obj != NULL); | ||
153 | + dns_zone_setmaxrecords(mayberaw, cfg_obj_asuint32(obj)); | ||
154 | + if (zone != mayberaw) | ||
155 | + dns_zone_setmaxrecords(zone, 0); | ||
156 | + | ||
157 | if (raw != NULL && filename != NULL) { | ||
158 | #define SIGNED ".signed" | ||
159 | size_t signedlen = strlen(filename) + sizeof(SIGNED); | ||
160 | diff --git a/bin/tests/system/nsupdate/clean.sh b/bin/tests/system/nsupdate/clean.sh | ||
161 | index aaefc02..ea25545 100644 | ||
162 | --- a/bin/tests/system/nsupdate/clean.sh | ||
163 | +++ b/bin/tests/system/nsupdate/clean.sh | ||
164 | @@ -32,6 +32,7 @@ rm -f ns3/example.db.jnl ns3/example.db | ||
165 | rm -f ns3/nsec3param.test.db.signed.jnl ns3/nsec3param.test.db ns3/nsec3param.test.db.signed ns3/dsset-nsec3param.test. | ||
166 | rm -f ns3/dnskey.test.db.signed.jnl ns3/dnskey.test.db ns3/dnskey.test.db.signed ns3/dsset-dnskey.test. | ||
167 | rm -f ns3/K* | ||
168 | +rm -f ns3/too-big.test.db | ||
169 | rm -f dig.out.* | ||
170 | rm -f jp.out.ns3.* | ||
171 | rm -f Kxxx.* | ||
172 | diff --git a/bin/tests/system/nsupdate/ns3/named.conf b/bin/tests/system/nsupdate/ns3/named.conf | ||
173 | index 2abd522..68ff27a 100644 | ||
174 | --- a/bin/tests/system/nsupdate/ns3/named.conf | ||
175 | +++ b/bin/tests/system/nsupdate/ns3/named.conf | ||
176 | @@ -60,3 +60,10 @@ zone "dnskey.test" { | ||
177 | allow-update { any; }; | ||
178 | file "dnskey.test.db.signed"; | ||
179 | }; | ||
180 | + | ||
181 | +zone "too-big.test" { | ||
182 | + type master; | ||
183 | + allow-update { any; }; | ||
184 | + max-records 3; | ||
185 | + file "too-big.test.db"; | ||
186 | +}; | ||
187 | diff --git a/bin/tests/system/nsupdate/ns3/too-big.test.db.in b/bin/tests/system/nsupdate/ns3/too-big.test.db.in | ||
188 | new file mode 100644 | ||
189 | index 0000000..7ff1e4a | ||
190 | --- /dev/null | ||
191 | +++ b/bin/tests/system/nsupdate/ns3/too-big.test.db.in | ||
192 | @@ -0,0 +1,10 @@ | ||
193 | +; Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") | ||
194 | +; | ||
195 | +; This Source Code Form is subject to the terms of the Mozilla Public | ||
196 | +; License, v. 2.0. If a copy of the MPL was not distributed with this | ||
197 | +; file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
198 | + | ||
199 | +$TTL 10 | ||
200 | +too-big.test. IN SOA too-big.test. hostmaster.too-big.test. 1 3600 900 2419200 3600 | ||
201 | +too-big.test. IN NS too-big.test. | ||
202 | +too-big.test. IN A 10.53.0.3 | ||
203 | diff --git a/bin/tests/system/nsupdate/setup.sh b/bin/tests/system/nsupdate/setup.sh | ||
204 | index 828255e..43c4094 100644 | ||
205 | --- a/bin/tests/system/nsupdate/setup.sh | ||
206 | +++ b/bin/tests/system/nsupdate/setup.sh | ||
207 | @@ -27,12 +27,14 @@ test -r $RANDFILE || $GENRANDOM 400 $RANDFILE | ||
208 | rm -f ns1/*.jnl ns1/example.db ns2/*.jnl ns2/example.bk | ||
209 | rm -f ns2/update.bk ns2/update.alt.bk | ||
210 | rm -f ns3/example.db.jnl | ||
211 | +rm -f ns3/too-big.test.db.jnl | ||
212 | |||
213 | cp -f ns1/example1.db ns1/example.db | ||
214 | sed 's/example.nil/other.nil/g' ns1/example1.db > ns1/other.db | ||
215 | sed 's/example.nil/unixtime.nil/g' ns1/example1.db > ns1/unixtime.db | ||
216 | sed 's/example.nil/keytests.nil/g' ns1/example1.db > ns1/keytests.db | ||
217 | cp -f ns3/example.db.in ns3/example.db | ||
218 | +cp -f ns3/too-big.test.db.in ns3/too-big.test.db | ||
219 | |||
220 | # update_test.pl has its own zone file because it | ||
221 | # requires a specific NS record set. | ||
222 | diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh | ||
223 | index 78d501e..0a6bbd3 100755 | ||
224 | --- a/bin/tests/system/nsupdate/tests.sh | ||
225 | +++ b/bin/tests/system/nsupdate/tests.sh | ||
226 | @@ -581,5 +581,20 @@ if [ $ret -ne 0 ]; then | ||
227 | status=1 | ||
228 | fi | ||
229 | |||
230 | +n=`expr $n + 1` | ||
231 | +echo "I:check that adding too many records is blocked ($n)" | ||
232 | +ret=0 | ||
233 | +$NSUPDATE -v << EOF > nsupdate.out-$n 2>&1 && ret=1 | ||
234 | +server 10.53.0.3 5300 | ||
235 | +zone too-big.test. | ||
236 | +update add r1.too-big.test 3600 IN TXT r1.too-big.test | ||
237 | +send | ||
238 | +EOF | ||
239 | +grep "update failed: SERVFAIL" nsupdate.out-$n > /dev/null || ret=1 | ||
240 | +DIG +tcp @10.53.0.3 -p 5300 r1.too-big.test TXT > dig.out.ns3.test$n | ||
241 | +grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1 | ||
242 | +grep "records in zone (4) exceeds max-records (3)" ns3/named.run > /dev/null || ret=1 | ||
243 | +[ $ret = 0 ] || { echo I:failed; status=1; } | ||
244 | + | ||
245 | echo "I:exit status: $status" | ||
246 | exit $status | ||
247 | diff --git a/bin/tests/system/xfer/clean.sh b/bin/tests/system/xfer/clean.sh | ||
248 | index 48aa159..da62a33 100644 | ||
249 | --- a/bin/tests/system/xfer/clean.sh | ||
250 | +++ b/bin/tests/system/xfer/clean.sh | ||
251 | @@ -36,3 +36,4 @@ rm -f ns7/*.db ns7/*.bk ns7/*.jnl | ||
252 | rm -f */named.memstats | ||
253 | rm -f */named.run | ||
254 | rm -f */ans.run | ||
255 | +rm -f ns1/ixfr-too-big.db ns1/ixfr-too-big.db.jnl | ||
256 | diff --git a/bin/tests/system/xfer/ns1/axfr-too-big.db b/bin/tests/system/xfer/ns1/axfr-too-big.db | ||
257 | new file mode 100644 | ||
258 | index 0000000..d43760d | ||
259 | --- /dev/null | ||
260 | +++ b/bin/tests/system/xfer/ns1/axfr-too-big.db | ||
261 | @@ -0,0 +1,10 @@ | ||
262 | +; Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") | ||
263 | +; | ||
264 | +; This Source Code Form is subject to the terms of the Mozilla Public | ||
265 | +; License, v. 2.0. If a copy of the MPL was not distributed with this | ||
266 | +; file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
267 | + | ||
268 | +$TTL 3600 | ||
269 | +@ IN SOA . . 0 0 0 0 0 | ||
270 | +@ IN NS . | ||
271 | +$GENERATE 1-29 host$ A 1.2.3.$ | ||
272 | diff --git a/bin/tests/system/xfer/ns1/ixfr-too-big.db.in b/bin/tests/system/xfer/ns1/ixfr-too-big.db.in | ||
273 | new file mode 100644 | ||
274 | index 0000000..318bb77 | ||
275 | --- /dev/null | ||
276 | +++ b/bin/tests/system/xfer/ns1/ixfr-too-big.db.in | ||
277 | @@ -0,0 +1,13 @@ | ||
278 | +; Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") | ||
279 | +; | ||
280 | +; This Source Code Form is subject to the terms of the Mozilla Public | ||
281 | +; License, v. 2.0. If a copy of the MPL was not distributed with this | ||
282 | +; file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
283 | + | ||
284 | +$TTL 3600 | ||
285 | +@ IN SOA . . 0 0 0 0 0 | ||
286 | +@ IN NS ns1 | ||
287 | +@ IN NS ns6 | ||
288 | +ns1 IN A 10.53.0.1 | ||
289 | +ns6 IN A 10.53.0.6 | ||
290 | +$GENERATE 1-25 host$ A 1.2.3.$ | ||
291 | diff --git a/bin/tests/system/xfer/ns1/named.conf b/bin/tests/system/xfer/ns1/named.conf | ||
292 | index 07dad85..1d29292 100644 | ||
293 | --- a/bin/tests/system/xfer/ns1/named.conf | ||
294 | +++ b/bin/tests/system/xfer/ns1/named.conf | ||
295 | @@ -44,3 +44,14 @@ zone "slave" { | ||
296 | type master; | ||
297 | file "slave.db"; | ||
298 | }; | ||
299 | + | ||
300 | +zone "axfr-too-big" { | ||
301 | + type master; | ||
302 | + file "axfr-too-big.db"; | ||
303 | +}; | ||
304 | + | ||
305 | +zone "ixfr-too-big" { | ||
306 | + type master; | ||
307 | + allow-update { any; }; | ||
308 | + file "ixfr-too-big.db"; | ||
309 | +}; | ||
310 | diff --git a/bin/tests/system/xfer/ns6/named.conf b/bin/tests/system/xfer/ns6/named.conf | ||
311 | index c9421b1..a12a92c 100644 | ||
312 | --- a/bin/tests/system/xfer/ns6/named.conf | ||
313 | +++ b/bin/tests/system/xfer/ns6/named.conf | ||
314 | @@ -52,3 +52,17 @@ zone "slave" { | ||
315 | masters { 10.53.0.1; }; | ||
316 | file "slave.bk"; | ||
317 | }; | ||
318 | + | ||
319 | +zone "axfr-too-big" { | ||
320 | + type slave; | ||
321 | + max-records 30; | ||
322 | + masters { 10.53.0.1; }; | ||
323 | + file "axfr-too-big.bk"; | ||
324 | +}; | ||
325 | + | ||
326 | +zone "ixfr-too-big" { | ||
327 | + type slave; | ||
328 | + max-records 30; | ||
329 | + masters { 10.53.0.1; }; | ||
330 | + file "ixfr-too-big.bk"; | ||
331 | +}; | ||
332 | diff --git a/bin/tests/system/xfer/setup.sh b/bin/tests/system/xfer/setup.sh | ||
333 | index 56ca901..c55abf8 100644 | ||
334 | --- a/bin/tests/system/xfer/setup.sh | ||
335 | +++ b/bin/tests/system/xfer/setup.sh | ||
336 | @@ -33,3 +33,5 @@ cp -f ns4/named.conf.base ns4/named.conf | ||
337 | |||
338 | cp ns2/slave.db.in ns2/slave.db | ||
339 | touch -t 200101010000 ns2/slave.db | ||
340 | + | ||
341 | +cp -f ns1/ixfr-too-big.db.in ns1/ixfr-too-big.db | ||
342 | diff --git a/bin/tests/system/xfer/tests.sh b/bin/tests/system/xfer/tests.sh | ||
343 | index 67b2a1a..fe33f0a 100644 | ||
344 | --- a/bin/tests/system/xfer/tests.sh | ||
345 | +++ b/bin/tests/system/xfer/tests.sh | ||
346 | @@ -368,5 +368,31 @@ $DIGCMD nil. TXT | grep 'incorrect key AXFR' >/dev/null && { | ||
347 | status=1 | ||
348 | } | ||
349 | |||
350 | +n=`expr $n + 1` | ||
351 | +echo "I:test that a zone with too many records is rejected (AXFR) ($n)" | ||
352 | +tmp=0 | ||
353 | +grep "'axfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null || tmp=1 | ||
354 | +if test $tmp != 0 ; then echo "I:failed"; fi | ||
355 | +status=`expr $status + $tmp` | ||
356 | + | ||
357 | +n=`expr $n + 1` | ||
358 | +echo "I:test that a zone with too many records is rejected (IXFR) ($n)" | ||
359 | +tmp=0 | ||
360 | +grep "'ixfr-too-big./IN.*: too many records" ns6/named.run >/dev/null && tmp=1 | ||
361 | +$NSUPDATE << EOF | ||
362 | +zone ixfr-too-big | ||
363 | +server 10.53.0.1 5300 | ||
364 | +update add the-31st-record.ixfr-too-big 0 TXT this is it | ||
365 | +send | ||
366 | +EOF | ||
367 | +for i in 1 2 3 4 5 6 7 8 | ||
368 | +do | ||
369 | + grep "'ixfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null && break | ||
370 | + sleep 1 | ||
371 | +done | ||
372 | +grep "'ixfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null || tmp=1 | ||
373 | +if test $tmp != 0 ; then echo "I:failed"; fi | ||
374 | +status=`expr $status + $tmp` | ||
375 | + | ||
376 | echo "I:exit status: $status" | ||
377 | exit $status | ||
378 | diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml | ||
379 | index 848b582..0369505 100644 | ||
380 | --- a/doc/arm/Bv9ARM-book.xml | ||
381 | +++ b/doc/arm/Bv9ARM-book.xml | ||
382 | @@ -4858,6 +4858,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] | ||
383 | <optional> use-queryport-pool <replaceable>yes_or_no</replaceable>; </optional> | ||
384 | <optional> queryport-pool-ports <replaceable>number</replaceable>; </optional> | ||
385 | <optional> queryport-pool-updateinterval <replaceable>number</replaceable>; </optional> | ||
386 | + <optional> max-records <replaceable>number</replaceable>; </optional> | ||
387 | <optional> max-transfer-time-in <replaceable>number</replaceable>; </optional> | ||
388 | <optional> max-transfer-time-out <replaceable>number</replaceable>; </optional> | ||
389 | <optional> max-transfer-idle-in <replaceable>number</replaceable>; </optional> | ||
390 | @@ -8164,6 +8165,16 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; | ||
391 | </varlistentry> | ||
392 | |||
393 | <varlistentry> | ||
394 | + <term><command>max-records</command></term> | ||
395 | + <listitem> | ||
396 | + <para> | ||
397 | + The maximum number of records permitted in a zone. | ||
398 | + The default is zero which means unlimited. | ||
399 | + </para> | ||
400 | + </listitem> | ||
401 | + </varlistentry> | ||
402 | + | ||
403 | + <varlistentry> | ||
404 | <term><command>host-statistics-max</command></term> | ||
405 | <listitem> | ||
406 | <para> | ||
407 | @@ -12056,6 +12067,16 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea | ||
408 | </varlistentry> | ||
409 | |||
410 | <varlistentry> | ||
411 | + <term><command>max-records</command></term> | ||
412 | + <listitem> | ||
413 | + <para> | ||
414 | + See the description of | ||
415 | + <command>max-records</command> in <xref linkend="server_resource_limits"/>. | ||
416 | + </para> | ||
417 | + </listitem> | ||
418 | + </varlistentry> | ||
419 | + | ||
420 | + <varlistentry> | ||
421 | <term><command>max-transfer-time-in</command></term> | ||
422 | <listitem> | ||
423 | <para> | ||
424 | diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml | ||
425 | index 095eb5b..36495e7 100644 | ||
426 | --- a/doc/arm/notes.xml | ||
427 | +++ b/doc/arm/notes.xml | ||
428 | @@ -52,6 +52,15 @@ | ||
429 | <itemizedlist> | ||
430 | <listitem> | ||
431 | <para> | ||
432 | + Added the ability to specify the maximum number of records | ||
433 | + permitted in a zone (max-records #;). This provides a mechanism | ||
434 | + to block overly large zone transfers, which is a potential risk | ||
435 | + with slave zones from other parties, as described in CVE-2016-6170. | ||
436 | + [RT #42143] | ||
437 | + </para> | ||
438 | + </listitem> | ||
439 | + <listitem> | ||
440 | + <para> | ||
441 | Duplicate EDNS COOKIE options in a response could trigger | ||
442 | an assertion failure. This flaw is disclosed in CVE-2016-2088. | ||
443 | [RT #41809] | ||
444 | diff --git a/lib/bind9/check.c b/lib/bind9/check.c | ||
445 | index b8c05dd..edb7534 100644 | ||
446 | --- a/lib/bind9/check.c | ||
447 | +++ b/lib/bind9/check.c | ||
448 | @@ -1510,6 +1510,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, | ||
449 | REDIRECTZONE }, | ||
450 | { "masters", SLAVEZONE | STUBZONE | REDIRECTZONE }, | ||
451 | { "max-ixfr-log-size", MASTERZONE | SLAVEZONE | STREDIRECTZONE }, | ||
452 | + { "max-records", MASTERZONE | SLAVEZONE | STUBZONE | STREDIRECTZONE | | ||
453 | + STATICSTUBZONE | REDIRECTZONE }, | ||
454 | { "max-refresh-time", SLAVEZONE | STUBZONE | STREDIRECTZONE }, | ||
455 | { "max-retry-time", SLAVEZONE | STUBZONE | STREDIRECTZONE }, | ||
456 | { "max-transfer-idle-in", SLAVEZONE | STUBZONE | STREDIRECTZONE }, | ||
457 | diff --git a/lib/dns/db.c b/lib/dns/db.c | ||
458 | index 7e4f357..ced94a5 100644 | ||
459 | --- a/lib/dns/db.c | ||
460 | +++ b/lib/dns/db.c | ||
461 | @@ -999,6 +999,19 @@ dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, | ||
462 | } | ||
463 | |||
464 | isc_result_t | ||
465 | +dns_db_getsize(dns_db_t *db, dns_dbversion_t *version, isc_uint64_t *records, | ||
466 | + isc_uint64_t *bytes) | ||
467 | +{ | ||
468 | + REQUIRE(DNS_DB_VALID(db)); | ||
469 | + REQUIRE(dns_db_iszone(db) == ISC_TRUE); | ||
470 | + | ||
471 | + if (db->methods->getsize != NULL) | ||
472 | + return ((db->methods->getsize)(db, version, records, bytes)); | ||
473 | + | ||
474 | + return (ISC_R_NOTFOUND); | ||
475 | +} | ||
476 | + | ||
477 | +isc_result_t | ||
478 | dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, | ||
479 | isc_stdtime_t resign) | ||
480 | { | ||
481 | diff --git a/lib/dns/ecdb.c b/lib/dns/ecdb.c | ||
482 | index 553a339..b5d04d2 100644 | ||
483 | --- a/lib/dns/ecdb.c | ||
484 | +++ b/lib/dns/ecdb.c | ||
485 | @@ -587,7 +587,8 @@ static dns_dbmethods_t ecdb_methods = { | ||
486 | NULL, /* findnodeext */ | ||
487 | NULL, /* findext */ | ||
488 | NULL, /* setcachestats */ | ||
489 | - NULL /* hashsize */ | ||
490 | + NULL, /* hashsize */ | ||
491 | + NULL /* getsize */ | ||
492 | }; | ||
493 | |||
494 | static isc_result_t | ||
495 | diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h | ||
496 | index a4a4482..aff42d6 100644 | ||
497 | --- a/lib/dns/include/dns/db.h | ||
498 | +++ b/lib/dns/include/dns/db.h | ||
499 | @@ -195,6 +195,8 @@ typedef struct dns_dbmethods { | ||
500 | dns_rdataset_t *sigrdataset); | ||
501 | isc_result_t (*setcachestats)(dns_db_t *db, isc_stats_t *stats); | ||
502 | unsigned int (*hashsize)(dns_db_t *db); | ||
503 | + isc_result_t (*getsize)(dns_db_t *db, dns_dbversion_t *version, | ||
504 | + isc_uint64_t *records, isc_uint64_t *bytes); | ||
505 | } dns_dbmethods_t; | ||
506 | |||
507 | typedef isc_result_t | ||
508 | @@ -1485,6 +1487,24 @@ dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, | ||
509 | */ | ||
510 | |||
511 | isc_result_t | ||
512 | +dns_db_getsize(dns_db_t *db, dns_dbversion_t *version, isc_uint64_t *records, | ||
513 | + isc_uint64_t *bytes); | ||
514 | +/*%< | ||
515 | + * Get the number of records in the given version of the database as well | ||
516 | + * as the number bytes used to store those records. | ||
517 | + * | ||
518 | + * Requires: | ||
519 | + * \li 'db' is a valid zone database. | ||
520 | + * \li 'version' is NULL or a valid version. | ||
521 | + * \li 'records' is NULL or a pointer to return the record count in. | ||
522 | + * \li 'bytes' is NULL or a pointer to return the byte count in. | ||
523 | + * | ||
524 | + * Returns: | ||
525 | + * \li #ISC_R_SUCCESS | ||
526 | + * \li #ISC_R_NOTIMPLEMENTED | ||
527 | + */ | ||
528 | + | ||
529 | +isc_result_t | ||
530 | dns_db_findnsec3node(dns_db_t *db, dns_name_t *name, | ||
531 | isc_boolean_t create, dns_dbnode_t **nodep); | ||
532 | /*%< | ||
533 | diff --git a/lib/dns/include/dns/rdataslab.h b/lib/dns/include/dns/rdataslab.h | ||
534 | index 3ac44b8..2e1e759 100644 | ||
535 | --- a/lib/dns/include/dns/rdataslab.h | ||
536 | +++ b/lib/dns/include/dns/rdataslab.h | ||
537 | @@ -104,6 +104,7 @@ dns_rdataslab_tordataset(unsigned char *slab, unsigned int reservelen, | ||
538 | * Ensures: | ||
539 | *\li 'rdataset' is associated and points to a valid rdataest. | ||
540 | */ | ||
541 | + | ||
542 | unsigned int | ||
543 | dns_rdataslab_size(unsigned char *slab, unsigned int reservelen); | ||
544 | /*%< | ||
545 | @@ -116,6 +117,18 @@ dns_rdataslab_size(unsigned char *slab, unsigned int reservelen); | ||
546 | *\li The number of bytes in the slab, including the reservelen. | ||
547 | */ | ||
548 | |||
549 | +unsigned int | ||
550 | +dns_rdataslab_count(unsigned char *slab, unsigned int reservelen); | ||
551 | +/*%< | ||
552 | + * Return the number of records in the rdataslab | ||
553 | + * | ||
554 | + * Requires: | ||
555 | + *\li 'slab' points to a slab. | ||
556 | + * | ||
557 | + * Returns: | ||
558 | + *\li The number of records in the slab. | ||
559 | + */ | ||
560 | + | ||
561 | isc_result_t | ||
562 | dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab, | ||
563 | unsigned int reservelen, isc_mem_t *mctx, | ||
564 | diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h | ||
565 | index 7d11c2b..93d1fd5 100644 | ||
566 | --- a/lib/dns/include/dns/result.h | ||
567 | +++ b/lib/dns/include/dns/result.h | ||
568 | @@ -157,8 +157,12 @@ | ||
569 | #define DNS_R_BADCDS (ISC_RESULTCLASS_DNS + 111) | ||
570 | #define DNS_R_BADCDNSKEY (ISC_RESULTCLASS_DNS + 112) | ||
571 | #define DNS_R_OPTERR (ISC_RESULTCLASS_DNS + 113) | ||
572 | +#define DNS_R_BADDNSTAP (ISC_RESULTCLASS_DNS + 114) | ||
573 | +#define DNS_R_BADTSIG (ISC_RESULTCLASS_DNS + 115) | ||
574 | +#define DNS_R_BADSIG0 (ISC_RESULTCLASS_DNS + 116) | ||
575 | +#define DNS_R_TOOMANYRECORDS (ISC_RESULTCLASS_DNS + 117) | ||
576 | |||
577 | -#define DNS_R_NRESULTS 114 /*%< Number of results */ | ||
578 | +#define DNS_R_NRESULTS 118 /*%< Number of results */ | ||
579 | |||
580 | /* | ||
581 | * DNS wire format rcodes. | ||
582 | diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h | ||
583 | index a9367f1..227540b 100644 | ||
584 | --- a/lib/dns/include/dns/zone.h | ||
585 | +++ b/lib/dns/include/dns/zone.h | ||
586 | @@ -296,6 +296,32 @@ dns_zone_getfile(dns_zone_t *zone); | ||
587 | */ | ||
588 | |||
589 | void | ||
590 | +dns_zone_setmaxrecords(dns_zone_t *zone, isc_uint32_t records); | ||
591 | +/*%< | ||
592 | + * Sets the maximim number of records permitted in a zone. | ||
593 | + * 0 implies unlimited. | ||
594 | + * | ||
595 | + * Requires: | ||
596 | + *\li 'zone' to be valid initialised zone. | ||
597 | + * | ||
598 | + * Returns: | ||
599 | + *\li void | ||
600 | + */ | ||
601 | + | ||
602 | +isc_uint32_t | ||
603 | +dns_zone_getmaxrecords(dns_zone_t *zone); | ||
604 | +/*%< | ||
605 | + * Gets the maximim number of records permitted in a zone. | ||
606 | + * 0 implies unlimited. | ||
607 | + * | ||
608 | + * Requires: | ||
609 | + *\li 'zone' to be valid initialised zone. | ||
610 | + * | ||
611 | + * Returns: | ||
612 | + *\li isc_uint32_t maxrecords. | ||
613 | + */ | ||
614 | + | ||
615 | +void | ||
616 | dns_zone_setmaxttl(dns_zone_t *zone, isc_uint32_t maxttl); | ||
617 | /*%< | ||
618 | * Sets the max ttl of the zone. | ||
619 | @@ -316,7 +342,7 @@ dns_zone_getmaxttl(dns_zone_t *zone); | ||
620 | *\li 'zone' to be valid initialised zone. | ||
621 | * | ||
622 | * Returns: | ||
623 | - *\li isc_uint32_t maxttl. | ||
624 | + *\li dns_ttl_t maxttl. | ||
625 | */ | ||
626 | |||
627 | isc_result_t | ||
628 | diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c | ||
629 | index 62becfc..72d722f 100644 | ||
630 | --- a/lib/dns/rbtdb.c | ||
631 | +++ b/lib/dns/rbtdb.c | ||
632 | @@ -209,6 +209,7 @@ typedef isc_uint64_t rbtdb_serial_t; | ||
633 | #define free_rbtdb_callback free_rbtdb_callback64 | ||
634 | #define free_rdataset free_rdataset64 | ||
635 | #define getnsec3parameters getnsec3parameters64 | ||
636 | +#define getsize getsize64 | ||
637 | #define getoriginnode getoriginnode64 | ||
638 | #define getrrsetstats getrrsetstats64 | ||
639 | #define getsigningtime getsigningtime64 | ||
640 | @@ -589,6 +590,13 @@ typedef struct rbtdb_version { | ||
641 | isc_uint16_t iterations; | ||
642 | isc_uint8_t salt_length; | ||
643 | unsigned char salt[DNS_NSEC3_SALTSIZE]; | ||
644 | + | ||
645 | + /* | ||
646 | + * records and bytes are covered by rwlock. | ||
647 | + */ | ||
648 | + isc_rwlock_t rwlock; | ||
649 | + isc_uint64_t records; | ||
650 | + isc_uint64_t bytes; | ||
651 | } rbtdb_version_t; | ||
652 | |||
653 | typedef ISC_LIST(rbtdb_version_t) rbtdb_versionlist_t; | ||
654 | @@ -1130,6 +1138,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) { | ||
655 | INSIST(refs == 0); | ||
656 | UNLINK(rbtdb->open_versions, rbtdb->current_version, link); | ||
657 | isc_refcount_destroy(&rbtdb->current_version->references); | ||
658 | + isc_rwlock_destroy(&rbtdb->current_version->rwlock); | ||
659 | isc_mem_put(rbtdb->common.mctx, rbtdb->current_version, | ||
660 | sizeof(rbtdb_version_t)); | ||
661 | } | ||
662 | @@ -1383,6 +1392,7 @@ allocate_version(isc_mem_t *mctx, rbtdb_serial_t serial, | ||
663 | |||
664 | static isc_result_t | ||
665 | newversion(dns_db_t *db, dns_dbversion_t **versionp) { | ||
666 | + isc_result_t result; | ||
667 | dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; | ||
668 | rbtdb_version_t *version; | ||
669 | |||
670 | @@ -1415,13 +1425,28 @@ newversion(dns_db_t *db, dns_dbversion_t **versionp) { | ||
671 | version->salt_length = 0; | ||
672 | memset(version->salt, 0, sizeof(version->salt)); | ||
673 | } | ||
674 | - rbtdb->next_serial++; | ||
675 | - rbtdb->future_version = version; | ||
676 | - } | ||
677 | + result = isc_rwlock_init(&version->rwlock, 0, 0); | ||
678 | + if (result != ISC_R_SUCCESS) { | ||
679 | + isc_refcount_destroy(&version->references); | ||
680 | + isc_mem_put(rbtdb->common.mctx, version, | ||
681 | + sizeof(*version)); | ||
682 | + version = NULL; | ||
683 | + } else { | ||
684 | + RWLOCK(&rbtdb->current_version->rwlock, | ||
685 | + isc_rwlocktype_read); | ||
686 | + version->records = rbtdb->current_version->records; | ||
687 | + version->bytes = rbtdb->current_version->bytes; | ||
688 | + RWUNLOCK(&rbtdb->current_version->rwlock, | ||
689 | + isc_rwlocktype_read); | ||
690 | + rbtdb->next_serial++; | ||
691 | + rbtdb->future_version = version; | ||
692 | + } | ||
693 | + } else | ||
694 | + result = ISC_R_NOMEMORY; | ||
695 | RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write); | ||
696 | |||
697 | if (version == NULL) | ||
698 | - return (ISC_R_NOMEMORY); | ||
699 | + return (result); | ||
700 | |||
701 | *versionp = version; | ||
702 | |||
703 | @@ -2681,6 +2706,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { | ||
704 | |||
705 | if (cleanup_version != NULL) { | ||
706 | INSIST(EMPTY(cleanup_version->changed_list)); | ||
707 | + isc_rwlock_destroy(&cleanup_version->rwlock); | ||
708 | isc_mem_put(rbtdb->common.mctx, cleanup_version, | ||
709 | sizeof(*cleanup_version)); | ||
710 | } | ||
711 | @@ -6254,6 +6280,26 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, | ||
712 | else | ||
713 | rbtnode->data = newheader; | ||
714 | newheader->next = topheader->next; | ||
715 | + if (rbtversion != NULL) | ||
716 | + RWLOCK(&rbtversion->rwlock, isc_rwlocktype_write); | ||
717 | + if (rbtversion != NULL && !header_nx) { | ||
718 | + rbtversion->records -= | ||
719 | + dns_rdataslab_count((unsigned char *)header, | ||
720 | + sizeof(*header)); | ||
721 | + rbtversion->bytes -= | ||
722 | + dns_rdataslab_size((unsigned char *)header, | ||
723 | + sizeof(*header)); | ||
724 | + } | ||
725 | + if (rbtversion != NULL && !newheader_nx) { | ||
726 | + rbtversion->records += | ||
727 | + dns_rdataslab_count((unsigned char *)newheader, | ||
728 | + sizeof(*newheader)); | ||
729 | + rbtversion->bytes += | ||
730 | + dns_rdataslab_size((unsigned char *)newheader, | ||
731 | + sizeof(*newheader)); | ||
732 | + } | ||
733 | + if (rbtversion != NULL) | ||
734 | + RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_write); | ||
735 | if (loading) { | ||
736 | /* | ||
737 | * There are no other references to 'header' when | ||
738 | @@ -6355,6 +6401,16 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, | ||
739 | newheader->down = NULL; | ||
740 | rbtnode->data = newheader; | ||
741 | } | ||
742 | + if (rbtversion != NULL && !newheader_nx) { | ||
743 | + RWLOCK(&rbtversion->rwlock, isc_rwlocktype_write); | ||
744 | + rbtversion->records += | ||
745 | + dns_rdataslab_count((unsigned char *)newheader, | ||
746 | + sizeof(*newheader)); | ||
747 | + rbtversion->bytes += | ||
748 | + dns_rdataslab_size((unsigned char *)newheader, | ||
749 | + sizeof(*newheader)); | ||
750 | + RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_write); | ||
751 | + } | ||
752 | idx = newheader->node->locknum; | ||
753 | if (IS_CACHE(rbtdb)) { | ||
754 | ISC_LIST_PREPEND(rbtdb->rdatasets[idx], | ||
755 | @@ -6811,6 +6867,12 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, | ||
756 | */ | ||
757 | newheader->additional_auth = NULL; | ||
758 | newheader->additional_glue = NULL; | ||
759 | + rbtversion->records += | ||
760 | + dns_rdataslab_count((unsigned char *)newheader, | ||
761 | + sizeof(*newheader)); | ||
762 | + rbtversion->bytes += | ||
763 | + dns_rdataslab_size((unsigned char *)newheader, | ||
764 | + sizeof(*newheader)); | ||
765 | } else if (result == DNS_R_NXRRSET) { | ||
766 | /* | ||
767 | * This subtraction would remove all of the rdata; | ||
768 | @@ -6846,6 +6908,12 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, | ||
769 | * topheader. | ||
770 | */ | ||
771 | INSIST(rbtversion->serial >= topheader->serial); | ||
772 | + rbtversion->records -= | ||
773 | + dns_rdataslab_count((unsigned char *)header, | ||
774 | + sizeof(*header)); | ||
775 | + rbtversion->bytes -= | ||
776 | + dns_rdataslab_size((unsigned char *)header, | ||
777 | + sizeof(*header)); | ||
778 | if (topheader_prev != NULL) | ||
779 | topheader_prev->next = newheader; | ||
780 | else | ||
781 | @@ -7172,6 +7240,7 @@ rbt_datafixer(dns_rbtnode_t *rbtnode, void *base, size_t filesize, | ||
782 | unsigned char *limit = ((unsigned char *) base) + filesize; | ||
783 | unsigned char *p; | ||
784 | size_t size; | ||
785 | + unsigned int count; | ||
786 | |||
787 | REQUIRE(rbtnode != NULL); | ||
788 | |||
789 | @@ -7179,6 +7248,9 @@ rbt_datafixer(dns_rbtnode_t *rbtnode, void *base, size_t filesize, | ||
790 | p = (unsigned char *) header; | ||
791 | |||
792 | size = dns_rdataslab_size(p, sizeof(*header)); | ||
793 | + count = dns_rdataslab_count(p, sizeof(*header));; | ||
794 | + rbtdb->current_version->records += count; | ||
795 | + rbtdb->current_version->bytes += size; | ||
796 | isc_crc64_update(crc, p, size); | ||
797 | #ifdef DEBUG | ||
798 | hexdump("hashing header", p, sizeof(rdatasetheader_t)); | ||
799 | @@ -7777,6 +7849,33 @@ getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, dns_hash_t *hash, | ||
800 | } | ||
801 | |||
802 | static isc_result_t | ||
803 | +getsize(dns_db_t *db, dns_dbversion_t *version, isc_uint64_t *records, | ||
804 | + isc_uint64_t *bytes) | ||
805 | +{ | ||
806 | + dns_rbtdb_t *rbtdb; | ||
807 | + isc_result_t result = ISC_R_SUCCESS; | ||
808 | + rbtdb_version_t *rbtversion = version; | ||
809 | + | ||
810 | + rbtdb = (dns_rbtdb_t *)db; | ||
811 | + | ||
812 | + REQUIRE(VALID_RBTDB(rbtdb)); | ||
813 | + INSIST(rbtversion == NULL || rbtversion->rbtdb == rbtdb); | ||
814 | + | ||
815 | + if (rbtversion == NULL) | ||
816 | + rbtversion = rbtdb->current_version; | ||
817 | + | ||
818 | + RWLOCK(&rbtversion->rwlock, isc_rwlocktype_read); | ||
819 | + if (records != NULL) | ||
820 | + *records = rbtversion->records; | ||
821 | + | ||
822 | + if (bytes != NULL) | ||
823 | + *bytes = rbtversion->bytes; | ||
824 | + RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_read); | ||
825 | + | ||
826 | + return (result); | ||
827 | +} | ||
828 | + | ||
829 | +static isc_result_t | ||
830 | setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) { | ||
831 | dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; | ||
832 | isc_stdtime_t oldresign; | ||
833 | @@ -7972,7 +8071,8 @@ static dns_dbmethods_t zone_methods = { | ||
834 | NULL, | ||
835 | NULL, | ||
836 | NULL, | ||
837 | - hashsize | ||
838 | + hashsize, | ||
839 | + getsize | ||
840 | }; | ||
841 | |||
842 | static dns_dbmethods_t cache_methods = { | ||
843 | @@ -8018,7 +8118,8 @@ static dns_dbmethods_t cache_methods = { | ||
844 | NULL, | ||
845 | NULL, | ||
846 | setcachestats, | ||
847 | - hashsize | ||
848 | + hashsize, | ||
849 | + NULL | ||
850 | }; | ||
851 | |||
852 | isc_result_t | ||
853 | @@ -8310,6 +8411,20 @@ dns_rbtdb_create | ||
854 | rbtdb->current_version->salt_length = 0; | ||
855 | memset(rbtdb->current_version->salt, 0, | ||
856 | sizeof(rbtdb->current_version->salt)); | ||
857 | + result = isc_rwlock_init(&rbtdb->current_version->rwlock, 0, 0); | ||
858 | + if (result != ISC_R_SUCCESS) { | ||
859 | + isc_refcount_destroy(&rbtdb->current_version->references); | ||
860 | + isc_mem_put(mctx, rbtdb->current_version, | ||
861 | + sizeof(*rbtdb->current_version)); | ||
862 | + rbtdb->current_version = NULL; | ||
863 | + isc_refcount_decrement(&rbtdb->references, NULL); | ||
864 | + isc_refcount_destroy(&rbtdb->references); | ||
865 | + free_rbtdb(rbtdb, ISC_FALSE, NULL); | ||
866 | + return (result); | ||
867 | + } | ||
868 | + | ||
869 | + rbtdb->current_version->records = 0; | ||
870 | + rbtdb->current_version->bytes = 0; | ||
871 | rbtdb->future_version = NULL; | ||
872 | ISC_LIST_INIT(rbtdb->open_versions); | ||
873 | /* | ||
874 | diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c | ||
875 | index e29dc84..63e3728 100644 | ||
876 | --- a/lib/dns/rdataslab.c | ||
877 | +++ b/lib/dns/rdataslab.c | ||
878 | @@ -523,6 +523,19 @@ dns_rdataslab_size(unsigned char *slab, unsigned int reservelen) { | ||
879 | return ((unsigned int)(current - slab)); | ||
880 | } | ||
881 | |||
882 | +unsigned int | ||
883 | +dns_rdataslab_count(unsigned char *slab, unsigned int reservelen) { | ||
884 | + unsigned int count; | ||
885 | + unsigned char *current; | ||
886 | + | ||
887 | + REQUIRE(slab != NULL); | ||
888 | + | ||
889 | + current = slab + reservelen; | ||
890 | + count = *current++ * 256; | ||
891 | + count += *current++; | ||
892 | + return (count); | ||
893 | +} | ||
894 | + | ||
895 | /* | ||
896 | * Make the dns_rdata_t 'rdata' refer to the slab item | ||
897 | * beginning at '*current', which is part of a slab of type | ||
898 | diff --git a/lib/dns/result.c b/lib/dns/result.c | ||
899 | index 7be4f57..a621909 100644 | ||
900 | --- a/lib/dns/result.c | ||
901 | +++ b/lib/dns/result.c | ||
902 | @@ -167,11 +167,16 @@ static const char *text[DNS_R_NRESULTS] = { | ||
903 | "covered by negative trust anchor", /*%< 110 DNS_R_NTACOVERED */ | ||
904 | "bad CDS", /*%< 111 DNS_R_BADCSD */ | ||
905 | "bad CDNSKEY", /*%< 112 DNS_R_BADCDNSKEY */ | ||
906 | - "malformed OPT option" /*%< 113 DNS_R_OPTERR */ | ||
907 | + "malformed OPT option", /*%< 113 DNS_R_OPTERR */ | ||
908 | + "malformed DNSTAP data", /*%< 114 DNS_R_BADDNSTAP */ | ||
909 | + | ||
910 | + "TSIG in wrong location", /*%< 115 DNS_R_BADTSIG */ | ||
911 | + "SIG(0) in wrong location", /*%< 116 DNS_R_BADSIG0 */ | ||
912 | + "too many records", /*%< 117 DNS_R_TOOMANYRECORDS */ | ||
913 | }; | ||
914 | |||
915 | static const char *rcode_text[DNS_R_NRCODERESULTS] = { | ||
916 | - "NOERROR", /*%< 0 DNS_R_NOEROR */ | ||
917 | + "NOERROR", /*%< 0 DNS_R_NOERROR */ | ||
918 | "FORMERR", /*%< 1 DNS_R_FORMERR */ | ||
919 | "SERVFAIL", /*%< 2 DNS_R_SERVFAIL */ | ||
920 | "NXDOMAIN", /*%< 3 DNS_R_NXDOMAIN */ | ||
921 | diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c | ||
922 | index abfeeb0..19397e0 100644 | ||
923 | --- a/lib/dns/sdb.c | ||
924 | +++ b/lib/dns/sdb.c | ||
925 | @@ -1298,7 +1298,8 @@ static dns_dbmethods_t sdb_methods = { | ||
926 | findnodeext, | ||
927 | findext, | ||
928 | NULL, /* setcachestats */ | ||
929 | - NULL /* hashsize */ | ||
930 | + NULL, /* hashsize */ | ||
931 | + NULL /* getsize */ | ||
932 | }; | ||
933 | |||
934 | static isc_result_t | ||
935 | diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c | ||
936 | index b1198a4..0e3163d 100644 | ||
937 | --- a/lib/dns/sdlz.c | ||
938 | +++ b/lib/dns/sdlz.c | ||
939 | @@ -1269,7 +1269,8 @@ static dns_dbmethods_t sdlzdb_methods = { | ||
940 | findnodeext, | ||
941 | findext, | ||
942 | NULL, /* setcachestats */ | ||
943 | - NULL /* hashsize */ | ||
944 | + NULL, /* hashsize */ | ||
945 | + NULL /* getsize */ | ||
946 | }; | ||
947 | |||
948 | /* | ||
949 | diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c | ||
950 | index 2a6c1b4..ac566e1 100644 | ||
951 | --- a/lib/dns/xfrin.c | ||
952 | +++ b/lib/dns/xfrin.c | ||
953 | @@ -149,6 +149,9 @@ struct dns_xfrin_ctx { | ||
954 | unsigned int nrecs; /*%< Number of records recvd */ | ||
955 | isc_uint64_t nbytes; /*%< Number of bytes received */ | ||
956 | |||
957 | + unsigned int maxrecords; /*%< The maximum number of | ||
958 | + records set for the zone */ | ||
959 | + | ||
960 | isc_time_t start; /*%< Start time of the transfer */ | ||
961 | isc_time_t end; /*%< End time of the transfer */ | ||
962 | |||
963 | @@ -309,10 +312,18 @@ axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, | ||
964 | static isc_result_t | ||
965 | axfr_apply(dns_xfrin_ctx_t *xfr) { | ||
966 | isc_result_t result; | ||
967 | + isc_uint64_t records; | ||
968 | |||
969 | CHECK(dns_diff_load(&xfr->diff, xfr->axfr.add, xfr->axfr.add_private)); | ||
970 | xfr->difflen = 0; | ||
971 | dns_diff_clear(&xfr->diff); | ||
972 | + if (xfr->maxrecords != 0U) { | ||
973 | + result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL); | ||
974 | + if (result == ISC_R_SUCCESS && records > xfr->maxrecords) { | ||
975 | + result = DNS_R_TOOMANYRECORDS; | ||
976 | + goto failure; | ||
977 | + } | ||
978 | + } | ||
979 | result = ISC_R_SUCCESS; | ||
980 | failure: | ||
981 | return (result); | ||
982 | @@ -396,6 +407,7 @@ ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, | ||
983 | static isc_result_t | ||
984 | ixfr_apply(dns_xfrin_ctx_t *xfr) { | ||
985 | isc_result_t result; | ||
986 | + isc_uint64_t records; | ||
987 | |||
988 | if (xfr->ver == NULL) { | ||
989 | CHECK(dns_db_newversion(xfr->db, &xfr->ver)); | ||
990 | @@ -403,6 +415,13 @@ ixfr_apply(dns_xfrin_ctx_t *xfr) { | ||
991 | CHECK(dns_journal_begin_transaction(xfr->ixfr.journal)); | ||
992 | } | ||
993 | CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver)); | ||
994 | + if (xfr->maxrecords != 0U) { | ||
995 | + result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL); | ||
996 | + if (result == ISC_R_SUCCESS && records > xfr->maxrecords) { | ||
997 | + result = DNS_R_TOOMANYRECORDS; | ||
998 | + goto failure; | ||
999 | + } | ||
1000 | + } | ||
1001 | if (xfr->ixfr.journal != NULL) { | ||
1002 | result = dns_journal_writediff(xfr->ixfr.journal, &xfr->diff); | ||
1003 | if (result != ISC_R_SUCCESS) | ||
1004 | @@ -759,7 +778,7 @@ xfrin_reset(dns_xfrin_ctx_t *xfr) { | ||
1005 | |||
1006 | static void | ||
1007 | xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) { | ||
1008 | - if (result != DNS_R_UPTODATE) { | ||
1009 | + if (result != DNS_R_UPTODATE && result != DNS_R_TOOMANYRECORDS) { | ||
1010 | xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", | ||
1011 | msg, isc_result_totext(result)); | ||
1012 | if (xfr->is_ixfr) | ||
1013 | @@ -852,6 +871,7 @@ xfrin_create(isc_mem_t *mctx, | ||
1014 | xfr->nmsg = 0; | ||
1015 | xfr->nrecs = 0; | ||
1016 | xfr->nbytes = 0; | ||
1017 | + xfr->maxrecords = dns_zone_getmaxrecords(zone); | ||
1018 | isc_time_now(&xfr->start); | ||
1019 | |||
1020 | xfr->tsigkey = NULL; | ||
1021 | diff --git a/lib/dns/zone.c b/lib/dns/zone.c | ||
1022 | index 90e558d..2b0d8e4 100644 | ||
1023 | --- a/lib/dns/zone.c | ||
1024 | +++ b/lib/dns/zone.c | ||
1025 | @@ -253,6 +253,8 @@ struct dns_zone { | ||
1026 | isc_uint32_t maxretry; | ||
1027 | isc_uint32_t minretry; | ||
1028 | |||
1029 | + isc_uint32_t maxrecords; | ||
1030 | + | ||
1031 | isc_sockaddr_t *masters; | ||
1032 | isc_dscp_t *masterdscps; | ||
1033 | dns_name_t **masterkeynames; | ||
1034 | @@ -10088,6 +10090,20 @@ dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) { | ||
1035 | zone->maxretry = val; | ||
1036 | } | ||
1037 | |||
1038 | +isc_uint32_t | ||
1039 | +dns_zone_getmaxrecords(dns_zone_t *zone) { | ||
1040 | + REQUIRE(DNS_ZONE_VALID(zone)); | ||
1041 | + | ||
1042 | + return (zone->maxrecords); | ||
1043 | +} | ||
1044 | + | ||
1045 | +void | ||
1046 | +dns_zone_setmaxrecords(dns_zone_t *zone, isc_uint32_t val) { | ||
1047 | + REQUIRE(DNS_ZONE_VALID(zone)); | ||
1048 | + | ||
1049 | + zone->maxrecords = val; | ||
1050 | +} | ||
1051 | + | ||
1052 | static isc_boolean_t | ||
1053 | notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name, | ||
1054 | isc_sockaddr_t *addr, dns_tsigkey_t *key) | ||
1055 | @@ -14431,7 +14447,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) { | ||
1056 | DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR); | ||
1057 | |||
1058 | TIME_NOW(&now); | ||
1059 | - switch (result) { | ||
1060 | + switch (xfrresult) { | ||
1061 | case ISC_R_SUCCESS: | ||
1062 | DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); | ||
1063 | /*FALLTHROUGH*/ | ||
1064 | @@ -14558,6 +14574,11 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) { | ||
1065 | DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR); | ||
1066 | goto same_master; | ||
1067 | |||
1068 | + case DNS_R_TOOMANYRECORDS: | ||
1069 | + DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime); | ||
1070 | + inc_stats(zone, dns_zonestatscounter_xfrfail); | ||
1071 | + break; | ||
1072 | + | ||
1073 | default: | ||
1074 | next_master: | ||
1075 | /* | ||
1076 | diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c | ||
1077 | index 780ab46..e7ff1cc 100644 | ||
1078 | --- a/lib/isccfg/namedconf.c | ||
1079 | +++ b/lib/isccfg/namedconf.c | ||
1080 | @@ -1679,6 +1679,7 @@ zone_clauses[] = { | ||
1081 | { "masterfile-format", &cfg_type_masterformat, 0 }, | ||
1082 | { "max-ixfr-log-size", &cfg_type_size, CFG_CLAUSEFLAG_OBSOLETE }, | ||
1083 | { "max-journal-size", &cfg_type_sizenodefault, 0 }, | ||
1084 | + { "max-records", &cfg_type_uint32, 0 }, | ||
1085 | { "max-refresh-time", &cfg_type_uint32, 0 }, | ||
1086 | { "max-retry-time", &cfg_type_uint32, 0 }, | ||
1087 | { "max-transfer-idle-in", &cfg_type_uint32, 0 }, | ||
1088 | -- | ||
1089 | 2.7.4 | ||
1090 | |||
diff --git a/meta/recipes-connectivity/bind/bind_9.10.3-P3.bb b/meta/recipes-connectivity/bind/bind_9.10.3-P3.bb index fa45809980..8160625282 100644 --- a/meta/recipes-connectivity/bind/bind_9.10.3-P3.bb +++ b/meta/recipes-connectivity/bind/bind_9.10.3-P3.bb | |||
@@ -28,6 +28,7 @@ SRC_URI = "ftp://ftp.isc.org/isc/bind9/${PV}/${BPN}-${PV}.tar.gz \ | |||
28 | file://CVE-2016-2775.patch \ | 28 | file://CVE-2016-2775.patch \ |
29 | file://CVE-2016-2776.patch \ | 29 | file://CVE-2016-2776.patch \ |
30 | file://CVE-2016-8864.patch \ | 30 | file://CVE-2016-8864.patch \ |
31 | file://CVE-2016-6170.patch \ | ||
31 | " | 32 | " |
32 | 33 | ||
33 | SRC_URI[md5sum] = "bcf7e772b616f7259420a3edc5df350a" | 34 | SRC_URI[md5sum] = "bcf7e772b616f7259420a3edc5df350a" |