diff options
author | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2017-12-04 01:01:44 -0500 |
---|---|---|
committer | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2017-12-14 17:17:23 +0000 |
commit | 37a0e4ddff58c0120cc5cfef104b60d0e180638c (patch) | |
tree | 1628857a2eb33ab517ba93d6a3ca25e55bd3e628 /import-layers/yocto-poky/meta/recipes-connectivity | |
parent | 3c4c45d1e9a2324191a8640b22df1b71f15f3037 (diff) | |
download | talos-openbmc-37a0e4ddff58c0120cc5cfef104b60d0e180638c.tar.gz talos-openbmc-37a0e4ddff58c0120cc5cfef104b60d0e180638c.zip |
Squashed 'import-layers/yocto-poky/' changes from dc8508f6099..67491b0c104
Yocto 2.2.2 (Morty)
Change-Id: Id9a452e28940d9f166957de243d9cb1d8818704e
git-subtree-dir: import-layers/yocto-poky
git-subtree-split: 67491b0c104101bb9f366d697edd23c895be4302
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
Diffstat (limited to 'import-layers/yocto-poky/meta/recipes-connectivity')
17 files changed, 1844 insertions, 13 deletions
diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch b/import-layers/yocto-poky/meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch new file mode 100644 index 000000000..75bc211cb --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch @@ -0,0 +1,1090 @@ +From 1bbcfe2fc84f57b1e4e075fb3bc2a1dd0a3a851f Mon Sep 17 00:00:00 2001 +From: Mark Andrews <marka@isc.org> +Date: Wed, 2 Nov 2016 17:31:27 +1100 +Subject: [PATCH] 4504. [security] Allow the maximum number of records in a + zone to be specified. This provides a control for issues raised in + CVE-2016-6170. [RT #42143] + +(cherry picked from commit 5f8412a4cb5ee14a0e8cddd4107854b40ee3291e) + +Upstream-Status: Backport +[https://source.isc.org/cgi-bin/gitweb.cgi?p=bind9.git;a=commit;h=1bbcfe2fc84f57b1e4e075fb3bc2a1dd0a3a851f] + +CVE: CVE-2016-6170 + +Signed-off-by: Yi Zhao <yi.zhao@windriver.com> +--- + CHANGES | 4 + + bin/named/config.c | 1 + + bin/named/named.conf.docbook | 3 + + bin/named/update.c | 16 +++ + bin/named/zoneconf.c | 7 ++ + bin/tests/system/nsupdate/clean.sh | 1 + + bin/tests/system/nsupdate/ns3/named.conf | 7 ++ + bin/tests/system/nsupdate/ns3/too-big.test.db.in | 10 ++ + bin/tests/system/nsupdate/setup.sh | 2 + + bin/tests/system/nsupdate/tests.sh | 15 +++ + bin/tests/system/xfer/clean.sh | 1 + + bin/tests/system/xfer/ns1/axfr-too-big.db | 10 ++ + bin/tests/system/xfer/ns1/ixfr-too-big.db.in | 13 +++ + bin/tests/system/xfer/ns1/named.conf | 11 ++ + bin/tests/system/xfer/ns6/named.conf | 14 +++ + bin/tests/system/xfer/setup.sh | 2 + + bin/tests/system/xfer/tests.sh | 26 +++++ + doc/arm/Bv9ARM-book.xml | 21 ++++ + doc/arm/notes.xml | 9 ++ + lib/bind9/check.c | 2 + + lib/dns/db.c | 13 +++ + lib/dns/ecdb.c | 3 +- + lib/dns/include/dns/db.h | 20 ++++ + lib/dns/include/dns/rdataslab.h | 13 +++ + lib/dns/include/dns/result.h | 6 +- + lib/dns/include/dns/zone.h | 28 ++++- + lib/dns/rbtdb.c | 127 +++++++++++++++++++++-- + lib/dns/rdataslab.c | 13 +++ + lib/dns/result.c | 9 +- + lib/dns/sdb.c | 3 +- + lib/dns/sdlz.c | 3 +- + lib/dns/xfrin.c | 22 +++- + lib/dns/zone.c | 23 +++- + lib/isccfg/namedconf.c | 1 + + 34 files changed, 444 insertions(+), 15 deletions(-) + create mode 100644 bin/tests/system/nsupdate/ns3/too-big.test.db.in + create mode 100644 bin/tests/system/xfer/ns1/axfr-too-big.db + create mode 100644 bin/tests/system/xfer/ns1/ixfr-too-big.db.in + +diff --git a/CHANGES b/CHANGES +index 41cfce5..97d2e60 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -1,3 +1,7 @@ ++4504. [security] Allow the maximum number of records in a zone to ++ be specified. This provides a control for issues ++ raised in CVE-2016-6170. [RT #42143] ++ + 4489. [security] It was possible to trigger assertions when processing + a response. (CVE-2016-8864) [RT #43465] + +diff --git a/bin/named/config.c b/bin/named/config.c +index f06348c..c24e334 100644 +--- a/bin/named/config.c ++++ b/bin/named/config.c +@@ -209,6 +209,7 @@ options {\n\ + max-transfer-time-out 120;\n\ + max-transfer-idle-in 60;\n\ + max-transfer-idle-out 60;\n\ ++ max-records 0;\n\ + max-retry-time 1209600; /* 2 weeks */\n\ + min-retry-time 500;\n\ + max-refresh-time 2419200; /* 4 weeks */\n\ +diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook +index 4c99a61..c2d173a 100644 +--- a/bin/named/named.conf.docbook ++++ b/bin/named/named.conf.docbook +@@ -338,6 +338,7 @@ options { + }; + + max-journal-size <replaceable>size_no_default</replaceable>; ++ max-records <replaceable>integer</replaceable>; + max-transfer-time-in <replaceable>integer</replaceable>; + max-transfer-time-out <replaceable>integer</replaceable>; + max-transfer-idle-in <replaceable>integer</replaceable>; +@@ -527,6 +528,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable> + }; + + max-journal-size <replaceable>size_no_default</replaceable>; ++ max-records <replaceable>integer</replaceable>; + max-transfer-time-in <replaceable>integer</replaceable>; + max-transfer-time-out <replaceable>integer</replaceable>; + max-transfer-idle-in <replaceable>integer</replaceable>; +@@ -624,6 +626,7 @@ zone <replaceable>string</replaceable> <replaceable>optional_class</replaceable> + }; + + max-journal-size <replaceable>size_no_default</replaceable>; ++ max-records <replaceable>integer</replaceable>; + max-transfer-time-in <replaceable>integer</replaceable>; + max-transfer-time-out <replaceable>integer</replaceable>; + max-transfer-idle-in <replaceable>integer</replaceable>; +diff --git a/bin/named/update.c b/bin/named/update.c +index 83b1a05..cc2a611 100644 +--- a/bin/named/update.c ++++ b/bin/named/update.c +@@ -2455,6 +2455,8 @@ update_action(isc_task_t *task, isc_event_t *event) { + isc_boolean_t had_dnskey; + dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); + dns_ttl_t maxttl = 0; ++ isc_uint32_t maxrecords; ++ isc_uint64_t records; + + INSIST(event->ev_type == DNS_EVENT_UPDATE); + +@@ -3138,6 +3140,20 @@ update_action(isc_task_t *task, isc_event_t *event) { + } + } + ++ maxrecords = dns_zone_getmaxrecords(zone); ++ if (maxrecords != 0U) { ++ result = dns_db_getsize(db, ver, &records, NULL); ++ if (result == ISC_R_SUCCESS && records > maxrecords) { ++ update_log(client, zone, ISC_LOG_ERROR, ++ "records in zone (%" ++ ISC_PRINT_QUADFORMAT ++ "u) exceeds max-records (%u)", ++ records, maxrecords); ++ result = DNS_R_TOOMANYRECORDS; ++ goto failure; ++ } ++ } ++ + journalfile = dns_zone_getjournal(zone); + if (journalfile != NULL) { + update_log(client, zone, LOGLEVEL_DEBUG, +diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c +index 4ee3dfe..14dd8ce 100644 +--- a/bin/named/zoneconf.c ++++ b/bin/named/zoneconf.c +@@ -978,6 +978,13 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, + dns_zone_setmaxttl(raw, maxttl); + } + ++ obj = NULL; ++ result = ns_config_get(maps, "max-records", &obj); ++ INSIST(result == ISC_R_SUCCESS && obj != NULL); ++ dns_zone_setmaxrecords(mayberaw, cfg_obj_asuint32(obj)); ++ if (zone != mayberaw) ++ dns_zone_setmaxrecords(zone, 0); ++ + if (raw != NULL && filename != NULL) { + #define SIGNED ".signed" + size_t signedlen = strlen(filename) + sizeof(SIGNED); +diff --git a/bin/tests/system/nsupdate/clean.sh b/bin/tests/system/nsupdate/clean.sh +index aaefc02..ea25545 100644 +--- a/bin/tests/system/nsupdate/clean.sh ++++ b/bin/tests/system/nsupdate/clean.sh +@@ -32,6 +32,7 @@ rm -f ns3/example.db.jnl ns3/example.db + rm -f ns3/nsec3param.test.db.signed.jnl ns3/nsec3param.test.db ns3/nsec3param.test.db.signed ns3/dsset-nsec3param.test. + rm -f ns3/dnskey.test.db.signed.jnl ns3/dnskey.test.db ns3/dnskey.test.db.signed ns3/dsset-dnskey.test. + rm -f ns3/K* ++rm -f ns3/too-big.test.db + rm -f dig.out.* + rm -f jp.out.ns3.* + rm -f Kxxx.* +diff --git a/bin/tests/system/nsupdate/ns3/named.conf b/bin/tests/system/nsupdate/ns3/named.conf +index 2abd522..68ff27a 100644 +--- a/bin/tests/system/nsupdate/ns3/named.conf ++++ b/bin/tests/system/nsupdate/ns3/named.conf +@@ -60,3 +60,10 @@ zone "dnskey.test" { + allow-update { any; }; + file "dnskey.test.db.signed"; + }; ++ ++zone "too-big.test" { ++ type master; ++ allow-update { any; }; ++ max-records 3; ++ file "too-big.test.db"; ++}; +diff --git a/bin/tests/system/nsupdate/ns3/too-big.test.db.in b/bin/tests/system/nsupdate/ns3/too-big.test.db.in +new file mode 100644 +index 0000000..7ff1e4a +--- /dev/null ++++ b/bin/tests/system/nsupdate/ns3/too-big.test.db.in +@@ -0,0 +1,10 @@ ++; Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ ++$TTL 10 ++too-big.test. IN SOA too-big.test. hostmaster.too-big.test. 1 3600 900 2419200 3600 ++too-big.test. IN NS too-big.test. ++too-big.test. IN A 10.53.0.3 +diff --git a/bin/tests/system/nsupdate/setup.sh b/bin/tests/system/nsupdate/setup.sh +index 828255e..43c4094 100644 +--- a/bin/tests/system/nsupdate/setup.sh ++++ b/bin/tests/system/nsupdate/setup.sh +@@ -27,12 +27,14 @@ test -r $RANDFILE || $GENRANDOM 400 $RANDFILE + rm -f ns1/*.jnl ns1/example.db ns2/*.jnl ns2/example.bk + rm -f ns2/update.bk ns2/update.alt.bk + rm -f ns3/example.db.jnl ++rm -f ns3/too-big.test.db.jnl + + cp -f ns1/example1.db ns1/example.db + sed 's/example.nil/other.nil/g' ns1/example1.db > ns1/other.db + sed 's/example.nil/unixtime.nil/g' ns1/example1.db > ns1/unixtime.db + sed 's/example.nil/keytests.nil/g' ns1/example1.db > ns1/keytests.db + cp -f ns3/example.db.in ns3/example.db ++cp -f ns3/too-big.test.db.in ns3/too-big.test.db + + # update_test.pl has its own zone file because it + # requires a specific NS record set. +diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh +index 78d501e..0a6bbd3 100755 +--- a/bin/tests/system/nsupdate/tests.sh ++++ b/bin/tests/system/nsupdate/tests.sh +@@ -581,5 +581,20 @@ if [ $ret -ne 0 ]; then + status=1 + fi + ++n=`expr $n + 1` ++echo "I:check that adding too many records is blocked ($n)" ++ret=0 ++$NSUPDATE -v << EOF > nsupdate.out-$n 2>&1 && ret=1 ++server 10.53.0.3 5300 ++zone too-big.test. ++update add r1.too-big.test 3600 IN TXT r1.too-big.test ++send ++EOF ++grep "update failed: SERVFAIL" nsupdate.out-$n > /dev/null || ret=1 ++DIG +tcp @10.53.0.3 -p 5300 r1.too-big.test TXT > dig.out.ns3.test$n ++grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1 ++grep "records in zone (4) exceeds max-records (3)" ns3/named.run > /dev/null || ret=1 ++[ $ret = 0 ] || { echo I:failed; status=1; } ++ + echo "I:exit status: $status" + exit $status +diff --git a/bin/tests/system/xfer/clean.sh b/bin/tests/system/xfer/clean.sh +index 48aa159..da62a33 100644 +--- a/bin/tests/system/xfer/clean.sh ++++ b/bin/tests/system/xfer/clean.sh +@@ -36,3 +36,4 @@ rm -f ns7/*.db ns7/*.bk ns7/*.jnl + rm -f */named.memstats + rm -f */named.run + rm -f */ans.run ++rm -f ns1/ixfr-too-big.db ns1/ixfr-too-big.db.jnl +diff --git a/bin/tests/system/xfer/ns1/axfr-too-big.db b/bin/tests/system/xfer/ns1/axfr-too-big.db +new file mode 100644 +index 0000000..d43760d +--- /dev/null ++++ b/bin/tests/system/xfer/ns1/axfr-too-big.db +@@ -0,0 +1,10 @@ ++; Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ ++$TTL 3600 ++@ IN SOA . . 0 0 0 0 0 ++@ IN NS . ++$GENERATE 1-29 host$ A 1.2.3.$ +diff --git a/bin/tests/system/xfer/ns1/ixfr-too-big.db.in b/bin/tests/system/xfer/ns1/ixfr-too-big.db.in +new file mode 100644 +index 0000000..318bb77 +--- /dev/null ++++ b/bin/tests/system/xfer/ns1/ixfr-too-big.db.in +@@ -0,0 +1,13 @@ ++; Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") ++; ++; This Source Code Form is subject to the terms of the Mozilla Public ++; License, v. 2.0. If a copy of the MPL was not distributed with this ++; file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ ++$TTL 3600 ++@ IN SOA . . 0 0 0 0 0 ++@ IN NS ns1 ++@ IN NS ns6 ++ns1 IN A 10.53.0.1 ++ns6 IN A 10.53.0.6 ++$GENERATE 1-25 host$ A 1.2.3.$ +diff --git a/bin/tests/system/xfer/ns1/named.conf b/bin/tests/system/xfer/ns1/named.conf +index 07dad85..1d29292 100644 +--- a/bin/tests/system/xfer/ns1/named.conf ++++ b/bin/tests/system/xfer/ns1/named.conf +@@ -44,3 +44,14 @@ zone "slave" { + type master; + file "slave.db"; + }; ++ ++zone "axfr-too-big" { ++ type master; ++ file "axfr-too-big.db"; ++}; ++ ++zone "ixfr-too-big" { ++ type master; ++ allow-update { any; }; ++ file "ixfr-too-big.db"; ++}; +diff --git a/bin/tests/system/xfer/ns6/named.conf b/bin/tests/system/xfer/ns6/named.conf +index c9421b1..a12a92c 100644 +--- a/bin/tests/system/xfer/ns6/named.conf ++++ b/bin/tests/system/xfer/ns6/named.conf +@@ -52,3 +52,17 @@ zone "slave" { + masters { 10.53.0.1; }; + file "slave.bk"; + }; ++ ++zone "axfr-too-big" { ++ type slave; ++ max-records 30; ++ masters { 10.53.0.1; }; ++ file "axfr-too-big.bk"; ++}; ++ ++zone "ixfr-too-big" { ++ type slave; ++ max-records 30; ++ masters { 10.53.0.1; }; ++ file "ixfr-too-big.bk"; ++}; +diff --git a/bin/tests/system/xfer/setup.sh b/bin/tests/system/xfer/setup.sh +index 56ca901..c55abf8 100644 +--- a/bin/tests/system/xfer/setup.sh ++++ b/bin/tests/system/xfer/setup.sh +@@ -33,3 +33,5 @@ cp -f ns4/named.conf.base ns4/named.conf + + cp ns2/slave.db.in ns2/slave.db + touch -t 200101010000 ns2/slave.db ++ ++cp -f ns1/ixfr-too-big.db.in ns1/ixfr-too-big.db +diff --git a/bin/tests/system/xfer/tests.sh b/bin/tests/system/xfer/tests.sh +index 67b2a1a..fe33f0a 100644 +--- a/bin/tests/system/xfer/tests.sh ++++ b/bin/tests/system/xfer/tests.sh +@@ -368,5 +368,31 @@ $DIGCMD nil. TXT | grep 'incorrect key AXFR' >/dev/null && { + status=1 + } + ++n=`expr $n + 1` ++echo "I:test that a zone with too many records is rejected (AXFR) ($n)" ++tmp=0 ++grep "'axfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null || tmp=1 ++if test $tmp != 0 ; then echo "I:failed"; fi ++status=`expr $status + $tmp` ++ ++n=`expr $n + 1` ++echo "I:test that a zone with too many records is rejected (IXFR) ($n)" ++tmp=0 ++grep "'ixfr-too-big./IN.*: too many records" ns6/named.run >/dev/null && tmp=1 ++$NSUPDATE << EOF ++zone ixfr-too-big ++server 10.53.0.1 5300 ++update add the-31st-record.ixfr-too-big 0 TXT this is it ++send ++EOF ++for i in 1 2 3 4 5 6 7 8 ++do ++ grep "'ixfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null && break ++ sleep 1 ++done ++grep "'ixfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null || tmp=1 ++if test $tmp != 0 ; then echo "I:failed"; fi ++status=`expr $status + $tmp` ++ + echo "I:exit status: $status" + exit $status +diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml +index 848b582..0369505 100644 +--- a/doc/arm/Bv9ARM-book.xml ++++ b/doc/arm/Bv9ARM-book.xml +@@ -4858,6 +4858,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] + <optional> use-queryport-pool <replaceable>yes_or_no</replaceable>; </optional> + <optional> queryport-pool-ports <replaceable>number</replaceable>; </optional> + <optional> queryport-pool-updateinterval <replaceable>number</replaceable>; </optional> ++ <optional> max-records <replaceable>number</replaceable>; </optional> + <optional> max-transfer-time-in <replaceable>number</replaceable>; </optional> + <optional> max-transfer-time-out <replaceable>number</replaceable>; </optional> + <optional> max-transfer-idle-in <replaceable>number</replaceable>; </optional> +@@ -8164,6 +8165,16 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; + </varlistentry> + + <varlistentry> ++ <term><command>max-records</command></term> ++ <listitem> ++ <para> ++ The maximum number of records permitted in a zone. ++ The default is zero which means unlimited. ++ </para> ++ </listitem> ++ </varlistentry> ++ ++ <varlistentry> + <term><command>host-statistics-max</command></term> + <listitem> + <para> +@@ -12056,6 +12067,16 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea + </varlistentry> + + <varlistentry> ++ <term><command>max-records</command></term> ++ <listitem> ++ <para> ++ See the description of ++ <command>max-records</command> in <xref linkend="server_resource_limits"/>. ++ </para> ++ </listitem> ++ </varlistentry> ++ ++ <varlistentry> + <term><command>max-transfer-time-in</command></term> + <listitem> + <para> +diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml +index 095eb5b..36495e7 100644 +--- a/doc/arm/notes.xml ++++ b/doc/arm/notes.xml +@@ -52,6 +52,15 @@ + <itemizedlist> + <listitem> + <para> ++ Added the ability to specify the maximum number of records ++ permitted in a zone (max-records #;). This provides a mechanism ++ to block overly large zone transfers, which is a potential risk ++ with slave zones from other parties, as described in CVE-2016-6170. ++ [RT #42143] ++ </para> ++ </listitem> ++ <listitem> ++ <para> + Duplicate EDNS COOKIE options in a response could trigger + an assertion failure. This flaw is disclosed in CVE-2016-2088. + [RT #41809] +diff --git a/lib/bind9/check.c b/lib/bind9/check.c +index b8c05dd..edb7534 100644 +--- a/lib/bind9/check.c ++++ b/lib/bind9/check.c +@@ -1510,6 +1510,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, + REDIRECTZONE }, + { "masters", SLAVEZONE | STUBZONE | REDIRECTZONE }, + { "max-ixfr-log-size", MASTERZONE | SLAVEZONE | STREDIRECTZONE }, ++ { "max-records", MASTERZONE | SLAVEZONE | STUBZONE | STREDIRECTZONE | ++ STATICSTUBZONE | REDIRECTZONE }, + { "max-refresh-time", SLAVEZONE | STUBZONE | STREDIRECTZONE }, + { "max-retry-time", SLAVEZONE | STUBZONE | STREDIRECTZONE }, + { "max-transfer-idle-in", SLAVEZONE | STUBZONE | STREDIRECTZONE }, +diff --git a/lib/dns/db.c b/lib/dns/db.c +index 7e4f357..ced94a5 100644 +--- a/lib/dns/db.c ++++ b/lib/dns/db.c +@@ -999,6 +999,19 @@ dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, + } + + isc_result_t ++dns_db_getsize(dns_db_t *db, dns_dbversion_t *version, isc_uint64_t *records, ++ isc_uint64_t *bytes) ++{ ++ REQUIRE(DNS_DB_VALID(db)); ++ REQUIRE(dns_db_iszone(db) == ISC_TRUE); ++ ++ if (db->methods->getsize != NULL) ++ return ((db->methods->getsize)(db, version, records, bytes)); ++ ++ return (ISC_R_NOTFOUND); ++} ++ ++isc_result_t + dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, + isc_stdtime_t resign) + { +diff --git a/lib/dns/ecdb.c b/lib/dns/ecdb.c +index 553a339..b5d04d2 100644 +--- a/lib/dns/ecdb.c ++++ b/lib/dns/ecdb.c +@@ -587,7 +587,8 @@ static dns_dbmethods_t ecdb_methods = { + NULL, /* findnodeext */ + NULL, /* findext */ + NULL, /* setcachestats */ +- NULL /* hashsize */ ++ NULL, /* hashsize */ ++ NULL /* getsize */ + }; + + static isc_result_t +diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h +index a4a4482..aff42d6 100644 +--- a/lib/dns/include/dns/db.h ++++ b/lib/dns/include/dns/db.h +@@ -195,6 +195,8 @@ typedef struct dns_dbmethods { + dns_rdataset_t *sigrdataset); + isc_result_t (*setcachestats)(dns_db_t *db, isc_stats_t *stats); + unsigned int (*hashsize)(dns_db_t *db); ++ isc_result_t (*getsize)(dns_db_t *db, dns_dbversion_t *version, ++ isc_uint64_t *records, isc_uint64_t *bytes); + } dns_dbmethods_t; + + typedef isc_result_t +@@ -1485,6 +1487,24 @@ dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, + */ + + isc_result_t ++dns_db_getsize(dns_db_t *db, dns_dbversion_t *version, isc_uint64_t *records, ++ isc_uint64_t *bytes); ++/*%< ++ * Get the number of records in the given version of the database as well ++ * as the number bytes used to store those records. ++ * ++ * Requires: ++ * \li 'db' is a valid zone database. ++ * \li 'version' is NULL or a valid version. ++ * \li 'records' is NULL or a pointer to return the record count in. ++ * \li 'bytes' is NULL or a pointer to return the byte count in. ++ * ++ * Returns: ++ * \li #ISC_R_SUCCESS ++ * \li #ISC_R_NOTIMPLEMENTED ++ */ ++ ++isc_result_t + dns_db_findnsec3node(dns_db_t *db, dns_name_t *name, + isc_boolean_t create, dns_dbnode_t **nodep); + /*%< +diff --git a/lib/dns/include/dns/rdataslab.h b/lib/dns/include/dns/rdataslab.h +index 3ac44b8..2e1e759 100644 +--- a/lib/dns/include/dns/rdataslab.h ++++ b/lib/dns/include/dns/rdataslab.h +@@ -104,6 +104,7 @@ dns_rdataslab_tordataset(unsigned char *slab, unsigned int reservelen, + * Ensures: + *\li 'rdataset' is associated and points to a valid rdataest. + */ ++ + unsigned int + dns_rdataslab_size(unsigned char *slab, unsigned int reservelen); + /*%< +@@ -116,6 +117,18 @@ dns_rdataslab_size(unsigned char *slab, unsigned int reservelen); + *\li The number of bytes in the slab, including the reservelen. + */ + ++unsigned int ++dns_rdataslab_count(unsigned char *slab, unsigned int reservelen); ++/*%< ++ * Return the number of records in the rdataslab ++ * ++ * Requires: ++ *\li 'slab' points to a slab. ++ * ++ * Returns: ++ *\li The number of records in the slab. ++ */ ++ + isc_result_t + dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab, + unsigned int reservelen, isc_mem_t *mctx, +diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h +index 7d11c2b..93d1fd5 100644 +--- a/lib/dns/include/dns/result.h ++++ b/lib/dns/include/dns/result.h +@@ -157,8 +157,12 @@ + #define DNS_R_BADCDS (ISC_RESULTCLASS_DNS + 111) + #define DNS_R_BADCDNSKEY (ISC_RESULTCLASS_DNS + 112) + #define DNS_R_OPTERR (ISC_RESULTCLASS_DNS + 113) ++#define DNS_R_BADDNSTAP (ISC_RESULTCLASS_DNS + 114) ++#define DNS_R_BADTSIG (ISC_RESULTCLASS_DNS + 115) ++#define DNS_R_BADSIG0 (ISC_RESULTCLASS_DNS + 116) ++#define DNS_R_TOOMANYRECORDS (ISC_RESULTCLASS_DNS + 117) + +-#define DNS_R_NRESULTS 114 /*%< Number of results */ ++#define DNS_R_NRESULTS 118 /*%< Number of results */ + + /* + * DNS wire format rcodes. +diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h +index a9367f1..227540b 100644 +--- a/lib/dns/include/dns/zone.h ++++ b/lib/dns/include/dns/zone.h +@@ -296,6 +296,32 @@ dns_zone_getfile(dns_zone_t *zone); + */ + + void ++dns_zone_setmaxrecords(dns_zone_t *zone, isc_uint32_t records); ++/*%< ++ * Sets the maximim number of records permitted in a zone. ++ * 0 implies unlimited. ++ * ++ * Requires: ++ *\li 'zone' to be valid initialised zone. ++ * ++ * Returns: ++ *\li void ++ */ ++ ++isc_uint32_t ++dns_zone_getmaxrecords(dns_zone_t *zone); ++/*%< ++ * Gets the maximim number of records permitted in a zone. ++ * 0 implies unlimited. ++ * ++ * Requires: ++ *\li 'zone' to be valid initialised zone. ++ * ++ * Returns: ++ *\li isc_uint32_t maxrecords. ++ */ ++ ++void + dns_zone_setmaxttl(dns_zone_t *zone, isc_uint32_t maxttl); + /*%< + * Sets the max ttl of the zone. +@@ -316,7 +342,7 @@ dns_zone_getmaxttl(dns_zone_t *zone); + *\li 'zone' to be valid initialised zone. + * + * Returns: +- *\li isc_uint32_t maxttl. ++ *\li dns_ttl_t maxttl. + */ + + isc_result_t +diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c +index 62becfc..72d722f 100644 +--- a/lib/dns/rbtdb.c ++++ b/lib/dns/rbtdb.c +@@ -209,6 +209,7 @@ typedef isc_uint64_t rbtdb_serial_t; + #define free_rbtdb_callback free_rbtdb_callback64 + #define free_rdataset free_rdataset64 + #define getnsec3parameters getnsec3parameters64 ++#define getsize getsize64 + #define getoriginnode getoriginnode64 + #define getrrsetstats getrrsetstats64 + #define getsigningtime getsigningtime64 +@@ -589,6 +590,13 @@ typedef struct rbtdb_version { + isc_uint16_t iterations; + isc_uint8_t salt_length; + unsigned char salt[DNS_NSEC3_SALTSIZE]; ++ ++ /* ++ * records and bytes are covered by rwlock. ++ */ ++ isc_rwlock_t rwlock; ++ isc_uint64_t records; ++ isc_uint64_t bytes; + } rbtdb_version_t; + + typedef ISC_LIST(rbtdb_version_t) rbtdb_versionlist_t; +@@ -1130,6 +1138,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) { + INSIST(refs == 0); + UNLINK(rbtdb->open_versions, rbtdb->current_version, link); + isc_refcount_destroy(&rbtdb->current_version->references); ++ isc_rwlock_destroy(&rbtdb->current_version->rwlock); + isc_mem_put(rbtdb->common.mctx, rbtdb->current_version, + sizeof(rbtdb_version_t)); + } +@@ -1383,6 +1392,7 @@ allocate_version(isc_mem_t *mctx, rbtdb_serial_t serial, + + static isc_result_t + newversion(dns_db_t *db, dns_dbversion_t **versionp) { ++ isc_result_t result; + dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; + rbtdb_version_t *version; + +@@ -1415,13 +1425,28 @@ newversion(dns_db_t *db, dns_dbversion_t **versionp) { + version->salt_length = 0; + memset(version->salt, 0, sizeof(version->salt)); + } +- rbtdb->next_serial++; +- rbtdb->future_version = version; +- } ++ result = isc_rwlock_init(&version->rwlock, 0, 0); ++ if (result != ISC_R_SUCCESS) { ++ isc_refcount_destroy(&version->references); ++ isc_mem_put(rbtdb->common.mctx, version, ++ sizeof(*version)); ++ version = NULL; ++ } else { ++ RWLOCK(&rbtdb->current_version->rwlock, ++ isc_rwlocktype_read); ++ version->records = rbtdb->current_version->records; ++ version->bytes = rbtdb->current_version->bytes; ++ RWUNLOCK(&rbtdb->current_version->rwlock, ++ isc_rwlocktype_read); ++ rbtdb->next_serial++; ++ rbtdb->future_version = version; ++ } ++ } else ++ result = ISC_R_NOMEMORY; + RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write); + + if (version == NULL) +- return (ISC_R_NOMEMORY); ++ return (result); + + *versionp = version; + +@@ -2681,6 +2706,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { + + if (cleanup_version != NULL) { + INSIST(EMPTY(cleanup_version->changed_list)); ++ isc_rwlock_destroy(&cleanup_version->rwlock); + isc_mem_put(rbtdb->common.mctx, cleanup_version, + sizeof(*cleanup_version)); + } +@@ -6254,6 +6280,26 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, + else + rbtnode->data = newheader; + newheader->next = topheader->next; ++ if (rbtversion != NULL) ++ RWLOCK(&rbtversion->rwlock, isc_rwlocktype_write); ++ if (rbtversion != NULL && !header_nx) { ++ rbtversion->records -= ++ dns_rdataslab_count((unsigned char *)header, ++ sizeof(*header)); ++ rbtversion->bytes -= ++ dns_rdataslab_size((unsigned char *)header, ++ sizeof(*header)); ++ } ++ if (rbtversion != NULL && !newheader_nx) { ++ rbtversion->records += ++ dns_rdataslab_count((unsigned char *)newheader, ++ sizeof(*newheader)); ++ rbtversion->bytes += ++ dns_rdataslab_size((unsigned char *)newheader, ++ sizeof(*newheader)); ++ } ++ if (rbtversion != NULL) ++ RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_write); + if (loading) { + /* + * There are no other references to 'header' when +@@ -6355,6 +6401,16 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, + newheader->down = NULL; + rbtnode->data = newheader; + } ++ if (rbtversion != NULL && !newheader_nx) { ++ RWLOCK(&rbtversion->rwlock, isc_rwlocktype_write); ++ rbtversion->records += ++ dns_rdataslab_count((unsigned char *)newheader, ++ sizeof(*newheader)); ++ rbtversion->bytes += ++ dns_rdataslab_size((unsigned char *)newheader, ++ sizeof(*newheader)); ++ RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_write); ++ } + idx = newheader->node->locknum; + if (IS_CACHE(rbtdb)) { + ISC_LIST_PREPEND(rbtdb->rdatasets[idx], +@@ -6811,6 +6867,12 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + */ + newheader->additional_auth = NULL; + newheader->additional_glue = NULL; ++ rbtversion->records += ++ dns_rdataslab_count((unsigned char *)newheader, ++ sizeof(*newheader)); ++ rbtversion->bytes += ++ dns_rdataslab_size((unsigned char *)newheader, ++ sizeof(*newheader)); + } else if (result == DNS_R_NXRRSET) { + /* + * This subtraction would remove all of the rdata; +@@ -6846,6 +6908,12 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, + * topheader. + */ + INSIST(rbtversion->serial >= topheader->serial); ++ rbtversion->records -= ++ dns_rdataslab_count((unsigned char *)header, ++ sizeof(*header)); ++ rbtversion->bytes -= ++ dns_rdataslab_size((unsigned char *)header, ++ sizeof(*header)); + if (topheader_prev != NULL) + topheader_prev->next = newheader; + else +@@ -7172,6 +7240,7 @@ rbt_datafixer(dns_rbtnode_t *rbtnode, void *base, size_t filesize, + unsigned char *limit = ((unsigned char *) base) + filesize; + unsigned char *p; + size_t size; ++ unsigned int count; + + REQUIRE(rbtnode != NULL); + +@@ -7179,6 +7248,9 @@ rbt_datafixer(dns_rbtnode_t *rbtnode, void *base, size_t filesize, + p = (unsigned char *) header; + + size = dns_rdataslab_size(p, sizeof(*header)); ++ count = dns_rdataslab_count(p, sizeof(*header));; ++ rbtdb->current_version->records += count; ++ rbtdb->current_version->bytes += size; + isc_crc64_update(crc, p, size); + #ifdef DEBUG + hexdump("hashing header", p, sizeof(rdatasetheader_t)); +@@ -7777,6 +7849,33 @@ getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, dns_hash_t *hash, + } + + static isc_result_t ++getsize(dns_db_t *db, dns_dbversion_t *version, isc_uint64_t *records, ++ isc_uint64_t *bytes) ++{ ++ dns_rbtdb_t *rbtdb; ++ isc_result_t result = ISC_R_SUCCESS; ++ rbtdb_version_t *rbtversion = version; ++ ++ rbtdb = (dns_rbtdb_t *)db; ++ ++ REQUIRE(VALID_RBTDB(rbtdb)); ++ INSIST(rbtversion == NULL || rbtversion->rbtdb == rbtdb); ++ ++ if (rbtversion == NULL) ++ rbtversion = rbtdb->current_version; ++ ++ RWLOCK(&rbtversion->rwlock, isc_rwlocktype_read); ++ if (records != NULL) ++ *records = rbtversion->records; ++ ++ if (bytes != NULL) ++ *bytes = rbtversion->bytes; ++ RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_read); ++ ++ return (result); ++} ++ ++static isc_result_t + setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) { + dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; + isc_stdtime_t oldresign; +@@ -7972,7 +8071,8 @@ static dns_dbmethods_t zone_methods = { + NULL, + NULL, + NULL, +- hashsize ++ hashsize, ++ getsize + }; + + static dns_dbmethods_t cache_methods = { +@@ -8018,7 +8118,8 @@ static dns_dbmethods_t cache_methods = { + NULL, + NULL, + setcachestats, +- hashsize ++ hashsize, ++ NULL + }; + + isc_result_t +@@ -8310,6 +8411,20 @@ dns_rbtdb_create + rbtdb->current_version->salt_length = 0; + memset(rbtdb->current_version->salt, 0, + sizeof(rbtdb->current_version->salt)); ++ result = isc_rwlock_init(&rbtdb->current_version->rwlock, 0, 0); ++ if (result != ISC_R_SUCCESS) { ++ isc_refcount_destroy(&rbtdb->current_version->references); ++ isc_mem_put(mctx, rbtdb->current_version, ++ sizeof(*rbtdb->current_version)); ++ rbtdb->current_version = NULL; ++ isc_refcount_decrement(&rbtdb->references, NULL); ++ isc_refcount_destroy(&rbtdb->references); ++ free_rbtdb(rbtdb, ISC_FALSE, NULL); ++ return (result); ++ } ++ ++ rbtdb->current_version->records = 0; ++ rbtdb->current_version->bytes = 0; + rbtdb->future_version = NULL; + ISC_LIST_INIT(rbtdb->open_versions); + /* +diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c +index e29dc84..63e3728 100644 +--- a/lib/dns/rdataslab.c ++++ b/lib/dns/rdataslab.c +@@ -523,6 +523,19 @@ dns_rdataslab_size(unsigned char *slab, unsigned int reservelen) { + return ((unsigned int)(current - slab)); + } + ++unsigned int ++dns_rdataslab_count(unsigned char *slab, unsigned int reservelen) { ++ unsigned int count; ++ unsigned char *current; ++ ++ REQUIRE(slab != NULL); ++ ++ current = slab + reservelen; ++ count = *current++ * 256; ++ count += *current++; ++ return (count); ++} ++ + /* + * Make the dns_rdata_t 'rdata' refer to the slab item + * beginning at '*current', which is part of a slab of type +diff --git a/lib/dns/result.c b/lib/dns/result.c +index 7be4f57..a621909 100644 +--- a/lib/dns/result.c ++++ b/lib/dns/result.c +@@ -167,11 +167,16 @@ static const char *text[DNS_R_NRESULTS] = { + "covered by negative trust anchor", /*%< 110 DNS_R_NTACOVERED */ + "bad CDS", /*%< 111 DNS_R_BADCSD */ + "bad CDNSKEY", /*%< 112 DNS_R_BADCDNSKEY */ +- "malformed OPT option" /*%< 113 DNS_R_OPTERR */ ++ "malformed OPT option", /*%< 113 DNS_R_OPTERR */ ++ "malformed DNSTAP data", /*%< 114 DNS_R_BADDNSTAP */ ++ ++ "TSIG in wrong location", /*%< 115 DNS_R_BADTSIG */ ++ "SIG(0) in wrong location", /*%< 116 DNS_R_BADSIG0 */ ++ "too many records", /*%< 117 DNS_R_TOOMANYRECORDS */ + }; + + static const char *rcode_text[DNS_R_NRCODERESULTS] = { +- "NOERROR", /*%< 0 DNS_R_NOEROR */ ++ "NOERROR", /*%< 0 DNS_R_NOERROR */ + "FORMERR", /*%< 1 DNS_R_FORMERR */ + "SERVFAIL", /*%< 2 DNS_R_SERVFAIL */ + "NXDOMAIN", /*%< 3 DNS_R_NXDOMAIN */ +diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c +index abfeeb0..19397e0 100644 +--- a/lib/dns/sdb.c ++++ b/lib/dns/sdb.c +@@ -1298,7 +1298,8 @@ static dns_dbmethods_t sdb_methods = { + findnodeext, + findext, + NULL, /* setcachestats */ +- NULL /* hashsize */ ++ NULL, /* hashsize */ ++ NULL /* getsize */ + }; + + static isc_result_t +diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c +index b1198a4..0e3163d 100644 +--- a/lib/dns/sdlz.c ++++ b/lib/dns/sdlz.c +@@ -1269,7 +1269,8 @@ static dns_dbmethods_t sdlzdb_methods = { + findnodeext, + findext, + NULL, /* setcachestats */ +- NULL /* hashsize */ ++ NULL, /* hashsize */ ++ NULL /* getsize */ + }; + + /* +diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c +index 2a6c1b4..ac566e1 100644 +--- a/lib/dns/xfrin.c ++++ b/lib/dns/xfrin.c +@@ -149,6 +149,9 @@ struct dns_xfrin_ctx { + unsigned int nrecs; /*%< Number of records recvd */ + isc_uint64_t nbytes; /*%< Number of bytes received */ + ++ unsigned int maxrecords; /*%< The maximum number of ++ records set for the zone */ ++ + isc_time_t start; /*%< Start time of the transfer */ + isc_time_t end; /*%< End time of the transfer */ + +@@ -309,10 +312,18 @@ axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, + static isc_result_t + axfr_apply(dns_xfrin_ctx_t *xfr) { + isc_result_t result; ++ isc_uint64_t records; + + CHECK(dns_diff_load(&xfr->diff, xfr->axfr.add, xfr->axfr.add_private)); + xfr->difflen = 0; + dns_diff_clear(&xfr->diff); ++ if (xfr->maxrecords != 0U) { ++ result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL); ++ if (result == ISC_R_SUCCESS && records > xfr->maxrecords) { ++ result = DNS_R_TOOMANYRECORDS; ++ goto failure; ++ } ++ } + result = ISC_R_SUCCESS; + failure: + return (result); +@@ -396,6 +407,7 @@ ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, + static isc_result_t + ixfr_apply(dns_xfrin_ctx_t *xfr) { + isc_result_t result; ++ isc_uint64_t records; + + if (xfr->ver == NULL) { + CHECK(dns_db_newversion(xfr->db, &xfr->ver)); +@@ -403,6 +415,13 @@ ixfr_apply(dns_xfrin_ctx_t *xfr) { + CHECK(dns_journal_begin_transaction(xfr->ixfr.journal)); + } + CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver)); ++ if (xfr->maxrecords != 0U) { ++ result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL); ++ if (result == ISC_R_SUCCESS && records > xfr->maxrecords) { ++ result = DNS_R_TOOMANYRECORDS; ++ goto failure; ++ } ++ } + if (xfr->ixfr.journal != NULL) { + result = dns_journal_writediff(xfr->ixfr.journal, &xfr->diff); + if (result != ISC_R_SUCCESS) +@@ -759,7 +778,7 @@ xfrin_reset(dns_xfrin_ctx_t *xfr) { + + static void + xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) { +- if (result != DNS_R_UPTODATE) { ++ if (result != DNS_R_UPTODATE && result != DNS_R_TOOMANYRECORDS) { + xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", + msg, isc_result_totext(result)); + if (xfr->is_ixfr) +@@ -852,6 +871,7 @@ xfrin_create(isc_mem_t *mctx, + xfr->nmsg = 0; + xfr->nrecs = 0; + xfr->nbytes = 0; ++ xfr->maxrecords = dns_zone_getmaxrecords(zone); + isc_time_now(&xfr->start); + + xfr->tsigkey = NULL; +diff --git a/lib/dns/zone.c b/lib/dns/zone.c +index 90e558d..2b0d8e4 100644 +--- a/lib/dns/zone.c ++++ b/lib/dns/zone.c +@@ -253,6 +253,8 @@ struct dns_zone { + isc_uint32_t maxretry; + isc_uint32_t minretry; + ++ isc_uint32_t maxrecords; ++ + isc_sockaddr_t *masters; + isc_dscp_t *masterdscps; + dns_name_t **masterkeynames; +@@ -10088,6 +10090,20 @@ dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) { + zone->maxretry = val; + } + ++isc_uint32_t ++dns_zone_getmaxrecords(dns_zone_t *zone) { ++ REQUIRE(DNS_ZONE_VALID(zone)); ++ ++ return (zone->maxrecords); ++} ++ ++void ++dns_zone_setmaxrecords(dns_zone_t *zone, isc_uint32_t val) { ++ REQUIRE(DNS_ZONE_VALID(zone)); ++ ++ zone->maxrecords = val; ++} ++ + static isc_boolean_t + notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name, + isc_sockaddr_t *addr, dns_tsigkey_t *key) +@@ -14431,7 +14447,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) { + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR); + + TIME_NOW(&now); +- switch (result) { ++ switch (xfrresult) { + case ISC_R_SUCCESS: + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); + /*FALLTHROUGH*/ +@@ -14558,6 +14574,11 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) { + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR); + goto same_master; + ++ case DNS_R_TOOMANYRECORDS: ++ DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime); ++ inc_stats(zone, dns_zonestatscounter_xfrfail); ++ break; ++ + default: + next_master: + /* +diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c +index 780ab46..e7ff1cc 100644 +--- a/lib/isccfg/namedconf.c ++++ b/lib/isccfg/namedconf.c +@@ -1679,6 +1679,7 @@ zone_clauses[] = { + { "masterfile-format", &cfg_type_masterformat, 0 }, + { "max-ixfr-log-size", &cfg_type_size, CFG_CLAUSEFLAG_OBSOLETE }, + { "max-journal-size", &cfg_type_sizenodefault, 0 }, ++ { "max-records", &cfg_type_uint32, 0 }, + { "max-refresh-time", &cfg_type_uint32, 0 }, + { "max-retry-time", &cfg_type_uint32, 0 }, + { "max-transfer-idle-in", &cfg_type_uint32, 0 }, +-- +2.7.4 + diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/bind/bind/CVE-2016-8864.patch b/import-layers/yocto-poky/meta/recipes-connectivity/bind/bind/CVE-2016-8864.patch new file mode 100644 index 000000000..b52d6800f --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-connectivity/bind/bind/CVE-2016-8864.patch @@ -0,0 +1,219 @@ +From c1d0599a246f646d1c22018f8fa09459270a44b8 Mon Sep 17 00:00:00 2001 +From: Mark Andrews <marka@isc.org> +Date: Fri, 21 Oct 2016 14:55:10 +1100 +Subject: [PATCH] 4489. [security] It was possible to trigger assertions when + processing a response. (CVE-2016-8864) [RT #43465] + +(cherry picked from commit bd6f27f5c353133b563fe69100b2f168c129f3ca) + +Upstream-Status: Backport +[https://source.isc.org/cgi-bin/gitweb.cgi?p=bind9.git;a=commit;h=c1d0599a246f646d1c22018f8fa09459270a44b8] + +CVE: CVE-2016-8864 + +Signed-off-by: Yi Zhao <yi.zhao@windriver.com> +--- + CHANGES | 3 +++ + lib/dns/resolver.c | 69 +++++++++++++++++++++++++++++++++++++----------------- + 2 files changed, 50 insertions(+), 22 deletions(-) + +diff --git a/CHANGES b/CHANGES +index 5c8c61a..41cfce5 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -1,3 +1,6 @@ ++4489. [security] It was possible to trigger assertions when processing ++ a response. (CVE-2016-8864) [RT #43465] ++ + 4467. [security] It was possible to trigger an assertion when + rendering a message. (CVE-2016-2776) [RT #43139] + +diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c +index ba1ae23..13c8b44 100644 +--- a/lib/dns/resolver.c ++++ b/lib/dns/resolver.c +@@ -612,7 +612,9 @@ valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name, + valarg->addrinfo = addrinfo; + + if (!ISC_LIST_EMPTY(fctx->validators)) +- INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0); ++ valoptions |= DNS_VALIDATOR_DEFER; ++ else ++ valoptions &= ~DNS_VALIDATOR_DEFER; + + result = dns_validator_create(fctx->res->view, name, type, rdataset, + sigrdataset, fctx->rmessage, +@@ -5526,13 +5528,6 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, + rdataset, + sigrdataset, + valoptions, task); +- /* +- * Defer any further validations. +- * This prevents multiple validators +- * from manipulating fctx->rmessage +- * simultaneously. +- */ +- valoptions |= DNS_VALIDATOR_DEFER; + } + } else if (CHAINING(rdataset)) { + if (rdataset->type == dns_rdatatype_cname) +@@ -5647,6 +5642,11 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, + eresult == DNS_R_NCACHENXRRSET); + } + event->result = eresult; ++ if (adbp != NULL && *adbp != NULL) { ++ if (anodep != NULL && *anodep != NULL) ++ dns_db_detachnode(*adbp, anodep); ++ dns_db_detach(adbp); ++ } + dns_db_attach(fctx->cache, adbp); + dns_db_transfernode(fctx->cache, &node, anodep); + clone_results(fctx); +@@ -5897,6 +5897,11 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, + fctx->attributes |= FCTX_ATTR_HAVEANSWER; + if (event != NULL) { + event->result = eresult; ++ if (adbp != NULL && *adbp != NULL) { ++ if (anodep != NULL && *anodep != NULL) ++ dns_db_detachnode(*adbp, anodep); ++ dns_db_detach(adbp); ++ } + dns_db_attach(fctx->cache, adbp); + dns_db_transfernode(fctx->cache, &node, anodep); + clone_results(fctx); +@@ -6718,13 +6723,15 @@ static isc_result_t + answer_response(fetchctx_t *fctx) { + isc_result_t result; + dns_message_t *message; +- dns_name_t *name, *dname, *qname, tname, *ns_name; ++ dns_name_t *name, *dname = NULL, *qname, *dqname, tname, *ns_name; ++ dns_name_t *cname = NULL; + dns_rdataset_t *rdataset, *ns_rdataset; + isc_boolean_t done, external, chaining, aa, found, want_chaining; +- isc_boolean_t have_answer, found_cname, found_type, wanted_chaining; ++ isc_boolean_t have_answer, found_cname, found_dname, found_type; ++ isc_boolean_t wanted_chaining; + unsigned int aflag; + dns_rdatatype_t type; +- dns_fixedname_t fdname, fqname; ++ dns_fixedname_t fdname, fqname, fqdname; + dns_view_t *view; + + FCTXTRACE("answer_response"); +@@ -6738,6 +6745,7 @@ answer_response(fetchctx_t *fctx) { + + done = ISC_FALSE; + found_cname = ISC_FALSE; ++ found_dname = ISC_FALSE; + found_type = ISC_FALSE; + chaining = ISC_FALSE; + have_answer = ISC_FALSE; +@@ -6747,12 +6755,13 @@ answer_response(fetchctx_t *fctx) { + aa = ISC_TRUE; + else + aa = ISC_FALSE; +- qname = &fctx->name; ++ dqname = qname = &fctx->name; + type = fctx->type; + view = fctx->res->view; ++ dns_fixedname_init(&fqdname); + result = dns_message_firstname(message, DNS_SECTION_ANSWER); + while (!done && result == ISC_R_SUCCESS) { +- dns_namereln_t namereln; ++ dns_namereln_t namereln, dnamereln; + int order; + unsigned int nlabels; + +@@ -6760,6 +6769,8 @@ answer_response(fetchctx_t *fctx) { + dns_message_currentname(message, DNS_SECTION_ANSWER, &name); + external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain)); + namereln = dns_name_fullcompare(qname, name, &order, &nlabels); ++ dnamereln = dns_name_fullcompare(dqname, name, &order, ++ &nlabels); + if (namereln == dns_namereln_equal) { + wanted_chaining = ISC_FALSE; + for (rdataset = ISC_LIST_HEAD(name->list); +@@ -6854,7 +6865,7 @@ answer_response(fetchctx_t *fctx) { + } + } else if (rdataset->type == dns_rdatatype_rrsig + && rdataset->covers == +- dns_rdatatype_cname ++ dns_rdatatype_cname + && !found_type) { + /* + * We're looking for something else, +@@ -6884,11 +6895,18 @@ answer_response(fetchctx_t *fctx) { + * a CNAME or DNAME). + */ + INSIST(!external); +- if (aflag == +- DNS_RDATASETATTR_ANSWER) { ++ if ((rdataset->type != ++ dns_rdatatype_cname) || ++ !found_dname || ++ (aflag == ++ DNS_RDATASETATTR_ANSWER)) ++ { + have_answer = ISC_TRUE; ++ if (rdataset->type == ++ dns_rdatatype_cname) ++ cname = name; + name->attributes |= +- DNS_NAMEATTR_ANSWER; ++ DNS_NAMEATTR_ANSWER; + } + rdataset->attributes |= aflag; + if (aa) +@@ -6982,11 +7000,11 @@ answer_response(fetchctx_t *fctx) { + return (DNS_R_FORMERR); + } + +- if (namereln != dns_namereln_subdomain) { ++ if (dnamereln != dns_namereln_subdomain) { + char qbuf[DNS_NAME_FORMATSIZE]; + char obuf[DNS_NAME_FORMATSIZE]; + +- dns_name_format(qname, qbuf, ++ dns_name_format(dqname, qbuf, + sizeof(qbuf)); + dns_name_format(name, obuf, + sizeof(obuf)); +@@ -7001,7 +7019,7 @@ answer_response(fetchctx_t *fctx) { + want_chaining = ISC_TRUE; + POST(want_chaining); + aflag = DNS_RDATASETATTR_ANSWER; +- result = dname_target(rdataset, qname, ++ result = dname_target(rdataset, dqname, + nlabels, &fdname); + if (result == ISC_R_NOSPACE) { + /* +@@ -7018,10 +7036,13 @@ answer_response(fetchctx_t *fctx) { + + dname = dns_fixedname_name(&fdname); + if (!is_answertarget_allowed(view, +- qname, rdataset->type, +- dname, &fctx->domain)) { ++ dqname, rdataset->type, ++ dname, &fctx->domain)) ++ { + return (DNS_R_SERVFAIL); + } ++ dqname = dns_fixedname_name(&fqdname); ++ dns_name_copy(dname, dqname, NULL); + } else { + /* + * We've found a signature that +@@ -7046,6 +7067,10 @@ answer_response(fetchctx_t *fctx) { + INSIST(!external); + if (aflag == DNS_RDATASETATTR_ANSWER) { + have_answer = ISC_TRUE; ++ found_dname = ISC_TRUE; ++ if (cname != NULL) ++ cname->attributes &= ++ ~DNS_NAMEATTR_ANSWER; + name->attributes |= + DNS_NAMEATTR_ANSWER; + } +-- +2.7.4 + diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/bind/bind_9.10.3-P3.bb b/import-layers/yocto-poky/meta/recipes-connectivity/bind/bind_9.10.3-P3.bb index 4e2e856b7..816062528 100644 --- a/import-layers/yocto-poky/meta/recipes-connectivity/bind/bind_9.10.3-P3.bb +++ b/import-layers/yocto-poky/meta/recipes-connectivity/bind/bind_9.10.3-P3.bb @@ -27,6 +27,8 @@ SRC_URI = "ftp://ftp.isc.org/isc/bind9/${PV}/${BPN}-${PV}.tar.gz \ file://CVE-2016-2088.patch \ file://CVE-2016-2775.patch \ file://CVE-2016-2776.patch \ + file://CVE-2016-8864.patch \ + file://CVE-2016-6170.patch \ " SRC_URI[md5sum] = "bcf7e772b616f7259420a3edc5df350a" diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/connman/connman/0003-stats-Fix-bad-file-descriptor-initialisation.patch b/import-layers/yocto-poky/meta/recipes-connectivity/connman/connman/0003-stats-Fix-bad-file-descriptor-initialisation.patch new file mode 100644 index 000000000..c545811ee --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-connectivity/connman/connman/0003-stats-Fix-bad-file-descriptor-initialisation.patch @@ -0,0 +1,102 @@ +From c7f4151fb053b0d0691d8f10d7e3690265d28889 Mon Sep 17 00:00:00 2001 +From: Lukasz Nowak <lnowak@tycoint.com> +Date: Wed, 26 Oct 2016 18:13:02 +0100 +Subject: [PATCH] stats: Fix bad file descriptor initialisation + +Stats file code initialises its file descriptor field to 0. But 0 is +a valid fd value. -1 should be used instead. This causes problems +when an error happens before a stats file is open (e.g. mkdir +fails). The clean-up procedure, stats_free() calls close(fd). When fd +is 0, this first closes stdin, and then any files/sockets which +received fd=0, re-used by the OS. + +Fixed several instances of bad file descriptor field handling, in case +of errors. + +The bug results with connman freezing if there is no read/write storage +directory available, and there are multiple active interfaces +(fd=0 gets re-used for sockets in that case). + +The patch was imported from the Connman git repository +(git://git.kernel.org/pub/scm/network/connman) as of commit id +c7f4151fb053b0d0691d8f10d7e3690265d28889. + +Upstream-Status: Accepted +Signed-off-by: Lukasz Nowak <lnowak@tycoint.com> +--- + src/stats.c | 15 +++++++++++++++ + src/util.c | 4 ++-- + 2 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/src/stats.c b/src/stats.c +index 26343b1..c3ca738 100644 +--- a/src/stats.c ++++ b/src/stats.c +@@ -378,6 +378,7 @@ static int stats_file_setup(struct stats_file *file) + strerror(errno), file->name); + + TFR(close(file->fd)); ++ file->fd = -1; + g_free(file->name); + file->name = NULL; + +@@ -393,6 +394,7 @@ static int stats_file_setup(struct stats_file *file) + err = stats_file_remap(file, size); + if (err < 0) { + TFR(close(file->fd)); ++ file->fd = -1; + g_free(file->name); + file->name = NULL; + +@@ -649,6 +651,13 @@ static int stats_file_history_update(struct stats_file *data_file) + bzero(history_file, sizeof(struct stats_file)); + bzero(temp_file, sizeof(struct stats_file)); + ++ /* ++ * 0 is a valid file descriptor - fd needs to be initialized ++ * to -1 to handle errors correctly ++ */ ++ history_file->fd = -1; ++ temp_file->fd = -1; ++ + err = stats_open(history_file, data_file->history_name); + if (err < 0) + return err; +@@ -682,6 +691,12 @@ int __connman_stats_service_register(struct connman_service *service) + if (!file) + return -ENOMEM; + ++ /* ++ * 0 is a valid file descriptor - fd needs to be initialized ++ * to -1 to handle errors correctly ++ */ ++ file->fd = -1; ++ + g_hash_table_insert(stats_hash, service, file); + } else { + return -EALREADY; +diff --git a/src/util.c b/src/util.c +index e6532c8..732d451 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -63,7 +63,7 @@ int __connman_util_init(void) + { + int r = 0; + +- if (f > 0) ++ if (f >= 0) + return 0; + + f = open(URANDOM, O_RDONLY); +@@ -86,7 +86,7 @@ int __connman_util_init(void) + + void __connman_util_cleanup(void) + { +- if (f > 0) ++ if (f >= 0) + close(f); + + f = -1; +-- +2.7.4 + diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/connman/connman/CVE-2017-12865.patch b/import-layers/yocto-poky/meta/recipes-connectivity/connman/connman/CVE-2017-12865.patch new file mode 100644 index 000000000..45f78f10e --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-connectivity/connman/connman/CVE-2017-12865.patch @@ -0,0 +1,87 @@ +From 5c281d182ecdd0a424b64f7698f32467f8f67b71 Mon Sep 17 00:00:00 2001 +From: Jukka Rissanen <jukka.rissanen@linux.intel.com> +Date: Wed, 9 Aug 2017 10:16:46 +0300 +Subject: dnsproxy: Fix crash on malformed DNS response + +If the response query string is malformed, we might access memory +pass the end of "name" variable in parse_response(). + +CVE: CVE-2017-12865 +Upstream-Status: Backport [https://git.kernel.org/pub/scm/network/connman/connman.git/patch/?id=5c281d182ecdd0a424b64f7698f32467f8f67b71] + +Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> +--- + src/dnsproxy.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/src/dnsproxy.c b/src/dnsproxy.c +index 38ac5bf..40b4f15 100644 +--- a/src/dnsproxy.c ++++ b/src/dnsproxy.c +@@ -838,7 +838,7 @@ static struct cache_entry *cache_check(gpointer request, int *qtype, int proto) + static int get_name(int counter, + unsigned char *pkt, unsigned char *start, unsigned char *max, + unsigned char *output, int output_max, int *output_len, +- unsigned char **end, char *name, int *name_len) ++ unsigned char **end, char *name, size_t max_name, int *name_len) + { + unsigned char *p; + +@@ -859,7 +859,7 @@ static int get_name(int counter, + + return get_name(counter + 1, pkt, pkt + offset, max, + output, output_max, output_len, end, +- name, name_len); ++ name, max_name, name_len); + } else { + unsigned label_len = *p; + +@@ -869,6 +869,9 @@ static int get_name(int counter, + if (*output_len > output_max) + return -ENOBUFS; + ++ if ((*name_len + 1 + label_len + 1) > max_name) ++ return -ENOBUFS; ++ + /* + * We need the original name in order to check + * if this answer is the correct one. +@@ -900,14 +903,14 @@ static int parse_rr(unsigned char *buf, unsigned char *start, + unsigned char *response, unsigned int *response_size, + uint16_t *type, uint16_t *class, int *ttl, int *rdlen, + unsigned char **end, +- char *name) ++ char *name, size_t max_name) + { + struct domain_rr *rr; + int err, offset; + int name_len = 0, output_len = 0, max_rsp = *response_size; + + err = get_name(0, buf, start, max, response, max_rsp, +- &output_len, end, name, &name_len); ++ &output_len, end, name, max_name, &name_len); + if (err < 0) + return err; + +@@ -1033,7 +1036,8 @@ static int parse_response(unsigned char *buf, int buflen, + memset(rsp, 0, sizeof(rsp)); + + ret = parse_rr(buf, ptr, buf + buflen, rsp, &rsp_len, +- type, class, ttl, &rdlen, &next, name); ++ type, class, ttl, &rdlen, &next, name, ++ sizeof(name) - 1); + if (ret != 0) { + err = ret; + goto out; +@@ -1099,7 +1103,7 @@ static int parse_response(unsigned char *buf, int buflen, + */ + ret = get_name(0, buf, next - rdlen, buf + buflen, + rsp, rsp_len, &output_len, &end, +- name, &name_len); ++ name, sizeof(name) - 1, &name_len); + if (ret != 0) { + /* just ignore the error at this point */ + ptr = next; +-- +cgit v1.1 + diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/connman/connman_1.33.bb b/import-layers/yocto-poky/meta/recipes-connectivity/connman/connman_1.33.bb index 6ea1a08dc..d8793ac8b 100644 --- a/import-layers/yocto-poky/meta/recipes-connectivity/connman/connman_1.33.bb +++ b/import-layers/yocto-poky/meta/recipes-connectivity/connman/connman_1.33.bb @@ -5,6 +5,8 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/network/${BPN}/${BP}.tar.xz \ file://connman \ file://no-version-scripts.patch \ file://includes.patch \ + file://0003-stats-Fix-bad-file-descriptor-initialisation.patch \ + file://CVE-2017-12865.patch \ " SRC_URI_append_libc-musl = " file://0002-resolve-musl-does-not-implement-res_ninit.patch" diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/nfs-utils/nfs-utils/fix-protocol-minor-version-fall-back.patch b/import-layers/yocto-poky/meta/recipes-connectivity/nfs-utils/nfs-utils/fix-protocol-minor-version-fall-back.patch new file mode 100644 index 000000000..683246c4a --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-connectivity/nfs-utils/nfs-utils/fix-protocol-minor-version-fall-back.patch @@ -0,0 +1,55 @@ +From 78bb645a42c216b37b8d930c7c849a3fa89babf8 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai <tiwai@suse.com> +Date: Sat, 16 Jan 2016 12:02:30 -0500 +Subject: [PATCH] Fix protocol minor version fall-back + +mount.nfs currently expects mount(2) to fail with EPROTONOSUPPORT if +the kernel doesn't understand the requested NFS version. + +Unfortunately if the requested minor is not known to the kernel +it returns -EINVAL. +In kernels since 3.11 this can happen in nfs4_alloc_client(), if +compiled without NFS_V4_2. + +More generally it can happen in in nfs_validate_text_mount_data() +when nfs_parse_mount_options() returns 0 because +nfs_parse_version_string() +didn't recognise the version. + +EPROTONOSUPPORT is only returned if NFSv4 support is completely compiled +out. + +So nfs_autonegotiate needs to check for EINVAL as well as +EPROTONOSUPPORT. + +URL: https://bugzilla.opensuse.org/show_bug.cgi?id=959211 +Reported-by: Takashi Iwai <tiwai@suse.com> +Signed-off-by: NeilBrown <neilb@suse.com> +Signed-off-by: Steve Dickson <steved@redhat.com> + + +Upstream-Status: Backport +http://git.linux-nfs.org/?p=steved/nfs-utils.git;a=patch;h=78bb645a42c216b37b8d930c7c849a3fa89babf8 + +Signed-off-by: Yi Zhao <yi.zhao@windriver.com> +--- + utils/mount/stropts.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c +index c8f5a6d..86829a9 100644 +--- a/utils/mount/stropts.c ++++ b/utils/mount/stropts.c +@@ -841,6 +841,9 @@ check_result: + case EPROTONOSUPPORT: + /* A clear indication that the server or our + * client does not support NFS version 4 and minor */ ++ case EINVAL: ++ /* A less clear indication that our client ++ * does not support NFSv4 minor version. */ + if (mi->version.v_mode == V_GENERAL && + mi->version.minor == 0) + return result; +-- +2.7.4 + diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/nfs-utils/nfs-utils_1.3.3.bb b/import-layers/yocto-poky/meta/recipes-connectivity/nfs-utils/nfs-utils_1.3.3.bb index 8540503df..a2bebe0ba 100644 --- a/import-layers/yocto-poky/meta/recipes-connectivity/nfs-utils/nfs-utils_1.3.3.bb +++ b/import-layers/yocto-poky/meta/recipes-connectivity/nfs-utils/nfs-utils_1.3.3.bb @@ -33,6 +33,7 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/utils/nfs-utils/${PV}/nfs-utils-${PV}.tar.x file://nfs-utils-debianize-start-statd.patch \ file://0001-nfs-utils-statd-fix-a-segfault-caused-by-improper-us.patch \ file://bugfix-adjust-statd-service-name.patch \ + file://fix-protocol-minor-version-fall-back.patch \ " SRC_URI[md5sum] = "cd6b568c2e9301cc3bfac09d87fbbc0b" diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/openssh/openssh/fix-CVE-2016-8858.patch b/import-layers/yocto-poky/meta/recipes-connectivity/openssh/openssh/fix-CVE-2016-8858.patch new file mode 100644 index 000000000..b26ee81b9 --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-connectivity/openssh/openssh/fix-CVE-2016-8858.patch @@ -0,0 +1,39 @@ +Fix CVE-2016-8858 of openssh + +Backport patch from upstream and drop the change of comment which can NOT be applied. + +Upstream-Status: Backport [ https://anongit.mindrot.org/openssh.git/commit/?id=ec165c3 ] +CVE: CVE-2016-8858 + +Signed-off-by: Kai Kang <kai.kang@windriver.com> +--- +From ec165c392ca54317dbe3064a8c200de6531e89ad Mon Sep 17 00:00:00 2001 +From: "markus@openbsd.org" <markus@openbsd.org> +Date: Mon, 10 Oct 2016 19:28:48 +0000 +Subject: [PATCH] upstream commit + +Unregister the KEXINIT handler after message has been +received. Otherwise an unauthenticated peer can repeat the KEXINIT and cause +allocation of up to 128MB -- until the connection is closed. Reported by +shilei-c at 360.cn + +Upstream-ID: 43649ae12a27ef94290db16d1a98294588b75c05 +--- + kex.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kex.c b/kex.c +index 3f97f8c..6a94bc5 100644 +--- a/kex.c ++++ b/kex.c +@@ -481,6 +481,7 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt) + if (kex == NULL) + return SSH_ERR_INVALID_ARGUMENT; + ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); + ptr = sshpkt_ptr(ssh, &dlen); + if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) + return r; +-- +2.10.1 + diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/openssh/openssh_7.3p1.bb b/import-layers/yocto-poky/meta/recipes-connectivity/openssh/openssh_7.3p1.bb index 039b0ffdd..94eb0ed20 100644 --- a/import-layers/yocto-poky/meta/recipes-connectivity/openssh/openssh_7.3p1.bb +++ b/import-layers/yocto-poky/meta/recipes-connectivity/openssh/openssh_7.3p1.bb @@ -25,6 +25,7 @@ SRC_URI = "http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${PV}.tar file://openssh-7.1p1-conditional-compile-des-in-cipher.patch \ file://openssh-7.1p1-conditional-compile-des-in-pkcs11.patch \ file://fix-potential-signed-overflow-in-pointer-arithmatic.patch \ + file://fix-CVE-2016-8858.patch \ " PAM_SRC_URI = "file://sshd" diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl.inc b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl.inc index f3a2c5abd..2ef8b38be 100644 --- a/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl.inc +++ b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl.inc @@ -107,18 +107,24 @@ do_configure () { linux-gnu64-x86_64) target=linux-x86_64 ;; - linux-mips) - target=debian-mips + linux-gnun32-mips*el) + target=debian-mipsn32el + ;; + linux-gnun32-mips*) + target=debian-mipsn32 + ;; + linux-mips*64*el) + target=debian-mips64el ;; - linux-mipsel) + linux-mips*64*) + target=debian-mips64 + ;; + linux-mips*el) target=debian-mipsel ;; - linux-*-mips64 | linux-mips64) - target=debian-mips64 - ;; - linux-*-mips64el | linux-mips64el) - target=debian-mips64el - ;; + linux-mips*) + target=debian-mips + ;; linux-microblaze*|linux-nios2*) target=linux-generic32 ;; diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/0001-CVE-2017-3731.patch b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/0001-CVE-2017-3731.patch new file mode 100644 index 000000000..04ef52682 --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/0001-CVE-2017-3731.patch @@ -0,0 +1,46 @@ +From 0cde9a9645c949fd0acf657dadc747676245cfaf Mon Sep 17 00:00:00 2001 +From: Alexandru Moise <alexandru.moise@windriver.com> +Date: Tue, 7 Feb 2017 11:13:19 +0200 +Subject: [PATCH 1/2] crypto/evp: harden RC4_MD5 cipher. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Originally a crash in 32-bit build was reported CHACHA20-POLY1305 +cipher. The crash is triggered by truncated packet and is result +of excessive hashing to the edge of accessible memory (or bogus +MAC value is produced if x86 MD5 assembly module is involved). Since +hash operation is read-only it is not considered to be exploitable +beyond a DoS condition. + +Thanks to Robert Święcki for report. + +CVE-2017-3731 + +Backported from upstream commit: +8e20499629b6bcf868d0072c7011e590b5c2294d + +Upstream-Status: Backport + +Reviewed-by: Rich Salz <rsalz@openssl.org> +Signed-off-by: Alexandru Moise <alexandru.moise@windriver.com> +--- + crypto/evp/e_rc4_hmac_md5.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/crypto/evp/e_rc4_hmac_md5.c b/crypto/evp/e_rc4_hmac_md5.c +index 5e92855..3293419 100644 +--- a/crypto/evp/e_rc4_hmac_md5.c ++++ b/crypto/evp/e_rc4_hmac_md5.c +@@ -269,6 +269,8 @@ static int rc4_hmac_md5_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, + len = p[arg - 2] << 8 | p[arg - 1]; + + if (!ctx->encrypt) { ++ if (len < MD5_DIGEST_LENGTH) ++ return -1; + len -= MD5_DIGEST_LENGTH; + p[arg - 2] = len >> 8; + p[arg - 1] = len; +-- +2.10.2 + diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/0002-CVE-2017-3731.patch b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/0002-CVE-2017-3731.patch new file mode 100644 index 000000000..b56b2d5bd --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/0002-CVE-2017-3731.patch @@ -0,0 +1,53 @@ +From 6427f1accc54b515bb899370f1a662bfcb1caa52 Mon Sep 17 00:00:00 2001 +From: Alexandru Moise <alexandru.moise@windriver.com> +Date: Tue, 7 Feb 2017 11:16:13 +0200 +Subject: [PATCH 2/2] crypto/evp: harden AEAD ciphers. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Originally a crash in 32-bit build was reported CHACHA20-POLY1305 +cipher. The crash is triggered by truncated packet and is result +of excessive hashing to the edge of accessible memory. Since hash +operation is read-only it is not considered to be exploitable +beyond a DoS condition. Other ciphers were hardened. + +Thanks to Robert Święcki for report. + +CVE-2017-3731 + +Backported from upstream commit: +2198b3a55de681e1f3c23edb0586afe13f438051 + +Upstream-Status: Backport + +Reviewed-by: Rich Salz <rsalz@openssl.org> +Signed-off-by: Alexandru Moise <alexandru.moise@windriver.com> +--- + crypto/evp/e_aes.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c +index 1734a82..16dcd10 100644 +--- a/crypto/evp/e_aes.c ++++ b/crypto/evp/e_aes.c +@@ -1235,10 +1235,15 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) + { + unsigned int len = c->buf[arg - 2] << 8 | c->buf[arg - 1]; + /* Correct length for explicit IV */ ++ if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN) ++ return 0; + len -= EVP_GCM_TLS_EXPLICIT_IV_LEN; + /* If decrypting correct for tag too */ +- if (!c->encrypt) ++ if (!c->encrypt) { ++ if (len < EVP_GCM_TLS_TAG_LEN) ++ return 0; + len -= EVP_GCM_TLS_TAG_LEN; ++ } + c->buf[arg - 2] = len >> 8; + c->buf[arg - 1] = len & 0xff; + } +-- +2.10.2 + diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/CVE-2016-7055.patch b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/CVE-2016-7055.patch new file mode 100644 index 000000000..83a74cdac --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/CVE-2016-7055.patch @@ -0,0 +1,43 @@ +From 57c4b9f6a2f800b41ce2836986fe33640f6c3f8a Mon Sep 17 00:00:00 2001 +From: Andy Polyakov <appro@openssl.org> +Date: Sun, 6 Nov 2016 18:33:17 +0100 +Subject: [PATCH] bn/asm/x86_64-mont.pl: fix for CVE-2016-7055 (Low severity). + +Reviewed-by: Rich Salz <rsalz@openssl.org> +(cherry picked from commit 2fac86d9abeaa643677d1ffd0a139239fdf9406a) + +Upstream-Status: Backport [https://github.com/openssl/openssl/commit/57c4b9f6a2f800b41ce2836986fe33640f6c3f8a] +CVE: CVE-2016-7055 +Signed-off-by: Yi Zhao <yi.zhao@windriver.com> +--- + crypto/bn/asm/x86_64-mont.pl | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/crypto/bn/asm/x86_64-mont.pl b/crypto/bn/asm/x86_64-mont.pl +index 044fd7e..80492d8 100755 +--- a/crypto/bn/asm/x86_64-mont.pl ++++ b/crypto/bn/asm/x86_64-mont.pl +@@ -1148,18 +1148,17 @@ $code.=<<___; + mulx 2*8($aptr),%r15,%r13 # ... + adox -3*8($tptr),%r11 + adcx %r15,%r12 +- adox $zero,%r12 ++ adox -2*8($tptr),%r12 + adcx $zero,%r13 ++ adox $zero,%r13 + + mov $bptr,8(%rsp) # off-load &b[i] +- .byte 0x67 + mov $mi,%r15 + imulq 24(%rsp),$mi # "t[0]"*n0 + xor %ebp,%ebp # xor $zero,$zero # cf=0, of=0 + + mulx 3*8($aptr),%rax,%r14 + mov $mi,%rdx +- adox -2*8($tptr),%r12 + adcx %rax,%r13 + adox -1*8($tptr),%r13 + adcx $zero,%r14 +-- +2.7.4 + diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/Use-SHA256-not-MD5-as-default-digest.patch b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/Use-SHA256-not-MD5-as-default-digest.patch new file mode 100644 index 000000000..58c9ee784 --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/Use-SHA256-not-MD5-as-default-digest.patch @@ -0,0 +1,69 @@ +From d795f5f20a29adecf92c09459a3ee07ffac01a99 Mon Sep 17 00:00:00 2001 +From: Rich Salz <rsalz@akamai.com> +Date: Sat, 13 Jun 2015 17:03:39 -0400 +Subject: [PATCH] Use SHA256 not MD5 as default digest. + +Commit f8547f62c212837dbf44fb7e2755e5774a59a57b upstream. + +Upstream-Status: Backport +Backport from OpenSSL 2.0 to OpenSSL 1.0.2 +Commit f8547f62c212837dbf44fb7e2755e5774a59a57b + +CVE: CVE-2004-2761 + + The MD5 Message-Digest Algorithm is not collision resistant, + which makes it easier for context-dependent attackers to + conduct spoofing attacks, as demonstrated by attacks on the + use of MD5 in the signature algorithm of an X.509 certificate. + +Reviewed-by: Viktor Dukhovni <viktor@openssl.org> +Signed-off-by: Zhang Xiao <xiao.zhang@windriver.com> +Signed-off-by: T.O. Radzy Radzykewycz <radzy@windriver.com> +--- + apps/ca.c | 2 +- + apps/dgst.c | 2 +- + apps/enc.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/apps/ca.c b/apps/ca.c +index 3b7336c..8f3a84b 100644 +--- a/apps/ca.c ++++ b/apps/ca.c +@@ -1612,7 +1612,7 @@ static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, + } else + BIO_printf(bio_err, "Signature ok\n"); + +- if ((rreq = X509_to_X509_REQ(req, NULL, EVP_md5())) == NULL) ++ if ((rreq = X509_to_X509_REQ(req, NULL, NULL)) == NULL) + goto err; + + ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj, +diff --git a/apps/dgst.c b/apps/dgst.c +index 95e5fa3..0d1529f 100644 +--- a/apps/dgst.c ++++ b/apps/dgst.c +@@ -442,7 +442,7 @@ int MAIN(int argc, char **argv) + goto end; + } + if (md == NULL) +- md = EVP_md5(); ++ md = EVP_sha256(); + if (!EVP_DigestInit_ex(mctx, md, impl)) { + BIO_printf(bio_err, "Error setting digest %s\n", pname); + ERR_print_errors(bio_err); +diff --git a/apps/enc.c b/apps/enc.c +index 7b7c70b..a7d944c 100644 +--- a/apps/enc.c ++++ b/apps/enc.c +@@ -344,7 +344,7 @@ int MAIN(int argc, char **argv) + } + + if (dgst == NULL) { +- dgst = EVP_md5(); ++ dgst = EVP_sha256(); + } + + if (bufsize != NULL) { +-- +1.9.1 + diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/openssl-c_rehash.sh b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/openssl-c_rehash.sh index f67f41554..6620fdcb5 100644 --- a/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/openssl-c_rehash.sh +++ b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl/openssl-c_rehash.sh @@ -114,11 +114,11 @@ link_hash() LINKFILE=${HASH}.${TAG}${SUFFIX} done - echo "${1} => ${LINKFILE}" + echo "${3} => ${LINKFILE}" # assume any system with a POSIX shell will either support symlinks or # do something to handle this gracefully - ln -s ${1} ${LINKFILE} + ln -s ${3} ${LINKFILE} return 0 } @@ -142,7 +142,19 @@ hash_dir() ls -1 *.pem *.cer *.crt *.crl 2>/dev/null | while read FILE do - check_file ${FILE} + REAL_FILE=${FILE} + # if we run on build host then get to the real files in rootfs + if [ -n "${SYSROOT}" -a -h ${FILE} ] + then + FILE=$( readlink ${FILE} ) + # check the symlink is absolute (or dangling in other word) + if [ "x/" = "x$( echo ${FILE} | cut -c1 -)" ] + then + REAL_FILE=${SYSROOT}/${FILE} + fi + fi + + check_file ${REAL_FILE} local FILE_TYPE=${?} local TYPE_STR='' @@ -157,7 +169,7 @@ hash_dir() continue fi - link_hash ${FILE} ${TYPE_STR} + link_hash ${REAL_FILE} ${TYPE_STR} ${FILE} done } diff --git a/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl_1.0.2j.bb b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl_1.0.2j.bb index 257e3cfc4..b6fb12634 100644 --- a/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl_1.0.2j.bb +++ b/import-layers/yocto-poky/meta/recipes-connectivity/openssl/openssl_1.0.2j.bb @@ -5,6 +5,7 @@ require openssl.inc DEPENDS += "cryptodev-linux" CFLAG += "-DHAVE_CRYPTODEV -DUSE_CRYPTODEV_DIGESTS" +CFLAG_append_class-native = " -fPIC" LIC_FILES_CHKSUM = "file://LICENSE;md5=27ffa5d74bb5a337056c14b2ef93fbf6" @@ -40,6 +41,9 @@ SRC_URI += "file://find.pl;subdir=${BP}/util/ \ file://configure-musl-target.patch \ file://parallel.patch \ file://openssl-util-perlpath.pl-cwd.patch \ + file://CVE-2016-7055.patch \ + file://0001-CVE-2017-3731.patch \ + file://0002-CVE-2017-3731.patch \ " SRC_URI[md5sum] = "96322138f0b69e61b7212bc53d5e912b" SRC_URI[sha256sum] = "e7aff292be21c259c6af26469c7a9b3ba26e9abaaffd325e3dccc9785256c431" |