about summary refs log tree commit diff
path: root/pkgs/servers/search/qdrant/1.7.4-CVE-2024-3078.patch
blob: b12b438342878ce871fd0d514a60bfdfead63607 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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<PathBuf> {
-        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<String>) -> 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<String>) -> 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<String, String>,
 }
 
+/// 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<PathBuf, StorageError> {
-    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(