From: Yixin Jin Date: Wed, 15 Feb 2023 17:08:19 +0000 (+0000) Subject: rgw: Fix segfault due to concurrent socket use at timeout X-Git-Tag: v18.1.0~354^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=6d5988cbdab48705414e311217c61d3c798085d8;p=ceph-ci.git 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 --- diff --git a/src/rgw/rgw_asio_frontend.cc b/src/rgw/rgw_asio_frontend.cc index 000a0bc6a9f..c444090192e 100644 --- a/src/rgw/rgw_asio_frontend.cc +++ b/src/rgw/rgw_asio_frontend.cc @@ -338,6 +338,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 b7d6a63b46f..bc58790d629 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); } } };