aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXin LI <delphij@FreeBSD.org>2014-12-10 08:36:40 +0000
committerXin LI <delphij@FreeBSD.org>2014-12-10 08:36:40 +0000
commita2e5f6ff73d4de4a344ed0a55d718af6e696c851 (patch)
tree10ff56324da1984892c183e6d78c35e857046171
parent95694478dbec043d57a331f6deb9d4a8649bec20 (diff)
downloadsrc-a2e5f6ff73d4de4a344ed0a55d718af6e696c851.tar.gz
src-a2e5f6ff73d4de4a344ed0a55d718af6e696c851.zip
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 Approved by: so
Notes
Notes: svn path=/releng/9.3/; revision=275672
-rw-r--r--UPDATING8
-rw-r--r--contrib/bind9/CHANGES11
-rw-r--r--contrib/bind9/bin/named/config.c3
-rw-r--r--contrib/bind9/bin/named/query.c7
-rw-r--r--contrib/bind9/bin/named/server.c5
-rw-r--r--contrib/bind9/lib/dns/adb.c58
-rw-r--r--contrib/bind9/lib/dns/include/dns/adb.h8
-rw-r--r--contrib/bind9/lib/dns/include/dns/resolver.h25
-rw-r--r--contrib/bind9/lib/dns/resolver.c90
-rw-r--r--contrib/bind9/lib/isccfg/namedconf.c1
-rw-r--r--contrib/file/elfclass.h24
-rw-r--r--contrib/file/readelf.c23
-rw-r--r--contrib/file/softmagic.c5
-rw-r--r--sys/conf/newvers.sh2
14 files changed, 222 insertions, 48 deletions
diff --git a/UPDATING b/UPDATING
index 92d55bfba48d..c8551b875dac 100644
--- a/UPDATING
+++ b/UPDATING
@@ -11,6 +11,14 @@ handbook:
Items affecting the ports and packages system can be found in
/usr/ports/UPDATING. Please read that file before running portupgrade.
+20141210: p6 FreeBSD-SA-14:28.file
+ FreeBSD-SA-14:29.bind
+
+ Fix multiple vulnerabilities in file(1) and libmagic(3).
+ [SA-14:28]
+
+ Fix BIND remote denial of service vulnerability. [SA-14:29]
+
20141104: p5 FreeBSD-SA-14:25.setlogin
FreeBSD-SA-14:26.ftp
FreeBSD-EN-14:12.zfs
diff --git a/contrib/bind9/CHANGES b/contrib/bind9/CHANGES
index 00a0ffd0cc01..7981f7d10ed7 100644
--- a/contrib/bind9/CHANGES
+++ b/contrib/bind9/CHANGES
@@ -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 ---
diff --git a/contrib/bind9/bin/named/config.c b/contrib/bind9/bin/named/config.c
index 278272082ae2..5ee8c4ee6619 100644
--- a/contrib/bind9/bin/named/config.c
+++ b/contrib/bind9/bin/named/config.c
@@ -15,8 +15,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: config.c,v 1.123 2012/01/06 23:46:41 tbox Exp $ */
-
/*! \file */
#include <config.h>
@@ -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\
diff --git a/contrib/bind9/bin/named/query.c b/contrib/bind9/bin/named/query.c
index c357f83ee427..534b2949f76a 100644
--- a/contrib/bind9/bin/named/query.c
+++ b/contrib/bind9/bin/named/query.c
@@ -3872,12 +3872,11 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
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);
diff --git a/contrib/bind9/bin/named/server.c b/contrib/bind9/bin/named/server.c
index 77a4e4406976..f65d1cea2239 100644
--- a/contrib/bind9/bin/named/server.c
+++ b/contrib/bind9/bin/named/server.c
@@ -3141,6 +3141,11 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
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);
diff --git a/contrib/bind9/lib/dns/adb.c b/contrib/bind9/lib/dns/adb.c
index 10d51bc44143..a4d5b0cedd03 100644
--- a/contrib/bind9/lib/dns/adb.c
+++ b/contrib/bind9/lib/dns/adb.c
@@ -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_hierarchy(isc_mutex_t *, isc_mutex_t *);
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_adbname_t *);
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_eventtype_t ev) {
* 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, isc_eventtype_t evtype,
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_task_t *task, isc_taskaction_t action,
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_task_t *task, isc_taskaction_t action,
* 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_task_t *task, isc_taskaction_t action,
* 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_event_t *ev) {
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_event_t *ev) {
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_event_t *ev) {
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_event_t *ev) {
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;
}
-
- result = dns_resolver_createfetch(adb->view->resolver, &adbname->name,
- type, name, nameservers, NULL,
- options, adb->task, fetch_callback,
- adbname, &fetch->rdataset, NULL,
- &fetch->fetch);
+ fetch->depth = depth;
+
+ 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;
diff --git a/contrib/bind9/lib/dns/include/dns/adb.h b/contrib/bind9/lib/dns/include/dns/adb.h
index a5a312406aff..cc85646e7889 100644
--- a/contrib/bind9/lib/dns/include/dns/adb.h
+++ b/contrib/bind9/lib/dns/include/dns/adb.h
@@ -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_task_t *task, isc_taskaction_t action,
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
diff --git a/contrib/bind9/lib/dns/include/dns/resolver.h b/contrib/bind9/lib/dns/include/dns/resolver.h
index 095269ea2dd2..4c5026af4e05 100644
--- a/contrib/bind9/lib/dns/include/dns/resolver.h
+++ b/contrib/bind9/lib/dns/include/dns/resolver.h
@@ -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 *res, dns_name_t *name,
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_t *resolver, FILE *fp);
* \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 */
diff --git a/contrib/bind9/lib/dns/resolver.c b/contrib/bind9/lib/dns/resolver.c
index 2e60cd84cca2..894fbea7922c 100644
--- a/contrib/bind9/lib/dns/resolver.c
+++ b/contrib/bind9/lib/dns/resolver.c
@@ -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_result_t result, int line) {
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_adbaddrinfo_t *addrinfo,
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_event_t *event) {
*/
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 *name, in_port_t port,
* 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_boolean_t badcache) {
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 retrying, isc_boolean_t badcache) {
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 *event) {
* 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 *task, isc_sockaddr_t *client,
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 *where) {
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_name_t *name, dns_rdatatype_t type,
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_name_t *name, dns_rdatatype_t type,
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 *res, dns_name_t *name,
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 *res, dns_name_t *name,
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 *res, dns_name_t *name,
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, unsigned int seconds) {
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);
+}
diff --git a/contrib/bind9/lib/isccfg/namedconf.c b/contrib/bind9/lib/isccfg/namedconf.c
index f11e2938e861..a65f6f7e9d0e 100644
--- a/contrib/bind9/lib/isccfg/namedconf.c
+++ b/contrib/bind9/lib/isccfg/namedconf.c
@@ -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 },
diff --git a/contrib/file/elfclass.h b/contrib/file/elfclass.h
index 2e7741b3fc00..a3e3969d490e 100644
--- a/contrib/file/elfclass.h
+++ b/contrib/file/elfclass.h
@@ -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;
diff --git a/contrib/file/readelf.c b/contrib/file/readelf.c
index 8b141e12d405..85d28a31bcdd 100644
--- a/contrib/file/readelf.c
+++ b/contrib/file/readelf.c
@@ -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, size_t offset, size_t size,
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, int swap, int fd, off_t off, int num,
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, int swap, int fd, off_t off, int num,
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, int swap, int fd, off_t off, int num,
(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, const unsigned char *buf,
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;
diff --git a/contrib/file/softmagic.c b/contrib/file/softmagic.c
index 2afd9679cee6..44c8a06d893a 100644
--- a/contrib/file/softmagic.c
+++ b/contrib/file/softmagic.c
@@ -61,6 +61,9 @@ private void cvt_32(union VALUETYPE *, const struct magic *);
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 unsigned char *s,
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;
}
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index 6e1db903a958..93f05869eaed 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -32,7 +32,7 @@
TYPE="FreeBSD"
REVISION="9.3"
-BRANCH="RELEASE-p5"
+BRANCH="RELEASE-p6"
if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
BRANCH=${BRANCH_OVERRIDE}
fi