Even though we are not using gcrypt directly in any libvirt code,
it turns out that we are responsible for initializing its thread
support, since its used by gnutls. This really sucks in terms of
library API encapsulation. It is also a little annoying if libvirt
is used within an app that already uses gnutls/gcrypt, because
there is no checking in gcrypt to see if threading ops are already
set, so our call would override any pre-existing initialization,
and an apps own call would override us.
The only other option I see is to punt on the whole problem and
declare apps are responsible for initializing gcrypt, but then
this sucks too because it means apps have to presume we're built
with gnutls, and not nss - not that we support nss currently.
This bug only really impacts the libvirt client if using multiple
virConnectPtr objects from separate threads with a TLS based URI.
The server isn't impacted because all TLS I/O is done from the
single I/O thread, and not any of the RPC workers.
Daniel P. Berrange (1):
Initialize gcrypt threading
src/remote_internal.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 43 insertions(+), 0 deletions(-)
Show replies by date
* src/remote_internal.c: Register thread functions for gcrypt
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/remote_internal.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/src/remote_internal.c b/src/remote_internal.c
index f20ed6e..65dee25 100644
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -59,6 +59,7 @@
#include <rpc/types.h>
#include <rpc/xdr.h>
+#include <gcrypt.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include "gnutls_1_0_compat.h"
@@ -1065,6 +1066,46 @@ check_cert_file (virConnectPtr conn, const char *type, const char
*file)
return 0;
}
+static int remote_mutex_init (void **priv)
+{ \
+ virMutexPtr lock = NULL;
+
+ if (VIR_ALLOC(lock) < 0)
+ return ENOMEM;
+
+ if (virMutexInit(lock) < 0)
+ return errno;
+
+ *priv = lock;
+ return 0;
+}
+
+static int remote_mutex_destroy (void **lock)
+{
+ virMutexDestroy(*(virMutexPtr *)lock);
+ return 0;
+}
+
+static int remote_mutex_lock (void **lock)
+{
+ virMutexLock(*(virMutexPtr *)lock);
+ return 0;
+}
+static int remote_mutex_unlock (void **lock)
+{
+ virMutexUnlock(*(virMutexPtr *)lock);
+ return 0;
+}
+
+static struct gcry_thread_cbs remote_thread_cbs = {
+ (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
+ NULL,
+ remote_mutex_init,
+ remote_mutex_destroy,
+ remote_mutex_lock,
+ remote_mutex_unlock,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
static int
initialise_gnutls (virConnectPtr conn)
@@ -1074,6 +1115,8 @@ initialise_gnutls (virConnectPtr conn)
if (initialised) return 0;
+ gcry_control(GCRYCTL_SET_THREAD_CBS, &remote_thread_cbs);
+ gcry_check_version(NULL);
gnutls_global_init ();
/* X509 stuff */
--
1.6.2.5