aboutsummaryrefslogtreecommitdiff
path: root/src/zenserver/storage/cache/httpstructuredcache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zenserver/storage/cache/httpstructuredcache.cpp')
-rw-r--r--src/zenserver/storage/cache/httpstructuredcache.cpp31
1 files changed, 25 insertions, 6 deletions
diff --git a/src/zenserver/storage/cache/httpstructuredcache.cpp b/src/zenserver/storage/cache/httpstructuredcache.cpp
index 4d3673e70..7ca496dec 100644
--- a/src/zenserver/storage/cache/httpstructuredcache.cpp
+++ b/src/zenserver/storage/cache/httpstructuredcache.cpp
@@ -70,6 +70,7 @@ namespace {
static constinit std::string_view HttpZCacheUtilStopRecording = "exec$/stop-recording"sv;
static constinit std::string_view HttpZCacheUtilReplayRecording = "exec$/replay-recording"sv;
static constinit std::string_view HttpZCacheDetailsPrefix = "details$"sv;
+ static constinit std::string_view HttpZCacheRecordingsDirName = "recordings"sv;
} // namespace
//////////////////////////////////////////////////////////////////////////
@@ -396,17 +397,26 @@ HttpStructuredCacheService::HandleRequest(HttpServerRequest& Request)
{
HttpServerRequest::QueryParams Params = Request.GetQueryParams();
- std::string RecordPath = UrlDecode(Params.GetValue("path"));
+ const std::string RecordPath = UrlDecode(Params.GetValue("path"));
+
+ const std::filesystem::path RecordingsRoot = m_CacheStore.GetBasePath() / HttpZCacheRecordingsDirName;
+ std::optional<std::filesystem::path> ResolvedPath = ResolveSafeRelativePath(RecordingsRoot, RecordPath);
+ if (!ResolvedPath)
+ {
+ m_CacheStats.BadRequestCount++;
+ ZEN_WARN("cache RPC start-recording rejected unsafe path '{}'", RecordPath);
+ return Request.WriteResponse(HttpResponseCode::BadRequest);
+ }
{
RwLock::ExclusiveLockScope _(m_RequestRecordingLock);
m_RequestRecordingEnabled.store(false);
m_RequestRecorder.reset();
- m_RequestRecorder = cache::MakeDiskRequestRecorder(RecordPath);
+ m_RequestRecorder = cache::MakeDiskRequestRecorder(*ResolvedPath);
m_RequestRecordingEnabled.store(true);
}
- ZEN_INFO("cache RPC recording STARTED -> '{}'", RecordPath);
+ ZEN_INFO("cache RPC recording STARTED -> '{}'", *ResolvedPath);
Request.WriteResponse(HttpResponseCode::OK);
return;
}
@@ -435,7 +445,16 @@ HttpStructuredCacheService::HandleRequest(HttpServerRequest& Request)
HttpServerRequest::QueryParams Params = Request.GetQueryParams();
- std::string RecordPath = UrlDecode(Params.GetValue("path"));
+ const std::string RecordPath = UrlDecode(Params.GetValue("path"));
+
+ const std::filesystem::path RecordingsRoot = m_CacheStore.GetBasePath() / HttpZCacheRecordingsDirName;
+ std::optional<std::filesystem::path> ResolvedPath = ResolveSafeRelativePath(RecordingsRoot, RecordPath);
+ if (!ResolvedPath)
+ {
+ m_CacheStats.BadRequestCount++;
+ ZEN_WARN("cache RPC replay-recording rejected unsafe path '{}'", RecordPath);
+ return Request.WriteResponse(HttpResponseCode::BadRequest);
+ }
const uint32_t HardwareConcurrency = GetHardwareConcurrency();
const uint32_t MaxThreadCount = std::max<uint32_t>(HardwareConcurrency, 16u);
@@ -449,9 +468,9 @@ HttpStructuredCacheService::HandleRequest(HttpServerRequest& Request)
}
ThreadCount = std::clamp<uint32_t>(ThreadCount, 1u, MaxThreadCount);
- ZEN_INFO("initiating cache RPC replay using {} threads, from '{}'", ThreadCount, RecordPath);
+ ZEN_INFO("initiating cache RPC replay using {} threads, from '{}'", ThreadCount, *ResolvedPath);
- std::unique_ptr<cache::IRpcRequestReplayer> Replayer(cache::MakeDiskRequestReplayer(RecordPath, false));
+ std::unique_ptr<cache::IRpcRequestReplayer> Replayer(cache::MakeDiskRequestReplayer(*ResolvedPath, false));
ReplayRequestRecorder(RequestContext, *Replayer, ThreadCount);
ZEN_INFO("cache RPC replay COMPLETED");