From 2666e17d3ff7d456d5af3defd1ec7a8ea909d4ba Mon Sep 17 00:00:00 2001 From: Robert Scott Date: Mon, 15 Apr 2024 22:39:26 +0100 Subject: [PATCH] qdrant: add patch for CVE-2024-3078 --- .../search/qdrant/1.7.4-CVE-2024-3078.patch | 142 ++++++++++++++++++ pkgs/servers/search/qdrant/default.nix | 4 + 2 files changed, 146 insertions(+) create mode 100644 pkgs/servers/search/qdrant/1.7.4-CVE-2024-3078.patch diff --git a/pkgs/servers/search/qdrant/1.7.4-CVE-2024-3078.patch b/pkgs/servers/search/qdrant/1.7.4-CVE-2024-3078.patch new file mode 100644 index 000000000000..b12b43834287 --- /dev/null +++ b/pkgs/servers/search/qdrant/1.7.4-CVE-2024-3078.patch @@ -0,0 +1,142 @@ +Based on upstream 3ab5172e9c8f14fa1f7b24e7147eac74e2412b62 with minor +adjustments to apply to 1.7.4 + +diff --git a/lib/collection/src/collection/snapshots.rs b/lib/collection/src/collection/snapshots.rs +index e5a8be9c..ca48fb9e 100644 +--- a/lib/collection/src/collection/snapshots.rs ++++ b/lib/collection/src/collection/snapshots.rs +@@ -241,35 +241,35 @@ impl Collection { + .await + } + ++ /// Get full file path for a collection snapshot by name ++ /// ++ /// This enforces the file to be inside the snapshots directory + pub async fn get_snapshot_path(&self, snapshot_name: &str) -> CollectionResult { +- let snapshot_path = self.snapshots_path.join(snapshot_name); +- +- let absolute_snapshot_path = +- snapshot_path +- .canonicalize() +- .map_err(|_| CollectionError::NotFound { +- what: format!("Snapshot {snapshot_name}"), +- })?; +- +- let absolute_snapshot_dir = +- self.snapshots_path +- .canonicalize() +- .map_err(|_| CollectionError::NotFound { +- what: format!("Snapshot directory: {}", self.snapshots_path.display()), +- })?; ++ let absolute_snapshot_dir = self.snapshots_path.canonicalize().map_err(|_| { ++ CollectionError::not_found(format!( ++ "Snapshot directory: {}", ++ self.snapshots_path.display() ++ )) ++ })?; ++ ++ let absolute_snapshot_path = absolute_snapshot_dir ++ .join(snapshot_name) ++ .canonicalize() ++ .map_err(|_| CollectionError::not_found(format!("Snapshot {snapshot_name}")))?; + + if !absolute_snapshot_path.starts_with(absolute_snapshot_dir) { +- return Err(CollectionError::NotFound { +- what: format!("Snapshot {snapshot_name}"), +- }); ++ return Err(CollectionError::not_found(format!( ++ "Snapshot {snapshot_name}" ++ ))); + } + +- if !snapshot_path.exists() { +- return Err(CollectionError::NotFound { +- what: format!("Snapshot {snapshot_name}"), +- }); ++ if !absolute_snapshot_path.exists() { ++ return Err(CollectionError::not_found(format!( ++ "Snapshot {snapshot_name}" ++ ))); + } +- Ok(snapshot_path) ++ ++ Ok(absolute_snapshot_path) + } + + pub async fn list_shard_snapshots( +diff --git a/lib/collection/src/operations/types.rs b/lib/collection/src/operations/types.rs +index afc38d0f..63eae16e 100644 +--- a/lib/collection/src/operations/types.rs ++++ b/lib/collection/src/operations/types.rs +@@ -906,6 +906,10 @@ impl CollectionError { + CollectionError::BadInput { description } + } + ++ pub fn not_found(what: impl Into) -> CollectionError { ++ CollectionError::NotFound { what: what.into() } ++ } ++ + pub fn bad_request(description: String) -> CollectionError { + CollectionError::BadRequest { description } + } +diff --git a/lib/storage/src/content_manager/errors.rs b/lib/storage/src/content_manager/errors.rs +index 1ad8d413..4528e485 100644 +--- a/lib/storage/src/content_manager/errors.rs ++++ b/lib/storage/src/content_manager/errors.rs +@@ -46,6 +46,12 @@ impl StorageError { + } + } + ++ pub fn not_found(description: impl Into) -> StorageError { ++ StorageError::NotFound { ++ description: description.into(), ++ } ++ } ++ + /// Used to override the `description` field of the resulting `StorageError` + pub fn from_inconsistent_shard_failure( + err: CollectionError, +diff --git a/lib/storage/src/content_manager/snapshots/mod.rs b/lib/storage/src/content_manager/snapshots/mod.rs +index 8a417377..9965006a 100644 +--- a/lib/storage/src/content_manager/snapshots/mod.rs ++++ b/lib/storage/src/content_manager/snapshots/mod.rs +@@ -24,17 +24,33 @@ pub struct SnapshotConfig { + pub collections_aliases: HashMap, + } + ++/// Get full file path for a full snapshot by name ++/// ++/// This enforces the file to be inside the snapshots directory + pub async fn get_full_snapshot_path( + toc: &TableOfContent, + snapshot_name: &str, + ) -> Result { +- let snapshot_path = Path::new(toc.snapshots_path()).join(snapshot_name); +- if !snapshot_path.exists() { +- return Err(StorageError::NotFound { +- description: format!("Full storage snapshot {snapshot_name} not found"), +- }); ++ let snapshots_path = toc.snapshots_path(); ++ ++ let absolute_snapshot_dir = Path::new(snapshots_path) ++ .canonicalize() ++ .map_err(|_| StorageError::not_found(format!("Snapshot directory: {snapshots_path}")))?; ++ ++ let absolute_snapshot_path = absolute_snapshot_dir ++ .join(snapshot_name) ++ .canonicalize() ++ .map_err(|_| StorageError::not_found(format!("Snapshot {snapshot_name}")))?; ++ ++ if !absolute_snapshot_path.starts_with(absolute_snapshot_dir) { ++ return Err(StorageError::not_found(format!("Snapshot {snapshot_name}"))); + } +- Ok(snapshot_path) ++ ++ if !absolute_snapshot_path.exists() { ++ return Err(StorageError::not_found(format!("Snapshot {snapshot_name}"))); ++ } ++ ++ Ok(absolute_snapshot_path) + } + + pub async fn do_delete_full_snapshot( diff --git a/pkgs/servers/search/qdrant/default.nix b/pkgs/servers/search/qdrant/default.nix index eb6fc6c71943..801887103ec4 100644 --- a/pkgs/servers/search/qdrant/default.nix +++ b/pkgs/servers/search/qdrant/default.nix @@ -22,6 +22,10 @@ rustPlatform.buildRustPackage rec { sha256 = "sha256-BgsLmE50mGmB5fcUjov8wcAHRTKMYaoyoXjSUyIddlc="; }; + patches = [ + ./1.7.4-CVE-2024-3078.patch + ]; + cargoLock = { lockFile = ./Cargo.lock; outputHashes = {