Check whether the StoreId is inside the store, before doing anything on the FS

This commit is contained in:
Matthias Beyer 2016-02-06 18:46:54 +01:00
parent eb0d1dba69
commit 373502217e
2 changed files with 23 additions and 0 deletions

View File

@ -19,6 +19,7 @@ pub enum StoreErrorKind {
IoError, IoError,
StorePathExists, StorePathExists,
StorePathCreate, StorePathCreate,
StorePathOutsideStore,
LockPoisoned, LockPoisoned,
EntryAlreadyBorrowed, EntryAlreadyBorrowed,
EntryAlreadyExists, EntryAlreadyExists,
@ -37,6 +38,7 @@ fn store_error_type_as_str(e: &StoreErrorKind) -> &'static str {
&StoreErrorKind::IoError => "File Error", &StoreErrorKind::IoError => "File Error",
&StoreErrorKind::StorePathExists => "Store path exists", &StoreErrorKind::StorePathExists => "Store path exists",
&StoreErrorKind::StorePathCreate => "Store path create", &StoreErrorKind::StorePathCreate => "Store path create",
&StoreErrorKind::StorePathOutsideStore => "Store path would be outside of store",
&StoreErrorKind::LockPoisoned &StoreErrorKind::LockPoisoned
=> "The internal Store Lock has been poisoned", => "The internal Store Lock has been poisoned",
&StoreErrorKind::EntryAlreadyBorrowed => "Entry is already borrowed", &StoreErrorKind::EntryAlreadyBorrowed => "Entry is already borrowed",

View File

@ -129,6 +129,10 @@ impl Store {
/// Creates the Entry at the given location (inside the entry) /// Creates the Entry at the given location (inside the entry)
pub fn create<'a>(&'a self, id: StoreId) -> Result<FileLockEntry<'a>> { pub fn create<'a>(&'a self, id: StoreId) -> Result<FileLockEntry<'a>> {
if !self.id_in_store(&id) {
return Err(StoreError::new(StoreErrorKind::StorePathOutsideStore, None));
}
let hsmap = self.entries.write(); let hsmap = self.entries.write();
if hsmap.is_err() { if hsmap.is_err() {
return Err(StoreError::new(StoreErrorKind::LockPoisoned, None)) return Err(StoreError::new(StoreErrorKind::LockPoisoned, None))
@ -148,6 +152,10 @@ impl Store {
/// Borrow a given Entry. When the `FileLockEntry` is either `update`d or /// Borrow a given Entry. When the `FileLockEntry` is either `update`d or
/// dropped, the new Entry is written to disk /// dropped, the new Entry is written to disk
pub fn retrieve<'a>(&'a self, id: StoreId) -> Result<FileLockEntry<'a>> { pub fn retrieve<'a>(&'a self, id: StoreId) -> Result<FileLockEntry<'a>> {
if !self.id_in_store(&id) {
return Err(StoreError::new(StoreErrorKind::StorePathOutsideStore, None));
}
self.entries self.entries
.write() .write()
.map_err(|_| StoreError::new(StoreErrorKind::LockPoisoned, None)) .map_err(|_| StoreError::new(StoreErrorKind::LockPoisoned, None))
@ -200,6 +208,10 @@ impl Store {
/// Delete an entry /// Delete an entry
pub fn delete(&self, id: StoreId) -> Result<()> { pub fn delete(&self, id: StoreId) -> Result<()> {
if !self.id_in_store(&id) {
return Err(StoreError::new(StoreErrorKind::StorePathOutsideStore, None));
}
let mut entries_lock = self.entries.write(); let mut entries_lock = self.entries.write();
if entries_lock.is_err() { if entries_lock.is_err() {
return Err(StoreError::new(StoreErrorKind::LockPoisoned, None)) return Err(StoreError::new(StoreErrorKind::LockPoisoned, None))
@ -216,6 +228,15 @@ impl Store {
entries.remove(&id); entries.remove(&id);
remove_file(&id).map_err(|e| StoreError::new(StoreErrorKind::FileError, Some(Box::new(e)))) remove_file(&id).map_err(|e| StoreError::new(StoreErrorKind::FileError, Some(Box::new(e))))
} }
fn id_in_store(&self, path: &StoreId) -> bool {
path.canonicalize()
.map(|can| {
can.starts_with(&self.location)
})
.unwrap_or(false)
// we return false, as fs::canonicalize() returns an Err(..) on filesystem errors
}
} }
impl Drop for Store { impl Drop for Store {