提交 7722606b 编写于 作者: D Daniel P. Berrangé

rpc: ensure thread safe initialization of SASL library

Neither the sasl_client_init or sasl_server_init methods are even
remotely threadsafe. They do a bunch of one-time initialization and
merely use a simple integer counter to avoid repeated work, not even
using atomic increment/reads on the counter. This can easily race in a
threaded program. Protect the calls using a virOnce initializer function
which is guaranteed threadsafe at least from libvirt's POV.

If the application using libvirt also uses another library that makes
use of SASL then the race still exists. It is impossible to fix that
fully except in SASL code itself.
Reviewed-by: NMichal Privoznik <mprivozn@redhat.com>
Signed-off-by: NDaniel P. Berrangé <berrange@redhat.com>
上级 120465f3
......@@ -77,22 +77,46 @@ VIR_ONCE_GLOBAL_INIT(virNetSASLContext);
VIR_WARNINGS_NO_DEPRECATED
#endif
virNetSASLContextPtr virNetSASLContextNewClient(void)
static int virNetSASLContextClientOnceInit(void)
{
virNetSASLContextPtr ctxt;
int err;
int err = sasl_client_init(NULL);
if (err != SASL_OK) {
virReportError(VIR_ERR_AUTH_FAILED,
_("failed to initialize SASL library: %d (%s)"),
err, sasl_errstring(err, NULL, NULL));
return -1;
}
return 0;
}
VIR_ONCE_GLOBAL_INIT(virNetSASLContextClient);
if (virNetSASLContextInitialize() < 0)
return NULL;
err = sasl_client_init(NULL);
static int virNetSASLContextServerOnceInit(void)
{
int err = sasl_server_init(NULL, "libvirt");
if (err != SASL_OK) {
virReportError(VIR_ERR_AUTH_FAILED,
_("failed to initialize SASL library: %d (%s)"),
err, sasl_errstring(err, NULL, NULL));
return NULL;
return -1;
}
return 0;
}
VIR_ONCE_GLOBAL_INIT(virNetSASLContextServer);
virNetSASLContextPtr virNetSASLContextNewClient(void)
{
virNetSASLContextPtr ctxt;
if (virNetSASLContextInitialize() < 0 ||
virNetSASLContextClientInitialize() < 0)
return NULL;
if (!(ctxt = virObjectLockableNew(virNetSASLContextClass)))
return NULL;
......@@ -102,19 +126,11 @@ virNetSASLContextPtr virNetSASLContextNewClient(void)
virNetSASLContextPtr virNetSASLContextNewServer(const char *const*usernameWhitelist)
{
virNetSASLContextPtr ctxt;
int err;
if (virNetSASLContextInitialize() < 0)
if (virNetSASLContextInitialize() < 0 ||
virNetSASLContextServerInitialize() < 0)
return NULL;
err = sasl_server_init(NULL, "libvirt");
if (err != SASL_OK) {
virReportError(VIR_ERR_AUTH_FAILED,
_("failed to initialize SASL library: %d (%s)"),
err, sasl_errstring(err, NULL, NULL));
return NULL;
}
if (!(ctxt = virObjectLockableNew(virNetSASLContextClass)))
return NULL;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册