From 90560da5c35b71851fbea584e4afd0a5a5495540 Mon Sep 17 00:00:00 2001 From: Davide Beatrici Date: Fri, 23 Feb 2024 23:57:22 +0100 Subject: [PATCH] Connection: Fix unexpected server disconnection due to OpenSSL thread safety problems From the OpenSSL FAQ (https://www.openssl.org/docs/faq.html): "... an SSL connection cannot be used concurrently by multiple threads. This is true for most OpenSSL objects." --- src/Connection.cpp | 7 +++++++ src/Connection.hpp | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/src/Connection.cpp b/src/Connection.cpp index 88211d5..e5e5402 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -35,6 +35,8 @@ Connection::operator bool() const { } Code Connection::operator()(const Feedback &feedback, const std::function< bool() > halt) { + const auto guard = m_p->lock(); + if (!m_p->m_monitorIn.add(m_p->m_handle, true, false) || !m_p->m_monitorOut.add(m_p->m_handle, false, true)) { return Code::Failure; } @@ -87,6 +89,8 @@ Cert::Chain Connection::peerCert() const { } bool Connection::setCert(const Cert::Chain &cert, const Key &key) { + const auto guard = m_p->lock(); + return m_p->setCert(cert, key); } @@ -94,6 +98,7 @@ Code Connection::process(const bool wait, const std::function< bool() > halt) { using NetHeader = tcp::NetHeader; using Pack = tcp::Pack; + const auto guard = m_p->lock(); do { NetHeader header; auto code = m_p->read({ reinterpret_cast< std::byte * >(&header), sizeof(header) }, wait, halt); @@ -123,6 +128,8 @@ Code Connection::process(const bool wait, const std::function< bool() > halt) { } Code Connection::write(const BufViewConst data, const bool wait, const std::function< bool() > halt) { + const auto guard = m_p->lock(); + return m_p->write(data, wait, halt); } diff --git a/src/Connection.hpp b/src/Connection.hpp index e103f78..cbfc2aa 100644 --- a/src/Connection.hpp +++ b/src/Connection.hpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace mumble { class Connection::P : public SocketTLS { @@ -33,6 +34,10 @@ class Connection::P : public SocketTLS { mumble::Code handleState(const State state); private: + [[nodiscard]] std::lock_guard< std::recursive_mutex > lock() { + return std::lock_guard< std::recursive_mutex >(m_mutex); + } + mumble::Code read(BufView buf, const bool wait, const std::function< bool() > halt); mumble::Code write(BufViewConst buf, const bool wait, const std::function< bool() > halt); @@ -49,6 +54,7 @@ class Connection::P : public SocketTLS { Cert::Chain m_cert; uint32_t m_timeouts; std::atomic_flag m_closed; + std::recursive_mutex m_mutex; }; } // namespace mumble