diff --git a/src/impl/ltc/coin/rpc.cpp b/src/impl/ltc/coin/rpc.cpp index 777259302..2588436a8 100644 --- a/src/impl/ltc/coin/rpc.cpp +++ b/src/impl/ltc/coin/rpc.cpp @@ -132,6 +132,7 @@ void NodeRPC::sync_reconnect() std::string NodeRPC::Send(const std::string &request) { + std::lock_guard _rpc_lock(m_rpc_mutex); // Retry once after synchronous reconnect on write/read failure for (int attempt = 0; attempt < 2; ++attempt) { diff --git a/src/impl/ltc/coin/rpc.hpp b/src/impl/ltc/coin/rpc.hpp index d4f7b5c1f..df1f64e6c 100644 --- a/src/impl/ltc/coin/rpc.hpp +++ b/src/impl/ltc/coin/rpc.hpp @@ -5,6 +5,7 @@ #include "node_interface.hpp" #include +#include #include #include @@ -38,6 +39,11 @@ class NodeRPC : public jsonrpccxx::IClientConnector beast::tcp_stream m_stream; boost::asio::ip::tcp::resolver m_resolver; http::request m_http_request; + // Serializes Send(): m_http_request + m_stream are NOT thread-safe. The asio + // thread_pool worker (clean_tracker->think->score->getblockheader) and the main + // thread both drive Send() on this single shared client; without this lock T0's + // prepare_payload() frees the Content-Length field element mid-write on T8 -> UAF. + std::mutex m_rpc_mutex; std::unique_ptr m_auth; jsonrpccxx::JsonRpcClient m_client;