From 6a620c243d177d3b3c1ce3d0b65942309a3b377b Mon Sep 17 00:00:00 2001 From: Yixin Jin Date: Wed, 15 Feb 2023 17:08:19 +0000 Subject: [PATCH] rgw: Fix segfault due to concurrent socket use at timeout This commit fixes a potential segfault risk when rgw timeout handler works on the socket in one thread while it is concurrently used by another. The details of the fix are: 1. Instead of calling socket close(), which resets descriptor_data in boost::asio socket and risks segfault due to concurrent use of the socket, the timeout handler now calls cancel() to abort all pending ops followed by shutdown() to disable the underlying transport. The eventual closure of the socket will be done in the socket destructor. 2. Expose the actual boost::asio socket via get_socket() from Connection so that the timeout handler can call cancel() and shutdown() on it, although the socket data member is already accessible. It allows future expansion that wants to hide the socket even though it renders the existing close() less useful. Fixes: https://tracker.ceph.com/issues/58670 Signed-off-by: Yixin Jin (cherry picked from commit 6d5988cbdab48705414e311217c61d3c798085d8) --- src/rgw/rgw_asio_frontend.cc | 2 ++ src/rgw/rgw_asio_frontend_timer.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rgw/rgw_asio_frontend.cc b/src/rgw/rgw_asio_frontend.cc index 532ae0183d18c..bf87075a79643 100644 --- a/src/rgw/rgw_asio_frontend.cc +++ b/src/rgw/rgw_asio_frontend.cc @@ -336,6 +336,8 @@ struct Connection : boost::intrusive::list_base_hook<>, void close(boost::system::error_code& ec) { socket.close(ec); } + + tcp_socket& get_socket() { return socket; } }; class ConnectionList { diff --git a/src/rgw/rgw_asio_frontend_timer.h b/src/rgw/rgw_asio_frontend_timer.h index b7d6a63b46f11..bc58790d62986 100644 --- a/src/rgw/rgw_asio_frontend_timer.h +++ b/src/rgw/rgw_asio_frontend_timer.h @@ -20,7 +20,8 @@ struct timeout_handler { void operator()(boost::system::error_code ec) { if (!ec) { // wait was not canceled boost::system::error_code ec_ignored; - stream->close(ec_ignored); + stream->get_socket().cancel(); + stream->get_socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec_ignored); } } }; -- 2.39.5