]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/beast: use strand executor for timeout timer to prevent concurrent socket access 67424/head
authorOguzhan Ozmen <oozmen@bloomberg.net>
Thu, 19 Feb 2026 01:42:54 +0000 (01:42 +0000)
committerOguzhan Ozmen <oozmen@bloomberg.net>
Thu, 19 Feb 2026 15:18:17 +0000 (15:18 +0000)
The timeout_timer in AsioFrontend::on_accept() was constructed with
context.get_executor(), which dispatches the timeout handler to the
raw io_context. Since each connection's coroutine runs on a strand
(via make_strand(context)), this allowed the timeout handler to
execute concurrently with the coroutine on a different thread.

When the timeout fires, timeout_handler calls socket.cancel() and
socket.shutdown() racing with the coroutine's async_read_header(),
async_write(), or async_read_some() on the same socket and buffer.
This can corrupt the flat_static_buffer's internal pointers, leading
to SIGSEGV in the Beast HTTP parser.

Fix by constructing the timeout_timer with yield.get_executor(),
which returns the coroutine's strand executor. This ensures the
timeout handler is serialized with the coroutine, preventing
concurrent access to the socket and buffer.

Fixes: https://tracker.ceph.com/issues/75031
Signed-off-by: Oguzhan Ozmen <oozmen@bloomberg.net>
src/rgw/rgw_asio_frontend.cc

index 4c0ab7f29528c31bdfcc64e2496c39c5bab7aa8b..19fe534b7a4dcdf37a9ca901eb15a9a9b21e0010 100644 (file)
@@ -1198,7 +1198,7 @@ void AsioFrontend::on_accept(Listener& l, tcp::socket stream)
         auto c = connections.add(*conn);
         // wrap the tcp stream in an ssl stream
         boost::asio::ssl::stream<tcp::socket&> stream{conn->socket, *ssl_ctx};
-        auto timeout = timeout_timer{context.get_executor(), request_timeout, conn};
+        auto timeout = timeout_timer{yield.get_executor(), request_timeout, conn};
         // do ssl handshake
         boost::system::error_code ec;
         timeout.start();
@@ -1231,7 +1231,7 @@ void AsioFrontend::on_accept(Listener& l, tcp::socket stream)
       [this, s=std::move(stream)] (boost::asio::yield_context yield) mutable {
         auto conn = boost::intrusive_ptr{new Connection(std::move(s))};
         auto c = connections.add(*conn);
-        auto timeout = timeout_timer{context.get_executor(), request_timeout, conn};
+        auto timeout = timeout_timer{yield.get_executor(), request_timeout, conn};
         boost::system::error_code ec;
         handle_connection(context, env, conn->socket, timeout, header_limit,
                           conn->buffer, false, pause_mutex, scheduler.get(),