From 1ecc037ed7d637ad45fed6157314b070499399a1 Mon Sep 17 00:00:00 2001 From: Masakazu Kitajo Date: Tue, 16 May 2023 14:32:22 -0600 Subject: [PATCH] Fix a potential crash due to use-after-free on QUIC connections --- iocore/net/P_QUICNetVConnection_quiche.h | 5 ++++ iocore/net/QUICNetVConnection_quiche.cc | 34 ++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/iocore/net/P_QUICNetVConnection_quiche.h b/iocore/net/P_QUICNetVConnection_quiche.h index 16511fbf383..d20e9188b75 100644 --- a/iocore/net/P_QUICNetVConnection_quiche.h +++ b/iocore/net/P_QUICNetVConnection_quiche.h @@ -188,6 +188,11 @@ class QUICNetVConnection : public UnixNetVConnection, void _close_packet_write_ready(Event *data); Event *_packet_write_ready = nullptr; + void _schedule_quiche_timeout(); + void _unschedule_quiche_timeout(); + void _close_quiche_timeout(Event *data); + Event *_quiche_timeout = nullptr; + void _handle_read_ready(); void _handle_write_ready(); void _handle_interval(); diff --git a/iocore/net/QUICNetVConnection_quiche.cc b/iocore/net/QUICNetVConnection_quiche.cc index 7d4329f5fa1..933685af817 100644 --- a/iocore/net/QUICNetVConnection_quiche.cc +++ b/iocore/net/QUICNetVConnection_quiche.cc @@ -110,6 +110,10 @@ QUICNetVConnection::free(EThread *t) this->_udp_con = nullptr; quiche_conn_free(this->_quiche_con); + this->_quiche_con = nullptr; + + this->_unschedule_quiche_timeout(); + this->_unschedule_packet_write_ready(); delete this->_application_map; this->_application_map = nullptr; @@ -150,6 +154,7 @@ QUICNetVConnection::state_handshake(int event, Event *data) this->_schedule_packet_write_ready(true); break; case EVENT_INTERVAL: + this->_close_quiche_timeout(data); this->_handle_interval(); break; case VC_EVENT_EOS: @@ -181,6 +186,7 @@ QUICNetVConnection::state_established(int event, Event *data) this->_schedule_packet_write_ready(true); break; case EVENT_INTERVAL: + this->_close_quiche_timeout(data); this->_handle_interval(); break; case VC_EVENT_EOS: @@ -309,7 +315,7 @@ QUICNetVConnection::acceptEvent(int event, Event *e) action_.continuation->handleEvent(NET_EVENT_ACCEPT, this); this->_schedule_packet_write_ready(); - this->thread->schedule_in(this, HRTIME_MSECONDS(quiche_conn_timeout_as_millis(this->_quiche_con))); + this->_schedule_quiche_timeout(); return EVENT_DONE; } @@ -550,6 +556,30 @@ QUICNetVConnection::_close_packet_write_ready(Event *data) this->_packet_write_ready = nullptr; } +void +QUICNetVConnection::_schedule_quiche_timeout() +{ + if (!this->_quiche_timeout) { + this->_quiche_timeout = this->thread->schedule_in(this, HRTIME_MSECONDS(quiche_conn_timeout_as_millis(this->_quiche_con))); + } +} + +void +QUICNetVConnection::_unschedule_quiche_timeout() +{ + if (this->_quiche_timeout) { + this->_quiche_timeout->cancel(); + this->_quiche_timeout = nullptr; + } +} + +void +QUICNetVConnection::_close_quiche_timeout(Event *data) +{ + ink_assert(this->_quiche_timeout == data); + this->_quiche_timeout = nullptr; +} + void QUICNetVConnection::_handle_read_ready() { @@ -649,7 +679,7 @@ QUICNetVConnection::_handle_interval() } else { // Just schedule timeout event again if the connection is still open - this->thread->schedule_in(this, HRTIME_MSECONDS(quiche_conn_timeout_as_millis(this->_quiche_con))); + this->_schedule_quiche_timeout(); } }