Skip to content
This repository has been archived by the owner on Feb 4, 2025. It is now read-only.

Commit

Permalink
feat(sandbox): add remove_dir / remove_file permissions to sandbox API
Browse files Browse the repository at this point in the history
When an extraction directory is empty, unblob will try to delete it.
This can lead to PermissionError due to insufficient permissions within
the sandbox.

We therefore expose the RemoveDir and RemoveFile permissions through the
sandbox API so it can be used by unblob.
  • Loading branch information
qkaiser authored and vlaci committed Jan 24, 2025
1 parent 3f70f2e commit 598ba0e
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 0 deletions.
4 changes: 4 additions & 0 deletions python/unblob_native/sandbox.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ class AccessFS:
def make_reg(access_dir: _Path) -> AccessFS: ...
@staticmethod
def make_dir(access_dir: _Path) -> AccessFS: ...
@staticmethod
def remove_dir(access_dir: _Path) -> AccessFS: ...
@staticmethod
def remove_file(access_dir: _Path) -> AccessFS: ...

def restrict_access(*args: AccessFS) -> None: ...

Expand Down
28 changes: 28 additions & 0 deletions src/sandbox/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ impl AccessFS {
None
}
}

fn remove_dir(&self) -> Option<&Path> {
if let Self::RemoveDir(path) = self {
Some(path)
} else {
None
}
}

fn remove_file(&self) -> Option<&Path> {
if let Self::RemoveFile(path) = self {
Some(path)
} else {
None
}
}
}

pub fn restrict_access(access_rules: &[AccessFS]) -> Result<(), SandboxError> {
Expand All @@ -56,13 +72,25 @@ pub fn restrict_access(access_rules: &[AccessFS]) -> Result<(), SandboxError> {

let create_directory: Vec<&Path> = access_rules.iter().filter_map(AccessFS::make_dir).collect();

let remove_directory: Vec<&Path> = access_rules
.iter()
.filter_map(AccessFS::remove_dir)
.collect();

let remove_file: Vec<&Path> = access_rules
.iter()
.filter_map(AccessFS::remove_file)
.collect();

let status = Ruleset::default()
.handle_access(AccessFs::from_all(abi))?
.create()?
.add_rules(path_beneath_rules(read_write, AccessFs::from_all(abi)))?
.add_rules(path_beneath_rules(create_file, AccessFs::MakeReg))?
.add_rules(path_beneath_rules(create_directory, AccessFs::MakeDir))?
.add_rules(path_beneath_rules(read_only, AccessFs::from_read(abi)))?
.add_rules(path_beneath_rules(remove_directory, AccessFs::RemoveDir))?
.add_rules(path_beneath_rules(remove_file, AccessFs::RemoveFile))?
.restrict_self()?;

if status.ruleset == RulesetStatus::NotEnforced {
Expand Down
12 changes: 12 additions & 0 deletions src/sandbox/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ pub enum AccessFS {
ReadWrite(PathBuf),
MakeReg(PathBuf),
MakeDir(PathBuf),
RemoveDir(PathBuf),
RemoveFile(PathBuf),
}

#[derive(Debug, Error)]
Expand Down Expand Up @@ -92,6 +94,16 @@ impl PyAccessFS {
fn make_dir(dir: PathBuf) -> Self {
Self::new(AccessFS::MakeDir(dir))
}

#[staticmethod]
fn remove_dir(dir: PathBuf) -> Self {
Self::new(AccessFS::RemoveDir(dir))
}

#[staticmethod]
fn remove_file(dir: PathBuf) -> Self {
Self::new(AccessFS::RemoveFile(dir))
}
}

pub fn init_module(root_module: &Bound<'_, PyModule>) -> PyResult<()> {
Expand Down

0 comments on commit 598ba0e

Please sign in to comment.