Package: unbound
Version: 1.4.18-1
Severity: normal
Tags: upstream patch

Unbound crashes under high query load (while doing DNSSEC validation)
if "num-threads" configuration setting is higher than 1.

A simple workaround is to reduce the amount of threads to 1 (which is
the default).

There is a gdb backtrace of the crash at:

https://unbound.net/pipermail/unbound-users/2012-October/002653.html

A detailed description of the problem is available at:

https://unbound.net/pipermail/unbound-users/2012-September/002571.html

There is a patch included at the end of that message. I am attaching
it also to this bug report.

The fix is committed in Unbound SVN repository at r2733. It will be
included in the next Unbound version.

I have filed also Ubuntu bug report at:

https://bugs.launchpad.net/ubuntu/+source/unbound/+bug/1070247


-- System Information:
Debian Release: wheezy/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 3.2.0-3-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages unbound depends on:
ii  adduser         3.113+nmu3
ii  libc6           2.13-35
ii  libevent-2.0-5  2.0.19-stable-3
ii  libgcc1         1:4.7.2-4
ii  libldns1        1.6.13-3
ii  libpython2.7    2.7.3-5
ii  libssl1.0.0     1.0.1c-4
ii  openssl         1.0.1c-4
ii  unbound-anchor  1.4.18-1

unbound recommends no packages.

unbound suggests no packages.

-- Configuration Files:
/etc/unbound/unbound.conf changed:
server:
    # The following line will configure unbound to perform cryptographic
    # DNSSEC validation using the root trust anchor.
    auto-trust-anchor-file: "/var/lib/unbound/root.key"
    num-threads: 2


-- no debconf information
Index: daemon/daemon.c
===================================================================
--- daemon/daemon.c	(revision 2732)
+++ daemon/daemon.c	(revision 2733)
@@ -209,6 +209,10 @@
 	comp_meth = (void*)SSL_COMP_get_compression_methods();
 #  endif
 	(void)SSL_library_init();
+#  if defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
+	if(!ub_openssl_lock_init())
+		fatal_exit("could not init openssl locks");
+#  endif
 #elif defined(HAVE_NSS)
 	if(NSS_NoDB_Init(NULL) != SECSuccess)
 		fatal_exit("could not init NSS");
@@ -568,6 +572,9 @@
 	ERR_remove_state(0);
 	ERR_free_strings();
 	RAND_cleanup();
+#  if defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
+	ub_openssl_lock_delete();
+#  endif
 #elif defined(HAVE_NSS)
 	NSS_Shutdown();
 #endif /* HAVE_SSL or HAVE_NSS */
Index: util/net_help.c
===================================================================
--- util/net_help.c	(revision 2732)
+++ util/net_help.c	(revision 2733)
@@ -725,3 +725,54 @@
 	return NULL;
 #endif
 }
+
+/** global lock list for openssl locks */
+static lock_basic_t *ub_openssl_locks = NULL;
+
+/** callback that gets thread id for openssl */
+static unsigned long
+ub_crypto_id_cb(void)
+{
+	return (unsigned long)ub_thread_self();
+}
+
+static void
+ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file),
+	int ATTR_UNUSED(line))
+{
+	if((mode&CRYPTO_LOCK)) {
+		lock_basic_lock(&ub_openssl_locks[type]);
+	} else {
+		lock_basic_unlock(&ub_openssl_locks[type]);
+	}
+}
+
+int ub_openssl_lock_init(void)
+{
+#ifdef OPENSSL_THREADS
+	size_t i;
+	ub_openssl_locks = (lock_basic_t*)malloc(
+		sizeof(lock_basic_t)*CRYPTO_num_locks());
+	if(!ub_openssl_locks)
+		return 0;
+	for(i=0; i<CRYPTO_num_locks(); i++) {
+		lock_basic_init(&ub_openssl_locks[i]);
+	}
+	CRYPTO_set_id_callback(&ub_crypto_id_cb);
+	CRYPTO_set_locking_callback(&ub_crypto_lock_cb);
+#endif /* OPENSSL_THREADS */
+	return 1;
+}
+
+void ub_openssl_lock_delete(void)
+{
+#ifdef OPENSSL_THREADS
+	size_t i;
+	if(!ub_openssl_locks)
+		return;
+	for(i=0; i<CRYPTO_num_locks(); i++) {
+		lock_basic_destroy(&ub_openssl_locks[i]);
+	}
+#endif /* OPENSSL_THREADS */
+}
+
Index: util/net_help.h
===================================================================
--- util/net_help.h	(revision 2732)
+++ util/net_help.h	(revision 2733)
@@ -369,4 +369,15 @@
  */
 void* outgoing_ssl_fd(void* sslctx, int fd);
 
+/**
+ * Initialize openssl locking for thread safety
+ * @return false on failure (alloc failure).
+ */
+int ub_openssl_lock_init(void);
+
+/**
+ * De-init the allocated openssl locks
+ */
+void ub_openssl_lock_delete(void);
+
 #endif /* NET_HELP_H */

Reply via email to