From owner-svn-src-stable@FreeBSD.ORG Wed Dec 10 08:31:45 2014 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 79E92D4D; Wed, 10 Dec 2014 08:31:45 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 63185902; Wed, 10 Dec 2014 08:31:45 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sBA8VjRF037673; Wed, 10 Dec 2014 08:31:45 GMT (envelope-from delphij@FreeBSD.org) Received: (from delphij@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sBA8Vg2B037657; Wed, 10 Dec 2014 08:31:42 GMT (envelope-from delphij@FreeBSD.org) Message-Id: <201412100831.sBA8Vg2B037657@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: delphij set sender to delphij@FreeBSD.org using -f From: Xin LI Date: Wed, 10 Dec 2014 08:31:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r275669 - in stable: 8/contrib/bind9 8/contrib/bind9/bin/named 8/contrib/bind9/lib/dns 8/contrib/bind9/lib/dns/include/dns 8/contrib/bind9/lib/export/isc 8/contrib/bind9/lib/isc 8/contr... X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Dec 2014 08:31:45 -0000 Author: delphij Date: Wed Dec 10 08:31:41 2014 New Revision: 275669 URL: https://svnweb.freebsd.org/changeset/base/275669 Log: Fix multiple vulnerabilities in file(1) and libmagic(3). Security: FreeBSD-SA-14:28.file Security: CVE-2014-3710, CVE-2014-8116, CVE-2014-8117 Fix BIND remote denial of service vulnerability. Security: FreeBSD-SA-14:29.bind Security: CVE-2014-8500 Modified: stable/9/contrib/bind9/CHANGES stable/9/contrib/bind9/bin/named/config.c stable/9/contrib/bind9/bin/named/query.c stable/9/contrib/bind9/bin/named/server.c stable/9/contrib/bind9/lib/dns/adb.c stable/9/contrib/bind9/lib/dns/include/dns/adb.h stable/9/contrib/bind9/lib/dns/include/dns/resolver.h stable/9/contrib/bind9/lib/dns/resolver.c stable/9/contrib/bind9/lib/isccfg/namedconf.c stable/9/contrib/file/elfclass.h stable/9/contrib/file/readelf.c stable/9/contrib/file/softmagic.c Changes in other areas also in this revision: Added: stable/8/contrib/bind9/lib/isc/counter.c (contents, props changed) stable/8/contrib/bind9/lib/isc/include/isc/counter.h (contents, props changed) Modified: stable/8/contrib/bind9/CHANGES stable/8/contrib/bind9/bin/named/config.c stable/8/contrib/bind9/bin/named/query.c stable/8/contrib/bind9/bin/named/server.c stable/8/contrib/bind9/lib/dns/adb.c stable/8/contrib/bind9/lib/dns/include/dns/adb.h stable/8/contrib/bind9/lib/dns/include/dns/resolver.h stable/8/contrib/bind9/lib/dns/resolver.c stable/8/contrib/bind9/lib/export/isc/Makefile.in stable/8/contrib/bind9/lib/isc/Makefile.in stable/8/contrib/bind9/lib/isc/include/isc/Makefile.in stable/8/contrib/bind9/lib/isc/include/isc/types.h stable/8/contrib/bind9/lib/isccfg/namedconf.c stable/8/contrib/file/elfclass.h stable/8/contrib/file/readelf.c stable/8/contrib/file/softmagic.c stable/8/lib/bind/isc/Makefile Modified: stable/9/contrib/bind9/CHANGES ============================================================================== --- stable/9/contrib/bind9/CHANGES Wed Dec 10 08:26:53 2014 (r275668) +++ stable/9/contrib/bind9/CHANGES Wed Dec 10 08:31:41 2014 (r275669) @@ -1,3 +1,14 @@ +4006. [security] A flaw in delegation handling could be exploited + to put named into an infinite loop. This has + been addressed by placing limits on the number + of levels of recursion named will allow (default 7), + and the number of iterative queries that it will + send (default 50) before terminating a recursive + query (CVE-2014-8500). + + The recursion depth limit is configured via the + "max-recursion-depth" option. [RT #35780] + --- 9.9.5 released --- --- 9.9.5rc2 released --- Modified: stable/9/contrib/bind9/bin/named/config.c ============================================================================== --- stable/9/contrib/bind9/bin/named/config.c Wed Dec 10 08:26:53 2014 (r275668) +++ stable/9/contrib/bind9/bin/named/config.c Wed Dec 10 08:31:41 2014 (r275669) @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.c,v 1.123 2012/01/06 23:46:41 tbox Exp $ */ - /*! \file */ #include @@ -160,6 +158,7 @@ options {\n\ dnssec-accept-expired no;\n\ clients-per-query 10;\n\ max-clients-per-query 100;\n\ + max-recursion-depth 7;\n\ zero-no-soa-ttl-cache no;\n\ nsec3-test-zone no;\n\ allow-new-zones no;\n\ Modified: stable/9/contrib/bind9/bin/named/query.c ============================================================================== --- stable/9/contrib/bind9/bin/named/query.c Wed Dec 10 08:26:53 2014 (r275668) +++ stable/9/contrib/bind9/bin/named/query.c Wed Dec 10 08:31:41 2014 (r275669) @@ -3872,12 +3872,11 @@ query_recurse(ns_client_t *client, dns_r peeraddr = &client->peeraddr; else peeraddr = NULL; - result = dns_resolver_createfetch2(client->view->resolver, + result = dns_resolver_createfetch3(client->view->resolver, qname, qtype, qdomain, nameservers, NULL, peeraddr, client->message->id, - client->query.fetchoptions, - client->task, - query_resume, client, + client->query.fetchoptions, 0, + client->task, query_resume, client, rdataset, sigrdataset, &client->query.fetch); Modified: stable/9/contrib/bind9/bin/named/server.c ============================================================================== --- stable/9/contrib/bind9/bin/named/server.c Wed Dec 10 08:26:53 2014 (r275668) +++ stable/9/contrib/bind9/bin/named/server.c Wed Dec 10 08:31:41 2014 (r275669) @@ -3141,6 +3141,11 @@ configure_view(dns_view_t *view, cfg_obj cfg_obj_asuint32(obj), max_clients_per_query); + obj = NULL; + result = ns_config_get(maps, "max-recursion-depth", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); + #ifdef ALLOW_FILTER_AAAA_ON_V4 obj = NULL; result = ns_config_get(maps, "filter-aaaa-on-v4", &obj); Modified: stable/9/contrib/bind9/lib/dns/adb.c ============================================================================== --- stable/9/contrib/bind9/lib/dns/adb.c Wed Dec 10 08:26:53 2014 (r275668) +++ stable/9/contrib/bind9/lib/dns/adb.c Wed Dec 10 08:31:41 2014 (r275669) @@ -201,6 +201,7 @@ struct dns_adbfetch { unsigned int magic; dns_fetch_t *fetch; dns_rdataset_t rdataset; + unsigned int depth; }; /*% @@ -301,7 +302,7 @@ static inline void violate_locking_hiera static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *); static void clean_target(dns_adb_t *, dns_name_t *); static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, - unsigned int); + isc_uint32_t, unsigned int); static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t); static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **, isc_stdtime_t); @@ -309,7 +310,7 @@ static void cancel_fetches_at_name(dns_a static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t, dns_rdatatype_t); static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t, - dns_rdatatype_t); + unsigned int, dns_rdatatype_t); static inline void check_exit(dns_adb_t *); static void destroy(dns_adb_t *); static isc_boolean_t shutdown_names(dns_adb_t *); @@ -982,7 +983,7 @@ kill_name(dns_adbname_t **n, isc_eventty * Clean up the name's various lists. These two are destructive * in that they will always empty the list. */ - clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK); + clean_finds_at_name(name, ev, 0, DNS_ADBFIND_ADDRESSMASK); result4 = clean_namehooks(adb, &name->v4); result6 = clean_namehooks(adb, &name->v6); clean_target(adb, &name->target); @@ -1407,7 +1408,7 @@ event_free(isc_event_t *event) { */ static void clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype, - unsigned int addrs) + isc_uint32_t qtotal, unsigned int addrs) { isc_event_t *ev; isc_task_t *task; @@ -1467,6 +1468,7 @@ clean_finds_at_name(dns_adbname_t *name, ev->ev_sender = find; find->result_v4 = find_err_map[name->fetch_err]; find->result_v6 = find_err_map[name->fetch6_err]; + find->qtotal += qtotal; ev->ev_type = evtype; ev->ev_destroy = event_free; ev->ev_destroy_arg = find; @@ -1821,6 +1823,7 @@ new_adbfind(dns_adb_t *adb) { h->flags = 0; h->result_v4 = ISC_R_UNEXPECTED; h->result_v6 = ISC_R_UNEXPECTED; + h->qtotal = 0; ISC_LINK_INIT(h, publink); ISC_LINK_INIT(h, plink); ISC_LIST_INIT(h->list); @@ -2770,6 +2773,19 @@ dns_adb_createfind(dns_adb_t *adb, isc_t isc_stdtime_t now, dns_name_t *target, in_port_t port, dns_adbfind_t **findp) { + return (dns_adb_createfind2(adb, task, action, arg, name, + qname, qtype, options, now, + target, port, 0, findp)); +} + +isc_result_t +dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, + void *arg, dns_name_t *name, dns_name_t *qname, + dns_rdatatype_t qtype, unsigned int options, + isc_stdtime_t now, dns_name_t *target, + in_port_t port, unsigned int depth, + dns_adbfind_t **findp) +{ dns_adbfind_t *find; dns_adbname_t *adbname; int bucket; @@ -3000,7 +3016,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_t * Start V4. */ if (WANT_INET(wanted_fetches) && - fetch_name(adbname, start_at_zone, + fetch_name(adbname, start_at_zone, depth, dns_rdatatype_a) == ISC_R_SUCCESS) { DP(DEF_LEVEL, "dns_adb_createfind: started A fetch for name %p", @@ -3011,7 +3027,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_t * Start V6. */ if (WANT_INET6(wanted_fetches) && - fetch_name(adbname, start_at_zone, + fetch_name(adbname, start_at_zone, depth, dns_rdatatype_aaaa) == ISC_R_SUCCESS) { DP(DEF_LEVEL, "dns_adb_createfind: " @@ -3627,6 +3643,7 @@ fetch_callback(isc_task_t *task, isc_eve isc_result_t result; unsigned int address_type; isc_boolean_t want_check_exit = ISC_FALSE; + isc_uint32_t qtotal = 0; UNUSED(task); @@ -3637,6 +3654,8 @@ fetch_callback(isc_task_t *task, isc_eve adb = name->adb; INSIST(DNS_ADB_VALID(adb)); + qtotal = dev->qtotal; + bucket = name->lock_bucket; LOCK(&adb->namelocks[bucket]); @@ -3754,6 +3773,12 @@ fetch_callback(isc_task_t *task, isc_eve DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s", buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA", dns_result_totext(dev->result)); + /* + * Don't record a failure unless this is the initial + * fetch of a chain. + */ + if (fetch->depth > 1) + goto out; /* XXXMLG Don't pound on bad servers. */ if (address_type == DNS_ADBFIND_INET) { name->expire_v4 = ISC_MIN(name->expire_v4, now + 300); @@ -3785,15 +3810,14 @@ fetch_callback(isc_task_t *task, isc_eve free_adbfetch(adb, &fetch); isc_event_free(&ev); - clean_finds_at_name(name, ev_status, address_type); + clean_finds_at_name(name, ev_status, qtotal, address_type); UNLOCK(&adb->namelocks[bucket]); } static isc_result_t -fetch_name(dns_adbname_t *adbname, - isc_boolean_t start_at_zone, - dns_rdatatype_t type) +fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone, + unsigned int depth, dns_rdatatype_t type) { isc_result_t result; dns_adbfetch_t *fetch = NULL; @@ -3838,12 +3862,14 @@ fetch_name(dns_adbname_t *adbname, result = ISC_R_NOMEMORY; goto cleanup; } + fetch->depth = depth; - result = dns_resolver_createfetch(adb->view->resolver, &adbname->name, - type, name, nameservers, NULL, - options, adb->task, fetch_callback, - adbname, &fetch->rdataset, NULL, - &fetch->fetch); + result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name, + type, name, nameservers, NULL, + NULL, 0, options, depth, adb->task, + fetch_callback, adbname, + &fetch->rdataset, NULL, + &fetch->fetch); if (result != ISC_R_SUCCESS) goto cleanup; Modified: stable/9/contrib/bind9/lib/dns/include/dns/adb.h ============================================================================== --- stable/9/contrib/bind9/lib/dns/include/dns/adb.h Wed Dec 10 08:26:53 2014 (r275668) +++ stable/9/contrib/bind9/lib/dns/include/dns/adb.h Wed Dec 10 08:31:41 2014 (r275669) @@ -118,6 +118,8 @@ struct dns_adbfind { isc_result_t result_v6; /*%< RO: v6 result */ ISC_LINK(dns_adbfind_t) publink; /*%< RW: client use */ + isc_uint32_t qtotal; + /* Private */ isc_mutex_t lock; /* locks all below */ in_port_t port; @@ -334,6 +336,12 @@ dns_adb_createfind(dns_adb_t *adb, isc_t dns_rdatatype_t qtype, unsigned int options, isc_stdtime_t now, dns_name_t *target, in_port_t port, dns_adbfind_t **find); +isc_result_t +dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, + void *arg, dns_name_t *name, dns_name_t *qname, + dns_rdatatype_t qtype, unsigned int options, + isc_stdtime_t now, dns_name_t *target, in_port_t port, + unsigned int depth, dns_adbfind_t **find); /*%< * Main interface for clients. The adb will look up the name given in * "name" and will build up a list of found addresses, and perhaps start Modified: stable/9/contrib/bind9/lib/dns/include/dns/resolver.h ============================================================================== --- stable/9/contrib/bind9/lib/dns/include/dns/resolver.h Wed Dec 10 08:26:53 2014 (r275668) +++ stable/9/contrib/bind9/lib/dns/include/dns/resolver.h Wed Dec 10 08:31:41 2014 (r275669) @@ -82,6 +82,7 @@ typedef struct dns_fetchevent { isc_sockaddr_t * client; dns_messageid_t id; isc_result_t vresult; + isc_uint32_t qtotal; } dns_fetchevent_t; /* @@ -274,6 +275,18 @@ dns_resolver_createfetch2(dns_resolver_t dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, dns_fetch_t **fetchp); +isc_result_t +dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, + dns_rdatatype_t type, + dns_name_t *domain, dns_rdataset_t *nameservers, + dns_forwarders_t *forwarders, + isc_sockaddr_t *client, isc_uint16_t id, + unsigned int options, unsigned int depth, + isc_task_t *task, + isc_taskaction_t action, void *arg, + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp); /*%< * Recurse to answer a question. * @@ -575,6 +588,18 @@ dns_resolver_printbadcache(dns_resolver_ * \li resolver to be valid. */ +void +dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth); +unsigned int +dns_resolver_getmaxdepth(dns_resolver_t *resolver); +/*% + * Get and set how many NS indirections will be followed when looking for + * nameserver addresses. + * + * Requires: + * \li resolver to be valid. + */ + ISC_LANG_ENDDECLS #endif /* DNS_RESOLVER_H */ Modified: stable/9/contrib/bind9/lib/dns/resolver.c ============================================================================== --- stable/9/contrib/bind9/lib/dns/resolver.c Wed Dec 10 08:26:53 2014 (r275668) +++ stable/9/contrib/bind9/lib/dns/resolver.c Wed Dec 10 08:31:41 2014 (r275669) @@ -131,6 +131,16 @@ #define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */ #endif +/* The default maximum number of recursions to follow before giving up. */ +#ifndef DEFAULT_RECURSION_DEPTH +#define DEFAULT_RECURSION_DEPTH 7 +#endif + +/* The default maximum number of iterative queries to allow before giving up. */ +#ifndef DEFAULT_MAX_QUERIES +#define DEFAULT_MAX_QUERIES 50 +#endif + /*% * Maximum EDNS0 input packet size. */ @@ -297,6 +307,7 @@ struct fetchctx { isc_uint64_t duration; isc_boolean_t logged; unsigned int querysent; + unsigned int totalqueries; unsigned int referrals; unsigned int lamecount; unsigned int neterr; @@ -307,6 +318,7 @@ struct fetchctx { isc_boolean_t timeout; dns_adbaddrinfo_t *addrinfo; isc_sockaddr_t *client; + unsigned int depth; }; #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!') @@ -418,6 +430,7 @@ struct dns_resolver { isc_timer_t * spillattimer; isc_boolean_t zero_no_soa_ttl; unsigned int query_timeout; + unsigned int maxdepth; /* Locked by lock. */ unsigned int references; @@ -1093,6 +1106,7 @@ fctx_sendevents(fetchctx_t *fctx, isc_re event->result == DNS_R_NCACHENXRRSET); } + event->qtotal = fctx->totalqueries; isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event)); count++; } @@ -1533,7 +1547,9 @@ fctx_query(fetchctx_t *fctx, dns_adbaddr if (result != ISC_R_SUCCESS) goto cleanup_dispatch; } + fctx->querysent++; + fctx->totalqueries++; ISC_LIST_APPEND(fctx->queries, query, link); query->fctx->nqueries++; @@ -2186,9 +2202,10 @@ fctx_finddone(isc_task_t *task, isc_even */ INSIST(!SHUTTINGDOWN(fctx)); fctx->attributes &= ~FCTX_ATTR_ADDRWAIT; - if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) + if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) { want_try = ISC_TRUE; - else { + fctx->totalqueries += find->qtotal; + } else { fctx->findfail++; if (fctx->pending == 0) { /* @@ -2471,12 +2488,13 @@ findname(fetchctx_t *fctx, dns_name_t *n * See what we know about this address. */ find = NULL; - result = dns_adb_createfind(fctx->adb, - res->buckets[fctx->bucketnum].task, - fctx_finddone, fctx, name, - &fctx->name, fctx->type, - options, now, NULL, - res->view->dstport, &find); + result = dns_adb_createfind2(fctx->adb, + res->buckets[fctx->bucketnum].task, + fctx_finddone, fctx, name, + &fctx->name, fctx->type, + options, now, NULL, + res->view->dstport, + fctx->depth + 1, &find); if (result != ISC_R_SUCCESS) { if (result == DNS_R_ALIAS) { /* @@ -2584,6 +2602,11 @@ fctx_getaddresses(fetchctx_t *fctx, isc_ res = fctx->res; + if (fctx->depth > res->maxdepth) { + FCTXTRACE("too much NS indirection"); + return (DNS_R_SERVFAIL); + } + /* * Forwarders. */ @@ -3022,6 +3045,9 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t REQUIRE(!ADDRWAIT(fctx)); + if (fctx->totalqueries > DEFAULT_MAX_QUERIES) + fctx_done(fctx, DNS_R_SERVFAIL, __LINE__); + addrinfo = fctx_nextaddress(fctx); if (addrinfo == NULL) { /* @@ -3380,6 +3406,7 @@ fctx_start(isc_task_t *task, isc_event_t * Normal fctx startup. */ fctx->state = fetchstate_active; + fctx->totalqueries = 0; /* * Reset the control event for later use in shutting down * the fctx. @@ -3449,6 +3476,7 @@ fctx_join(fetchctx_t *fctx, isc_task_t * event->fetch = fetch; event->client = client; event->id = id; + event->qtotal = 0; dns_fixedname_init(&event->foundname); /* @@ -3485,7 +3513,8 @@ log_ns_ttl(fetchctx_t *fctx, const char static isc_result_t fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, dns_name_t *domain, dns_rdataset_t *nameservers, - unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp) + unsigned int options, unsigned int bucketnum, unsigned int depth, + fetchctx_t **fctxp) { fetchctx_t *fctx; isc_result_t result; @@ -3537,6 +3566,7 @@ fctx_create(dns_resolver_t *res, dns_nam fctx->state = fetchstate_init; fctx->want_shutdown = ISC_FALSE; fctx->cloned = ISC_FALSE; + fctx->depth = depth; ISC_LIST_INIT(fctx->queries); ISC_LIST_INIT(fctx->finds); ISC_LIST_INIT(fctx->altfinds); @@ -3555,6 +3585,7 @@ fctx_create(dns_resolver_t *res, dns_nam fctx->pending = 0; fctx->restarts = 0; fctx->querysent = 0; + fctx->totalqueries = 0; fctx->referrals = 0; TIME_NOW(&fctx->start); fctx->timeouts = 0; @@ -7731,6 +7762,7 @@ dns_resolver_create(dns_view_t *view, res->spillattimer = NULL; res->zero_no_soa_ttl = ISC_FALSE; res->query_timeout = DEFAULT_QUERY_TIMEOUT; + res->maxdepth = DEFAULT_RECURSION_DEPTH; res->nbuckets = ntasks; res->activebuckets = ntasks; res->buckets = isc_mem_get(view->mctx, @@ -8169,9 +8201,9 @@ dns_resolver_createfetch(dns_resolver_t dns_rdataset_t *sigrdataset, dns_fetch_t **fetchp) { - return (dns_resolver_createfetch2(res, name, type, domain, + return (dns_resolver_createfetch3(res, name, type, domain, nameservers, forwarders, NULL, 0, - options, task, action, arg, + options, 0, task, action, arg, rdataset, sigrdataset, fetchp)); } @@ -8187,6 +8219,25 @@ dns_resolver_createfetch2(dns_resolver_t dns_rdataset_t *sigrdataset, dns_fetch_t **fetchp) { + return (dns_resolver_createfetch3(res, name, type, domain, + nameservers, forwarders, client, id, + options, 0, task, action, arg, + rdataset, sigrdataset, fetchp)); +} + +isc_result_t +dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, + dns_rdatatype_t type, + dns_name_t *domain, dns_rdataset_t *nameservers, + dns_forwarders_t *forwarders, + isc_sockaddr_t *client, dns_messageid_t id, + unsigned int options, unsigned int depth, + isc_task_t *task, + isc_taskaction_t action, void *arg, + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp) +{ dns_fetch_t *fetch; fetchctx_t *fctx = NULL; isc_result_t result = ISC_R_SUCCESS; @@ -8273,11 +8324,12 @@ dns_resolver_createfetch2(dns_resolver_t if (fctx == NULL) { result = fctx_create(res, name, type, domain, nameservers, - options, bucketnum, &fctx); + options, bucketnum, depth, &fctx); if (result != ISC_R_SUCCESS) goto unlock; new_fctx = ISC_TRUE; - } + } else if (fctx->depth > depth) + fctx->depth = depth; result = fctx_join(fctx, task, client, id, action, arg, rdataset, sigrdataset, fetch); @@ -9049,3 +9101,15 @@ dns_resolver_settimeout(dns_resolver_t * resolver->query_timeout = seconds; } + +void +dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) { + REQUIRE(VALID_RESOLVER(resolver)); + resolver->maxdepth = maxdepth; +} + +unsigned int +dns_resolver_getmaxdepth(dns_resolver_t *resolver) { + REQUIRE(VALID_RESOLVER(resolver)); + return (resolver->maxdepth); +} Modified: stable/9/contrib/bind9/lib/isccfg/namedconf.c ============================================================================== --- stable/9/contrib/bind9/lib/isccfg/namedconf.c Wed Dec 10 08:26:53 2014 (r275668) +++ stable/9/contrib/bind9/lib/isccfg/namedconf.c Wed Dec 10 08:31:41 2014 (r275669) @@ -1419,6 +1419,7 @@ view_clauses[] = { { "max-cache-ttl", &cfg_type_uint32, 0 }, { "max-clients-per-query", &cfg_type_uint32, 0 }, { "max-ncache-ttl", &cfg_type_uint32, 0 }, + { "max-recursion-depth", &cfg_type_uint32, 0 }, { "max-udp-size", &cfg_type_uint32, 0 }, { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP }, { "minimal-responses", &cfg_type_boolean, 0 }, Modified: stable/9/contrib/file/elfclass.h ============================================================================== --- stable/9/contrib/file/elfclass.h Wed Dec 10 08:26:53 2014 (r275668) +++ stable/9/contrib/file/elfclass.h Wed Dec 10 08:31:41 2014 (r275669) @@ -35,10 +35,12 @@ switch (type) { #ifdef ELFCORE case ET_CORE: + phnum = elf_getu16(swap, elfhdr.e_phnum); + if (phnum > MAX_PHNUM) + return toomany(ms, "program", phnum); flags |= FLAGS_IS_CORE; if (dophn_core(ms, clazz, swap, fd, - (off_t)elf_getu(swap, elfhdr.e_phoff), - elf_getu16(swap, elfhdr.e_phnum), + (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, (size_t)elf_getu16(swap, elfhdr.e_phentsize), fsize, &flags) == -1) return -1; @@ -46,18 +48,24 @@ #endif case ET_EXEC: case ET_DYN: + phnum = elf_getu16(swap, elfhdr.e_phnum); + if (phnum > MAX_PHNUM) + return toomany(ms, "program", phnum); + shnum = elf_getu16(swap, elfhdr.e_shnum); + if (shnum > MAX_SHNUM) + return toomany(ms, "section", shnum); if (dophn_exec(ms, clazz, swap, fd, - (off_t)elf_getu(swap, elfhdr.e_phoff), - elf_getu16(swap, elfhdr.e_phnum), + (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, (size_t)elf_getu16(swap, elfhdr.e_phentsize), - fsize, &flags, elf_getu16(swap, elfhdr.e_shnum)) - == -1) + fsize, &flags, shnum) == -1) return -1; /*FALLTHROUGH*/ case ET_REL: + shnum = elf_getu16(swap, elfhdr.e_shnum); + if (shnum > MAX_SHNUM) + return toomany(ms, "section", shnum); if (doshn(ms, clazz, swap, fd, - (off_t)elf_getu(swap, elfhdr.e_shoff), - elf_getu16(swap, elfhdr.e_shnum), + (off_t)elf_getu(swap, elfhdr.e_shoff), shnum, (size_t)elf_getu16(swap, elfhdr.e_shentsize), fsize, &flags, elf_getu16(swap, elfhdr.e_machine)) == -1) return -1; Modified: stable/9/contrib/file/readelf.c ============================================================================== --- stable/9/contrib/file/readelf.c Wed Dec 10 08:26:53 2014 (r275668) +++ stable/9/contrib/file/readelf.c Wed Dec 10 08:31:41 2014 (r275669) @@ -60,6 +60,18 @@ private uint16_t getu16(int, uint16_t); private uint32_t getu32(int, uint32_t); private uint64_t getu64(int, uint64_t); +#define MAX_PHNUM 256 +#define MAX_SHNUM 1024 + +private int +toomany(struct magic_set *ms, const char *name, uint16_t num) +{ + if (file_printf(ms, ", too many %s header sections (%u)", name, num + ) == -1) + return -1; + return 0; +} + private uint16_t getu16(int swap, uint16_t value) { @@ -384,13 +396,13 @@ donote(struct magic_set *ms, void *vbuf, if (namesz & 0x80000000) { (void)file_printf(ms, ", bad note name size 0x%lx", (unsigned long)namesz); - return offset; + return 0; } if (descsz & 0x80000000) { (void)file_printf(ms, ", bad note description size 0x%lx", (unsigned long)descsz); - return offset; + return 0; } @@ -847,6 +859,7 @@ doshn(struct magic_set *ms, int clazz, i Elf32_Shdr sh32; Elf64_Shdr sh64; int stripped = 1; + size_t nbadcap = 0; void *nbuf; off_t noff, coff; uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */ @@ -919,6 +932,8 @@ doshn(struct magic_set *ms, int clazz, i free(nbuf); break; case SHT_SUNW_cap: + if (nbadcap > 5) + break; if (lseek(fd, (off_t)xsh_offset, SEEK_SET) == (off_t)-1) { file_badseek(ms); @@ -955,6 +970,8 @@ doshn(struct magic_set *ms, int clazz, i (unsigned long long)xcap_tag, (unsigned long long)xcap_val) == -1) return -1; + if (nbadcap++ > 2) + coff = xsh_size; break; } } @@ -1142,7 +1159,7 @@ file_tryelf(struct magic_set *ms, int fd int flags = 0; Elf32_Ehdr elf32hdr; Elf64_Ehdr elf64hdr; - uint16_t type; + uint16_t type, phnum, shnum; if (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) return 0; Modified: stable/9/contrib/file/softmagic.c ============================================================================== --- stable/9/contrib/file/softmagic.c Wed Dec 10 08:26:53 2014 (r275668) +++ stable/9/contrib/file/softmagic.c Wed Dec 10 08:31:41 2014 (r275669) @@ -61,6 +61,9 @@ private void cvt_32(union VALUETYPE *, c private void cvt_64(union VALUETYPE *, const struct magic *); #define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o))) + +#define MAX_RECURSION_LEVEL 10 + /* * softmagic - lookup one file in parsed, in-memory copy of database * Passed the name and FILE * of one file to be typed. @@ -1027,7 +1030,7 @@ mget(struct magic_set *ms, const unsigne uint32_t count = m->str_range; union VALUETYPE *p = &ms->ms_value; - if (recursion_level >= 20) { + if (recursion_level >= MAX_RECURSION_LEVEL) { file_error(ms, 0, "recursion nesting exceeded"); return -1; }