summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2018-05-12 11:55:17 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2018-05-12 11:55:17 +0000
commita6c5280ea59f940be13fd6eb0f94ab8360d3d6c9 (patch)
treecbe088761a83cf2025bbdf36e1574f38c3e988f5 /daemon
parent8c2647a7dc721c8e5349bd194b8e8e178412057e (diff)
Notes
Diffstat (limited to 'daemon')
-rw-r--r--daemon/daemon.c9
-rw-r--r--daemon/remote.c85
-rw-r--r--daemon/stats.c64
-rw-r--r--daemon/unbound.c28
-rw-r--r--daemon/worker.c20
5 files changed, 136 insertions, 70 deletions
diff --git a/daemon/daemon.c b/daemon/daemon.c
index dad9f86b344e5..7411fabe75736 100644
--- a/daemon/daemon.c
+++ b/daemon/daemon.c
@@ -221,7 +221,9 @@ daemon_init(void)
# ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
ERR_load_crypto_strings();
# endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
ERR_load_SSL_strings();
+#endif
# ifdef USE_GOST
(void)sldns_key_EVP_load_gost_id();
# endif
@@ -239,7 +241,7 @@ daemon_init(void)
# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
# else
- (void)OPENSSL_init_ssl(0, NULL);
+ (void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
# endif
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
if(!ub_openssl_lock_init())
@@ -421,8 +423,8 @@ daemon_create_workers(struct daemon* daemon)
daemon->rand = ub_initstate(seed, NULL);
if(!daemon->rand)
fatal_exit("could not init random generator");
+ hash_set_raninit((uint32_t)ub_random(daemon->rand));
}
- hash_set_raninit((uint32_t)ub_random(daemon->rand));
shufport = (int*)calloc(65536, sizeof(int));
if(!shufport)
fatal_exit("out of memory during daemon init");
@@ -691,6 +693,9 @@ daemon_cleanup(struct daemon* daemon)
#ifdef USE_DNSTAP
dt_delete(daemon->dtenv);
#endif
+#ifdef USE_DNSCRYPT
+ dnsc_delete(daemon->dnscenv);
+#endif
daemon->cfg = NULL;
}
diff --git a/daemon/remote.c b/daemon/remote.c
index bb41cc5df2dbb..243d94c49aa16 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -229,42 +229,10 @@ daemon_remote_create(struct config_file* cfg)
free(rc);
return NULL;
}
- /* no SSLv2, SSLv3 because has defects */
- if((SSL_CTX_set_options(rc->ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
- != SSL_OP_NO_SSLv2){
- log_crypto_err("could not set SSL_OP_NO_SSLv2");
+ if(!listen_sslctx_setup(rc->ctx)) {
daemon_remote_delete(rc);
return NULL;
}
- if((SSL_CTX_set_options(rc->ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
- != SSL_OP_NO_SSLv3){
- log_crypto_err("could not set SSL_OP_NO_SSLv3");
- daemon_remote_delete(rc);
- return NULL;
- }
-#if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1)
- /* if we have tls 1.1 disable 1.0 */
- if((SSL_CTX_set_options(rc->ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1)
- != SSL_OP_NO_TLSv1){
- log_crypto_err("could not set SSL_OP_NO_TLSv1");
- daemon_remote_delete(rc);
- return NULL;
- }
-#endif
-#if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2)
- /* if we have tls 1.2 disable 1.1 */
- if((SSL_CTX_set_options(rc->ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1)
- != SSL_OP_NO_TLSv1_1){
- log_crypto_err("could not set SSL_OP_NO_TLSv1_1");
- daemon_remote_delete(rc);
- return NULL;
- }
-#endif
-#if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA)
- /* if we have sha256, set the cipher list to have no known vulns */
- if(!SSL_CTX_set_cipher_list(rc->ctx, "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"))
- log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list");
-#endif
if (cfg->remote_control_use_cert == 0) {
/* No certificates are requested */
@@ -314,23 +282,7 @@ daemon_remote_create(struct config_file* cfg)
log_crypto_err("Error in SSL_CTX check_private_key");
goto setup_error;
}
-#if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
- if(!SSL_CTX_set_ecdh_auto(rc->ctx,1)) {
- log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE");
- }
-#elif defined(USE_ECDSA)
- if(1) {
- EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
- if (!ecdh) {
- log_crypto_err("could not find p256, not enabling ECDHE");
- } else {
- if (1 != SSL_CTX_set_tmp_ecdh (rc->ctx, ecdh)) {
- log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE");
- }
- EC_KEY_free (ecdh);
- }
- }
-#endif
+ listen_sslctx_setup_2(rc->ctx);
if(!SSL_CTX_load_verify_locations(rc->ctx, s_cert, NULL)) {
log_crypto_err("Error setting up SSL_CTX verify locations");
setup_error:
@@ -415,7 +367,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
if (cfg->username && cfg->username[0] &&
cfg_uid != (uid_t)-1) {
if(chown(ip, cfg_uid, cfg_gid) == -1)
- log_err("cannot chown %u.%u %s: %s",
+ verbose(VERB_QUERY, "cannot chown %u.%u %s: %s",
(unsigned)cfg_uid, (unsigned)cfg_gid,
ip, strerror(errno));
}
@@ -841,7 +793,7 @@ print_stats(SSL* ssl, const char* nm, struct ub_stats_info* s)
static int
print_thread_stats(SSL* ssl, int i, struct ub_stats_info* s)
{
- char nm[16];
+ char nm[32];
snprintf(nm, sizeof(nm), "thread%d", i);
nm[sizeof(nm)-1]=0;
return print_stats(ssl, nm, s);
@@ -873,6 +825,9 @@ print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon)
#ifdef USE_IPSECMOD
size_t ipsecmod = 0;
#endif /* USE_IPSECMOD */
+#ifdef USE_DNSCRYPT
+ size_t dnscrypt_shared_secret = 0;
+#endif /* USE_DNSCRYPT */
msg = slabhash_get_mem(daemon->env->msg_cache);
rrset = slabhash_get_mem(&daemon->env->rrset_cache->table);
val = mod_get_mem(&worker->env, "validator");
@@ -884,6 +839,12 @@ print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon)
#ifdef USE_IPSECMOD
ipsecmod = mod_get_mem(&worker->env, "ipsecmod");
#endif /* USE_IPSECMOD */
+#ifdef USE_DNSCRYPT
+ if(daemon->dnscenv) {
+ dnscrypt_shared_secret = slabhash_get_mem(
+ daemon->dnscenv->shared_secrets_cache);
+ }
+#endif /* USE_DNSCRYPT */
if(!print_longnum(ssl, "mem.cache.rrset"SQ, rrset))
return 0;
@@ -903,6 +864,11 @@ print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon)
if(!print_longnum(ssl, "mem.mod.ipsecmod"SQ, ipsecmod))
return 0;
#endif /* USE_IPSECMOD */
+#ifdef USE_DNSCRYPT
+ if(!print_longnum(ssl, "mem.cache.dnscrypt_shared_secret"SQ,
+ dnscrypt_shared_secret))
+ return 0;
+#endif /* USE_DNSCRYPT */
return 1;
}
@@ -1065,6 +1031,9 @@ print_ext(SSL* ssl, struct ub_stats_info* s)
if(!ssl_printf(ssl, "num.answer.rcode.nodata"SQ"%lu\n",
(unsigned long)s->svr.ans_rcode_nodata)) return 0;
}
+ /* iteration */
+ if(!ssl_printf(ssl, "num.query.ratelimited"SQ"%lu\n",
+ (unsigned long)s->svr.queries_ratelimited)) return 0;
/* validation */
if(!ssl_printf(ssl, "num.answer.secure"SQ"%lu\n",
(unsigned long)s->svr.ans_secure)) return 0;
@@ -1086,6 +1055,12 @@ print_ext(SSL* ssl, struct ub_stats_info* s)
(unsigned)s->svr.infra_cache_count)) return 0;
if(!ssl_printf(ssl, "key.cache.count"SQ"%u\n",
(unsigned)s->svr.key_cache_count)) return 0;
+#ifdef USE_DNSCRYPT
+ if(!ssl_printf(ssl, "dnscrypt_shared_secret.cache.count"SQ"%u\n",
+ (unsigned)s->svr.shared_secret_cache_count)) return 0;
+ if(!ssl_printf(ssl, "num.query.dnscrypt.shared_secret.cachemiss"SQ"%lu\n",
+ (unsigned long)s->svr.num_query_dnscrypt_secret_missed_cache)) return 0;
+#endif /* USE_DNSCRYPT */
return 1;
}
@@ -2389,10 +2364,16 @@ dump_infra_host(struct lruhash_entry* e, void* arg)
struct infra_data* d = (struct infra_data*)e->data;
char ip_str[1024];
char name[257];
+ int port;
if(a->ssl_failed)
return;
addr_to_str(&k->addr, k->addrlen, ip_str, sizeof(ip_str));
dname_str(k->zonename, name);
+ port = (int)ntohs(((struct sockaddr_in*)&k->addr)->sin_port);
+ if(port != UNBOUND_DNS_PORT) {
+ snprintf(ip_str+strlen(ip_str), sizeof(ip_str)-strlen(ip_str),
+ "@%d", port);
+ }
/* skip expired stuff (only backed off) */
if(d->ttl < a->now) {
if(d->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
diff --git a/daemon/stats.c b/daemon/stats.c
index 599f39bcddda0..1058556be7c26 100644
--- a/daemon/stats.c
+++ b/daemon/stats.c
@@ -56,6 +56,7 @@
#include "util/timehist.h"
#include "util/net_help.h"
#include "validator/validator.h"
+#include "iterator/iterator.h"
#include "sldns/sbuffer.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
@@ -123,7 +124,7 @@ void server_stats_log(struct ub_server_stats* stats, struct worker* worker,
/** get rrsets bogus number from validator */
static size_t
-get_rrset_bogus(struct worker* worker)
+get_rrset_bogus(struct worker* worker, int reset)
{
int m = modstack_find(&worker->env.mesh->mods, "validator");
struct val_env* ve;
@@ -133,12 +134,48 @@ get_rrset_bogus(struct worker* worker)
ve = (struct val_env*)worker->env.modinfo[m];
lock_basic_lock(&ve->bogus_lock);
r = ve->num_rrset_bogus;
- if(!worker->env.cfg->stat_cumulative)
+ if(reset && !worker->env.cfg->stat_cumulative)
ve->num_rrset_bogus = 0;
lock_basic_unlock(&ve->bogus_lock);
return r;
}
+/** get number of ratelimited queries from iterator */
+static size_t
+get_queries_ratelimit(struct worker* worker, int reset)
+{
+ int m = modstack_find(&worker->env.mesh->mods, "iterator");
+ struct iter_env* ie;
+ size_t r;
+ if(m == -1)
+ return 0;
+ ie = (struct iter_env*)worker->env.modinfo[m];
+ lock_basic_lock(&ie->queries_ratelimit_lock);
+ r = ie->num_queries_ratelimited;
+ if(reset && !worker->env.cfg->stat_cumulative)
+ ie->num_queries_ratelimited = 0;
+ lock_basic_unlock(&ie->queries_ratelimit_lock);
+ return r;
+}
+
+#ifdef USE_DNSCRYPT
+/** get the number of shared secret cache miss */
+static size_t
+get_dnscrypt_cache_miss(struct worker* worker, int reset)
+{
+ size_t r;
+ struct dnsc_env* de = worker->daemon->dnscenv;
+ if(!de) return 0;
+
+ lock_basic_lock(&de->shared_secrets_cache_lock);
+ r = de->num_query_dnscrypt_secret_missed_cache;
+ if(reset && !worker->env.cfg->stat_cumulative)
+ de->num_query_dnscrypt_secret_missed_cache = 0;
+ lock_basic_unlock(&de->shared_secrets_cache_lock);
+ return r;
+}
+#endif /* USE_DNSCRYPT */
+
void
server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
{
@@ -169,7 +206,10 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
s->svr.qtcp_outgoing = (long long)worker->back->num_tcp_outgoing;
/* get and reset validator rrset bogus number */
- s->svr.rrset_bogus = (long long)get_rrset_bogus(worker);
+ s->svr.rrset_bogus = (long long)get_rrset_bogus(worker, reset);
+
+ /* get and reset iterator query ratelimit number */
+ s->svr.queries_ratelimited = (long long)get_queries_ratelimit(worker, reset);
/* get cache sizes */
s->svr.msg_cache_count = (long long)count_slabhash_entries(worker->env.msg_cache);
@@ -179,6 +219,21 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
s->svr.key_cache_count = (long long)count_slabhash_entries(worker->env.key_cache->slab);
else s->svr.key_cache_count = 0;
+#ifdef USE_DNSCRYPT
+ if(worker->daemon->dnscenv) {
+ s->svr.num_query_dnscrypt_secret_missed_cache =
+ (long long)get_dnscrypt_cache_miss(worker, reset);
+ s->svr.shared_secret_cache_count = (long long)count_slabhash_entries(
+ worker->daemon->dnscenv->shared_secrets_cache);
+ } else {
+ s->svr.num_query_dnscrypt_secret_missed_cache = 0;
+ s->svr.shared_secret_cache_count = 0;
+ }
+#else
+ s->svr.num_query_dnscrypt_secret_missed_cache = 0;
+ s->svr.shared_secret_cache_count = 0;
+#endif /* USE_DNSCRYPT */
+
/* get tcp accept usage */
s->svr.tcp_accept_usage = 0;
for(lp = worker->front->cps; lp; lp = lp->next) {
@@ -240,7 +295,7 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
a->svr.num_query_dnscrypt_cleartext;
total->svr.num_query_dnscrypt_crypted_malformed += \
a->svr.num_query_dnscrypt_crypted_malformed;
-#endif
+#endif /* USE_DNSCRYPT */
/* the max size reached is upped to higher of both */
if(a->svr.max_query_list_size > total->svr.max_query_list_size)
total->svr.max_query_list_size = a->svr.max_query_list_size;
@@ -266,7 +321,6 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
total->svr.zero_ttl_responses += a->svr.zero_ttl_responses;
total->svr.ans_secure += a->svr.ans_secure;
total->svr.ans_bogus += a->svr.ans_bogus;
- total->svr.rrset_bogus += a->svr.rrset_bogus;
total->svr.unwanted_replies += a->svr.unwanted_replies;
total->svr.unwanted_queries += a->svr.unwanted_queries;
total->svr.tcp_accept_usage += a->svr.tcp_accept_usage;
diff --git a/daemon/unbound.c b/daemon/unbound.c
index ba7337d8907ad..070a824d67343 100644
--- a/daemon/unbound.c
+++ b/daemon/unbound.c
@@ -128,6 +128,9 @@ static void usage(void)
for(m = module_list_avail(); *m; m++)
printf(" %s", *m);
printf("\n");
+#ifdef USE_DNSCRYPT
+ printf("DNSCrypt feature available\n");
+#endif
printf("BSD licensed, see LICENSE in source package for details.\n");
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
ub_event_base_free(base);
@@ -400,7 +403,7 @@ detach(void)
/** daemonize, drop user priviliges and chroot if needed */
static void
perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
- const char** cfgfile)
+ const char** cfgfile, int need_pidfile)
{
#ifdef HAVE_KILL
int pidinchroot;
@@ -444,13 +447,13 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
#ifdef HAVE_KILL
/* true if pidfile is inside chrootdir, or nochroot */
- pidinchroot = !(cfg->chrootdir && cfg->chrootdir[0]) ||
+ pidinchroot = need_pidfile && (!(cfg->chrootdir && cfg->chrootdir[0]) ||
(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(cfg->pidfile, cfg->chrootdir,
- strlen(cfg->chrootdir))==0);
+ strlen(cfg->chrootdir))==0));
/* check old pid file before forking */
- if(cfg->pidfile && cfg->pidfile[0]) {
+ if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
/* calculate position of pidfile */
if(cfg->pidfile[0] == '/')
daemon->pidfile = strdup(cfg->pidfile);
@@ -469,7 +472,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
/* write new pidfile (while still root, so can be outside chroot) */
#ifdef HAVE_KILL
- if(cfg->pidfile && cfg->pidfile[0]) {
+ if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
writepid(daemon->pidfile, getpid());
if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 &&
pidinchroot) {
@@ -484,6 +487,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
}
#else
(void)daemon;
+ (void)need_pidfile;
#endif /* HAVE_KILL */
/* Set user context */
@@ -600,9 +604,10 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
* These increase verbosity as specified in the config file.
* @param debug_mode: if set, do not daemonize.
* @param log_default_identity: Default identity to report in logs
+ * @param need_pidfile: if false, no pidfile is checked or created.
*/
static void
-run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* log_default_identity)
+run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* log_default_identity, int need_pidfile)
{
struct config_file* cfg = NULL;
struct daemon* daemon = NULL;
@@ -632,7 +637,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char*
if(!daemon_open_shared_ports(daemon))
fatal_exit("could not open ports");
if(!done_setup) {
- perform_setup(daemon, cfg, debug_mode, &cfgfile);
+ perform_setup(daemon, cfg, debug_mode, &cfgfile, need_pidfile);
done_setup = 1;
} else {
/* reopen log after HUP to facilitate log rotation */
@@ -682,6 +687,8 @@ main(int argc, char* argv[])
const char* log_ident_default;
int cmdline_verbose = 0;
int debug_mode = 0;
+ int need_pidfile = 1;
+
#ifdef UB_ON_WINDOWS
int cmdline_cfg = 0;
#endif
@@ -690,7 +697,7 @@ main(int argc, char* argv[])
log_ident_default = strrchr(argv[0],'/')?strrchr(argv[0],'/')+1:argv[0];
log_ident_set(log_ident_default);
/* parse the options */
- while( (c=getopt(argc, argv, "c:dhvw:")) != -1) {
+ while( (c=getopt(argc, argv, "c:dhpvw:")) != -1) {
switch(c) {
case 'c':
cfgfile = optarg;
@@ -702,6 +709,9 @@ main(int argc, char* argv[])
cmdline_verbose++;
verbosity++;
break;
+ case 'p':
+ need_pidfile = 0;
+ break;
case 'd':
debug_mode++;
break;
@@ -732,7 +742,7 @@ main(int argc, char* argv[])
return 1;
}
- run_daemon(cfgfile, cmdline_verbose, debug_mode, log_ident_default);
+ run_daemon(cfgfile, cmdline_verbose, debug_mode, log_ident_default, need_pidfile);
log_init(NULL, 0, NULL); /* close logfile */
return 0;
}
diff --git a/daemon/worker.c b/daemon/worker.c
index 2c4cf5ba6c0a1..683f93169117d 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -1009,6 +1009,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
struct query_info* lookup_qinfo = &qinfo;
struct query_info qinfo_tmp; /* placeholdoer for lookup_qinfo */
struct respip_client_info* cinfo = NULL, cinfo_tmp;
+ memset(&qinfo, 0, sizeof(qinfo));
if(error != NETEVENT_NOERROR) {
/* some bad tcp query DNS formats give these error calls */
@@ -1111,6 +1112,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
if(!query_info_parse(&qinfo, c->buffer)) {
verbose(VERB_ALGO, "worker parse request: formerror.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
+ memset(&qinfo, 0, sizeof(qinfo)); /* zero qinfo.qname */
if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) {
comm_point_drop_reply(repinfo);
return 0;
@@ -1355,6 +1357,10 @@ lookup_cache:
lock_rw_unlock(&e->lock);
regional_free_all(worker->scratchpad);
goto send_reply;
+ } else {
+ /* Note that we've already released the
+ * lock if we're here after prefetch. */
+ lock_rw_unlock(&e->lock);
}
/* We've found a partial reply ending with an
* alias. Replace the lookup qinfo for the
@@ -1362,7 +1368,6 @@ lookup_cache:
* (possibly) complete the reply. As we're
* passing the "base" reply, there will be no
* more alias chasing. */
- lock_rw_unlock(&e->lock);
memset(&qinfo_tmp, 0, sizeof(qinfo_tmp));
get_cname_target(alias_rrset, &qinfo_tmp.qname,
&qinfo_tmp.qname_len);
@@ -1669,7 +1674,17 @@ worker_init(struct worker* worker, struct config_file *cfg,
worker->env.send_query = &worker_send_query;
worker->env.alloc = &worker->alloc;
worker->env.rnd = worker->rndstate;
- worker->env.scratch = worker->scratchpad;
+ /* If case prefetch is triggered, the corresponding mesh will clear
+ * the scratchpad for the module env in the middle of request handling.
+ * It would be prone to a use-after-free kind of bug, so we avoid
+ * sharing it with worker's own scratchpad at the cost of having
+ * one more pad per worker. */
+ worker->env.scratch = regional_create_custom(cfg->msg_buffer_size);
+ if(!worker->env.scratch) {
+ log_err("malloc failure");
+ worker_delete(worker);
+ return 0;
+ }
worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env);
worker->env.detach_subs = &mesh_detach_subs;
worker->env.attach_sub = &mesh_attach_sub;
@@ -1758,6 +1773,7 @@ worker_delete(struct worker* worker)
comm_base_delete(worker->base);
ub_randfree(worker->rndstate);
alloc_clear(&worker->alloc);
+ regional_destroy(worker->env.scratch);
regional_destroy(worker->scratchpad);
free(worker);
}