diff --git a/include/tscpp/api/TransactionPlugin.h b/include/tscpp/api/TransactionPlugin.h index ce3f1ca4419..cc3567d4e02 100644 --- a/include/tscpp/api/TransactionPlugin.h +++ b/include/tscpp/api/TransactionPlugin.h @@ -118,6 +118,8 @@ class TransactionPlugin : public Plugin */ std::shared_ptr getMutex(); + std::shared_ptr getMutex(TSHttpTxn); + private: TransactionPluginState *state_; /**< The internal state for a TransactionPlugin */ friend class utils::internal; diff --git a/src/tscpp/api/TransactionPlugin.cc b/src/tscpp/api/TransactionPlugin.cc index 5aba50b1fc7..3e1ba75655d 100644 --- a/src/tscpp/api/TransactionPlugin.cc +++ b/src/tscpp/api/TransactionPlugin.cc @@ -71,6 +71,12 @@ TransactionPlugin::getMutex() return state_->mutex_; } +std::shared_ptr +TransactionPlugin::getMutex(TSHttpTxn txnp) +{ + return state_->ats_txn_handle_ == txnp ? state_->mutex_ : nullptr; +} + bool TransactionPlugin::isWebsocket() const { diff --git a/src/tscpp/api/utils_internal.cc b/src/tscpp/api/utils_internal.cc index 61f90446aca..a4da599a0a4 100644 --- a/src/tscpp/api/utils_internal.cc +++ b/src/tscpp/api/utils_internal.cc @@ -58,10 +58,14 @@ cleanupTransaction(Transaction &transaction, TSHttpTxn ats_txn_handle) } void -cleanupTransactionPlugin(Plugin *plugin) +cleanupTransactionPlugin(Plugin *plugin, TSHttpTxn ats_txn_handle) { TransactionPlugin *transaction_plugin = static_cast(plugin); - std::shared_ptr trans_mutex = utils::internal::getTransactionPluginMutex(*transaction_plugin); + std::shared_ptr trans_mutex = utils::internal::getTransactionPluginMutex(*transaction_plugin, ats_txn_handle); + if (trans_mutex == nullptr) { + LOG_ERROR("TransactionPlugin use-after-free! plugin %p, txn %p", plugin, ats_txn_handle); + return; + } LOG_DEBUG("Locking TransactionPlugin mutex to delete transaction plugin at %p", transaction_plugin); trans_mutex->lock(); delete transaction_plugin; @@ -96,7 +100,7 @@ handleTransactionEvents(TSCont cont, TSEvent event, void *edata) resetTransactionHandles(transaction, event); const std::list &plugins = utils::internal::getTransactionPlugins(transaction); for (auto plugin : plugins) { - cleanupTransactionPlugin(plugin); + cleanupTransactionPlugin(plugin, ats_txn_handle); } cleanupTransaction(transaction, ats_txn_handle); } break; @@ -158,7 +162,7 @@ void inline invokePluginForEvent(Plugin *plugin, TSHttpTxn ats_txn_handle, TSEve case TS_EVENT_HTTP_TXN_CLOSE: if (plugin) { plugin->handleTxnClose(transaction); - cleanupTransactionPlugin(plugin); + cleanupTransactionPlugin(plugin, ats_txn_handle); } else { LOG_ERROR("stray event TS_EVENT_HTTP_TXN_CLOSE, no transaction plugin to handle it!"); } @@ -185,9 +189,9 @@ utils::internal::getTransaction(TSHttpTxn ats_txn_handle) } std::shared_ptr -utils::internal::getTransactionPluginMutex(TransactionPlugin &transaction_plugin) +utils::internal::getTransactionPluginMutex(TransactionPlugin &transaction_plugin, TSHttpTxn txnp) { - return transaction_plugin.getMutex(); + return transaction_plugin.getMutex(txnp); } TSHttpHookID diff --git a/src/tscpp/api/utils_internal.h b/src/tscpp/api/utils_internal.h index eacd1e4e9ed..a66f0a6f3ec 100644 --- a/src/tscpp/api/utils_internal.h +++ b/src/tscpp/api/utils_internal.h @@ -55,7 +55,7 @@ namespace utils static HttpVersion getHttpVersion(TSMBuffer hdr_buf, TSMLoc hdr_loc); static void initTransactionManagement(); static std::string consumeFromTSIOBufferReader(TSIOBufferReader); - static std::shared_ptr getTransactionPluginMutex(TransactionPlugin &); + static std::shared_ptr getTransactionPluginMutex(TransactionPlugin &, TSHttpTxn); static Transaction &getTransaction(TSHttpTxn); static AsyncHttpFetchState *