From c98a4622f7c9b1176b32c0438a2b29d236449203 Mon Sep 17 00:00:00 2001 From: jiayuzailiu Date: Thu, 30 Jul 2026 20:51:28 +0800 Subject: [PATCH 1/2] [TENT] Fix stack corruption in cuda_probe: cudaPointerGetAttributes() writes past sizeof(cudaPointerAttributes) and smashes the stack canary; route callers through a padded holder. --- .../tent/src/platform/cuda/cuda_probe.cpp | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/mooncake-transfer-engine/tent/src/platform/cuda/cuda_probe.cpp b/mooncake-transfer-engine/tent/src/platform/cuda/cuda_probe.cpp index 09345e982b..f7506d4962 100644 --- a/mooncake-transfer-engine/tent/src/platform/cuda/cuda_probe.cpp +++ b/mooncake-transfer-engine/tent/src/platform/cuda/cuda_probe.cpp @@ -262,10 +262,26 @@ Status CudaPlatform::probe(std::vector& nic_list, return Status::OK(); } +namespace { +struct PaddedPointerAttributes { + cudaPointerAttributes attr; + unsigned char pad[256]; +}; + +inline cudaError_t safePointerGetAttributes(cudaPointerAttributes* out, + const void* ptr) { + PaddedPointerAttributes buf; + memset(&buf, 0, sizeof(buf)); + cudaError_t rc = cudaPointerGetAttributes(&buf.attr, ptr); + memcpy(out, &buf.attr, sizeof(cudaPointerAttributes)); + return rc; +} +} + MemoryType CudaPlatform::getMemoryType(void* addr) { cudaPointerAttributes attributes; - cudaError_t result; - result = cudaPointerGetAttributes(&attributes, addr); + memset(&attributes, 0, sizeof(attributes)); + cudaError_t result = safePointerGetAttributes(&attributes, addr); if (result != cudaSuccess) { LOG(WARNING) << "cudaPointerGetAttributes: " << cudaGetErrorString(result); @@ -297,9 +313,8 @@ const std::vector CudaPlatform::getLocation(void* start, std::vector entries; cudaPointerAttributes attributes; - cudaError_t result; - - result = cudaPointerGetAttributes(&attributes, start); + memset(&attributes, 0, sizeof(attributes)); + cudaError_t result = safePointerGetAttributes(&attributes, start); if (result != cudaSuccess) { LOG(WARNING) << "cudaPointerGetAttributes: " << cudaGetErrorString(result); From 3812a95c0f8b29266b9a18f816a479760113e344 Mon Sep 17 00:00:00 2001 From: jiayuzailiu Date: Thu, 30 Jul 2026 21:02:53 +0800 Subject: [PATCH 2/2] [TENT] Fix double-free in HttpMetaStore: a shared CURL* is not thread-safe, concurrent get/set from worker threads double-freed handle-owned strings via curl_easy_reset(); allocate a per-request handle (RAII) and guard curl_global_init() with std::call_once. --- .../tent/include/tent/metastore/http.h | 7 +- .../tent/src/metastore/http.cpp | 98 ++++++++++++------- 2 files changed, 63 insertions(+), 42 deletions(-) diff --git a/mooncake-transfer-engine/tent/include/tent/metastore/http.h b/mooncake-transfer-engine/tent/include/tent/metastore/http.h index a9b5532f29..0a68ae4215 100644 --- a/mooncake-transfer-engine/tent/include/tent/metastore/http.h +++ b/mooncake-transfer-engine/tent/include/tent/metastore/http.h @@ -46,16 +46,15 @@ class HttpMetaStore : public MetaStore { } std::string encodeUrl(const std::string &key) { - char *newkey = curl_easy_escape(client_, key.c_str(), key.size()); - std::string encodedKey(newkey); + char *newkey = curl_easy_escape(nullptr, key.c_str(), key.size()); + std::string encodedKey(newkey ? newkey : ""); std::string url = endpoint_ + "?key=" + encodedKey; - curl_free(newkey); + if (newkey) curl_free(newkey); return url; } private: std::atomic connected_; - CURL *client_; std::string endpoint_; }; } // namespace tent diff --git a/mooncake-transfer-engine/tent/src/metastore/http.cpp b/mooncake-transfer-engine/tent/src/metastore/http.cpp index d5f1bfc132..ffa1cf130f 100644 --- a/mooncake-transfer-engine/tent/src/metastore/http.cpp +++ b/mooncake-transfer-engine/tent/src/metastore/http.cpp @@ -15,10 +15,17 @@ #include "tent/metastore/http.h" #include +#include namespace mooncake { namespace tent { +static std::once_flag g_curl_global_init_flag; +static void ensureCurlGlobalInit() { + std::call_once(g_curl_global_init_flag, + []() { curl_global_init(CURL_GLOBAL_ALL); }); +} + HttpMetaStore::HttpMetaStore() {} HttpMetaStore::~HttpMetaStore() { disconnect(); } @@ -28,42 +35,49 @@ Status HttpMetaStore::connect(const std::string &endpoint) { return Status::MetadataError( "HTTP connection already established" LOC_MARK); } - curl_global_init(CURL_GLOBAL_ALL); - client_ = curl_easy_init(); - if (!client_) { - return Status::InternalError( - "HTTP cannot allocate curl objects" LOC_MARK); - } + ensureCurlGlobalInit(); endpoint_ = endpoint; connected_ = true; return Status::OK(); } Status HttpMetaStore::disconnect() { - if (connected_) { - curl_easy_cleanup(client_); - curl_global_cleanup(); - connected_ = false; - } + connected_ = false; return Status::OK(); } +namespace { +struct ScopedCurl { + CURL *h{nullptr}; + ScopedCurl() : h(curl_easy_init()) {} + ~ScopedCurl() { if (h) curl_easy_cleanup(h); } + ScopedCurl(const ScopedCurl &) = delete; + ScopedCurl &operator=(const ScopedCurl &) = delete; + operator CURL *() const { return h; } + explicit operator bool() const { return h != nullptr; } +}; +} // namespace + Status HttpMetaStore::get(const std::string &key, std::string &value) { if (!connected_) { return Status::MetadataError("HTTP connection not available" LOC_MARK); } - curl_easy_reset(client_); - curl_easy_setopt(client_, CURLOPT_TIMEOUT_MS, 3000); // 3s timeout + ScopedCurl client; + if (!client) { + return Status::InternalError( + "HTTP cannot allocate curl handle" LOC_MARK); + } + curl_easy_setopt(client.h, CURLOPT_TIMEOUT_MS, 3000); // 3s timeout std::string url = encodeUrl(key); - curl_easy_setopt(client_, CURLOPT_URL, url.c_str()); - curl_easy_setopt(client_, CURLOPT_WRITEFUNCTION, writeCallback); + curl_easy_setopt(client.h, CURLOPT_URL, url.c_str()); + curl_easy_setopt(client.h, CURLOPT_WRITEFUNCTION, writeCallback); // get response body std::string readBuffer; - curl_easy_setopt(client_, CURLOPT_WRITEDATA, &readBuffer); - CURLcode res = curl_easy_perform(client_); + curl_easy_setopt(client.h, CURLOPT_WRITEDATA, &readBuffer); + CURLcode res = curl_easy_perform(client.h); if (res != CURLE_OK) { return Status::MetadataError( std::string("HTTP failed to post request: ") + @@ -72,7 +86,7 @@ Status HttpMetaStore::get(const std::string &key, std::string &value) { // Get the HTTP response code long responseCode; - curl_easy_getinfo(client_, CURLINFO_RESPONSE_CODE, &responseCode); + curl_easy_getinfo(client.h, CURLINFO_RESPONSE_CODE, &responseCode); if (responseCode == 404) { return Status::InvalidEntry(key); } else if (responseCode != 200) { @@ -81,7 +95,7 @@ Status HttpMetaStore::get(const std::string &key, std::string &value) { std::string("HTTP received unexpected response: ") + message + LOC_MARK); } - value = std::string(readBuffer); + value = std::move(readBuffer); return Status::OK(); } @@ -90,25 +104,29 @@ Status HttpMetaStore::set(const std::string &key, const std::string &value) { return Status::MetadataError("HTTP connection not available" LOC_MARK); } - curl_easy_reset(client_); - curl_easy_setopt(client_, CURLOPT_TIMEOUT_MS, 3000); // 3s timeout + ScopedCurl client; + if (!client) { + return Status::InternalError( + "HTTP cannot allocate curl handle" LOC_MARK); + } + curl_easy_setopt(client.h, CURLOPT_TIMEOUT_MS, 3000); // 3s timeout std::string url = encodeUrl(key); - curl_easy_setopt(client_, CURLOPT_URL, url.c_str()); - curl_easy_setopt(client_, CURLOPT_WRITEFUNCTION, writeCallback); - curl_easy_setopt(client_, CURLOPT_POSTFIELDS, value.c_str()); - curl_easy_setopt(client_, CURLOPT_POSTFIELDSIZE, value.size()); - curl_easy_setopt(client_, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_easy_setopt(client.h, CURLOPT_URL, url.c_str()); + curl_easy_setopt(client.h, CURLOPT_WRITEFUNCTION, writeCallback); + curl_easy_setopt(client.h, CURLOPT_POSTFIELDS, value.c_str()); + curl_easy_setopt(client.h, CURLOPT_POSTFIELDSIZE, value.size()); + curl_easy_setopt(client.h, CURLOPT_CUSTOMREQUEST, "PUT"); // get response body std::string readBuffer; - curl_easy_setopt(client_, CURLOPT_WRITEDATA, &readBuffer); + curl_easy_setopt(client.h, CURLOPT_WRITEDATA, &readBuffer); // set content-type to application/json struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Content-Type: application/json"); - curl_easy_setopt(client_, CURLOPT_HTTPHEADER, headers); - CURLcode res = curl_easy_perform(client_); + curl_easy_setopt(client.h, CURLOPT_HTTPHEADER, headers); + CURLcode res = curl_easy_perform(client.h); curl_slist_free_all(headers); // free headers if (res != CURLE_OK) { return Status::MetadataError( @@ -117,7 +135,7 @@ Status HttpMetaStore::set(const std::string &key, const std::string &value) { } long responseCode; - curl_easy_getinfo(client_, CURLINFO_RESPONSE_CODE, &responseCode); + curl_easy_getinfo(client.h, CURLINFO_RESPONSE_CODE, &responseCode); if (responseCode != 200) { std::string message = std::to_string(responseCode) + ": " + readBuffer; return Status::MetadataError( @@ -133,18 +151,22 @@ Status HttpMetaStore::remove(const std::string &key) { return Status::MetadataError("HTTP connection not available" LOC_MARK); } - curl_easy_reset(client_); - curl_easy_setopt(client_, CURLOPT_TIMEOUT_MS, 3000); // 3s timeout + ScopedCurl client; + if (!client) { + return Status::InternalError( + "HTTP cannot allocate curl handle" LOC_MARK); + } + curl_easy_setopt(client.h, CURLOPT_TIMEOUT_MS, 3000); // 3s timeout std::string url = encodeUrl(key); - curl_easy_setopt(client_, CURLOPT_URL, url.c_str()); - curl_easy_setopt(client_, CURLOPT_WRITEFUNCTION, writeCallback); - curl_easy_setopt(client_, CURLOPT_CUSTOMREQUEST, "DELETE"); + curl_easy_setopt(client.h, CURLOPT_URL, url.c_str()); + curl_easy_setopt(client.h, CURLOPT_WRITEFUNCTION, writeCallback); + curl_easy_setopt(client.h, CURLOPT_CUSTOMREQUEST, "DELETE"); // get response body std::string readBuffer; - curl_easy_setopt(client_, CURLOPT_WRITEDATA, &readBuffer); - CURLcode res = curl_easy_perform(client_); + curl_easy_setopt(client.h, CURLOPT_WRITEDATA, &readBuffer); + CURLcode res = curl_easy_perform(client.h); if (res != CURLE_OK) { return Status::MetadataError( std::string("HTTP failed to post request: ") + @@ -152,7 +174,7 @@ Status HttpMetaStore::remove(const std::string &key) { } long responseCode; - curl_easy_getinfo(client_, CURLINFO_RESPONSE_CODE, &responseCode); + curl_easy_getinfo(client.h, CURLINFO_RESPONSE_CODE, &responseCode); if (responseCode != 200) { std::string message = std::to_string(responseCode) + ": " + readBuffer; return Status::MetadataError(