Author: aokblast
Date: 2026-07-13T02:43:35Z
New Revision: 461f0b699c8dbcafaec0e4b2d171d42ee05f6999

URL: 
https://github.com/llvm/llvm-project/commit/461f0b699c8dbcafaec0e4b2d171d42ee05f6999
DIFF: 
https://github.com/llvm/llvm-project/commit/461f0b699c8dbcafaec0e4b2d171d42ee05f6999.diff

LOG: [LLDB] Fix use-after-free destroying a Binder from its OnClosed handler 
(#209019)

transport::Binder::OnClosed() holds m_mutex (a recursive_mutex) while
invoking m_disconnect_handler. In the MCP server, that handler removes
the disconnected client, which owns the transport and therefore the
Binder itself. As a result, the Binder -- and its m_mutex -- are
destroyed while the scoped_lock in OnClosed still holds the lock.

This is a use-after-free everywhere, as the lock guard later unlocks
freed memory.

Move the disconnect handler out of the critical section and release the
lock before invoking it, so the Binder can be safely destroyed without
holding or destroying a locked mutex.

Added: 
    

Modified: 
    lldb/include/lldb/Host/JSONTransport.h

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Host/JSONTransport.h 
b/lldb/include/lldb/Host/JSONTransport.h
index 87adbbc04eeda..d3c6e8e101ad5 100644
--- a/lldb/include/lldb/Host/JSONTransport.h
+++ b/lldb/include/lldb/Host/JSONTransport.h
@@ -587,9 +587,18 @@ class Binder : public JSONTransport<Proto>::MessageHandler 
{
   }
 
   void OnClosed() override {
-    std::scoped_lock<std::recursive_mutex> guard(m_mutex);
-    if (m_disconnect_handler)
-      m_disconnect_handler();
+    // The disconnect handler may destroy this Binder -- e.g. the server
+    // removes the disconnected client, which owns the transport and, with it,
+    // this handler.  Move the handler out and release the lock before invoking
+    // it, so we neither run the teardown while holding m_mutex nor destroy a
+    // still-locked mutex.
+    Callback<void()> disconnect_handler;
+    {
+      std::scoped_lock<std::recursive_mutex> guard(m_mutex);
+      disconnect_handler = std::move(m_disconnect_handler);
+    }
+    if (disconnect_handler)
+      disconnect_handler();
   }
 
   /// Fails every in-flight outgoing request, invoking its reply with an error.


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to