diff options
Diffstat (limited to 'src/zenserver/storage/cache/httpstructuredcache.cpp')
| -rw-r--r-- | src/zenserver/storage/cache/httpstructuredcache.cpp | 31 |
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"); |