mirror of
https://github.com/ouch-org/ouch.git
synced 2025-07-19 08:00:31 +00:00
allow multiple paths
This commit is contained in:
parent
1af69600ad
commit
6ccc7a3972
@ -321,9 +321,17 @@ fn execute_decompression(
|
|||||||
// init landlock sandbox to restrict file system write access to output_dir
|
// init landlock sandbox to restrict file system write access to output_dir
|
||||||
// The output directory iseither specified with the -d option or the current working directory is used
|
// The output directory iseither specified with the -d option or the current working directory is used
|
||||||
// TODO: restrict acess to the current working directory to allow only creating new files
|
// TODO: restrict acess to the current working directory to allow only creating new files
|
||||||
landlock::init_sandbox(Some(output_dir));
|
|
||||||
|
|
||||||
if is_smart_unpack {
|
// TODO: move to unpack and smart_unpack to cover the differetn dirctories used for
|
||||||
|
// decompression
|
||||||
|
|
||||||
|
//if !input_is_stdin && options.remove {
|
||||||
|
//permit write access to input_file_path
|
||||||
|
//} else {
|
||||||
|
landlock::init_sandbox(&[output_dir]);
|
||||||
|
//}
|
||||||
|
|
||||||
|
if is_smart_unpack {
|
||||||
return smart_unpack(unpack_fn, output_dir, output_file_path, question_policy);
|
return smart_unpack(unpack_fn, output_dir, output_file_path, question_policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ pub fn list_archive_contents(
|
|||||||
let mut temp_file = tempfile::NamedTempFile::new()?;
|
let mut temp_file = tempfile::NamedTempFile::new()?;
|
||||||
|
|
||||||
// Initialize landlock sandbox with write access restricted to /tmp/<tmp_file> as required by some formats
|
// Initialize landlock sandbox with write access restricted to /tmp/<tmp_file> as required by some formats
|
||||||
landlock::init_sandbox(Some(temp_file.path()));
|
landlock::init_sandbox(&[temp_file.path()]);
|
||||||
|
|
||||||
let reader = fs::File::open(archive_path)?;
|
let reader = fs::File::open(archive_path)?;
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ fn restrict_paths(hierarchies: &[&str]) -> Result<RestrictionStatus, MyRestrictE
|
|||||||
let access_all = AccessFs::from_all(abi);
|
let access_all = AccessFs::from_all(abi);
|
||||||
let access_read = AccessFs::from_read(abi);
|
let access_read = AccessFs::from_read(abi);
|
||||||
|
|
||||||
|
|
||||||
let mut ruleset = Ruleset::default()
|
let mut ruleset = Ruleset::default()
|
||||||
.handle_access(access_all)?
|
.handle_access(access_all)?
|
||||||
.create()?
|
.create()?
|
||||||
@ -76,18 +75,21 @@ fn restrict_paths(hierarchies: &[&str]) -> Result<RestrictionStatus, MyRestrictE
|
|||||||
Ok(ruleset.restrict_self()?)
|
Ok(ruleset.restrict_self()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Restricts the process to only access the given hierarchies using Landlock, if supported.
|
||||||
pub fn init_sandbox(allowed_dir: Option<&Path>) {
|
/// Accepts multiple allowed directories as &[&Path].
|
||||||
|
pub fn init_sandbox(allowed_dirs: &[&Path]) {
|
||||||
// if std::env::var("CI").is_ok() {
|
// if std::env::var("CI").is_ok() {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
if is_landlock_supported() {
|
if is_landlock_supported() {
|
||||||
let status = if let Some(allowed_dir) = allowed_dir {
|
let paths: Vec<&str> = allowed_dirs
|
||||||
let path_str = allowed_dir.to_str().expect("Cannot convert path");
|
.iter()
|
||||||
restrict_paths(&[path_str])
|
.map(|p| p.to_str().expect("Cannot convert path"))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let status = if !paths.is_empty() {
|
||||||
|
restrict_paths(&paths)
|
||||||
} else {
|
} else {
|
||||||
restrict_paths(&[])
|
restrict_paths(&[])
|
||||||
};
|
};
|
||||||
@ -104,8 +106,4 @@ pub fn init_sandbox(allowed_dir: Option<&Path>) {
|
|||||||
} else {
|
} else {
|
||||||
// warn!("Landlock is NOT supported on this platform or kernel (<5.19).");
|
// warn!("Landlock is NOT supported on this platform or kernel (<5.19).");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
109
src/utils/src_utils_landlock.rs
Normal file
109
src/utils/src_utils_landlock.rs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// Landlock support and generic Landlock sandbox implementation.
|
||||||
|
// https://landlock.io/rust-landlock/landlock/struct.Ruleset.html
|
||||||
|
|
||||||
|
use landlock::{
|
||||||
|
Access, AccessFs, PathBeneath, PathFd, PathFdError, RestrictionStatus, Ruleset,
|
||||||
|
RulesetAttr, RulesetCreatedAttr, RulesetError, ABI,
|
||||||
|
};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
/// The status code returned from `ouch` on error
|
||||||
|
pub const EXIT_FAILURE: i32 = libc::EXIT_FAILURE;
|
||||||
|
|
||||||
|
/// Returns true if Landlock is supported by the running kernel (Linux kernel >= 5.19).
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub fn is_landlock_supported() -> bool {
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
if let Ok(output) = Command::new("uname").arg("-r").output() {
|
||||||
|
if let Ok(version_str) = String::from_utf8(output.stdout) {
|
||||||
|
// Version string is expected to be in "5.19.0-foo" or similar
|
||||||
|
let mut parts = version_str.trim().split('.');
|
||||||
|
if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
|
||||||
|
if let (Ok(major), Ok(minor)) = (major.parse::<u32>(), minor.parse::<u32>()) {
|
||||||
|
return (major > 5) || (major == 5 && minor >= 19);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
pub fn is_landlock_supported() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum MyRestrictError {
|
||||||
|
#[error(transparent)]
|
||||||
|
Ruleset(#[from] RulesetError),
|
||||||
|
#[error(transparent)]
|
||||||
|
AddRule(#[from] PathFdError),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Restricts the process to only access the given hierarchies using Landlock, if supported.
|
||||||
|
///
|
||||||
|
/// The Landlock ABI is set to v2 for compatibility with Linux 5.19+.
|
||||||
|
/// All hierarchies are given full access, but root ("/") is read-only.
|
||||||
|
fn restrict_paths(hierarchies: &[&str]) -> Result<RestrictionStatus, MyRestrictError> {
|
||||||
|
// The Landlock ABI should be incremented (and tested) regularly.
|
||||||
|
// ABI set to 2 in compatibility with linux 5.19 and higher
|
||||||
|
let abi = ABI::V2;
|
||||||
|
let access_all = AccessFs::from_all(abi);
|
||||||
|
let access_read = AccessFs::from_read(abi);
|
||||||
|
|
||||||
|
let mut ruleset = Ruleset::default()
|
||||||
|
.handle_access(access_all)?
|
||||||
|
.create()?
|
||||||
|
// Read-only access to / (entire filesystem).
|
||||||
|
.add_rules(landlock::path_beneath_rules(&["/"], access_read))?;
|
||||||
|
|
||||||
|
// Add write permissions to specified directory of provided
|
||||||
|
if !hierarchies.is_empty() {
|
||||||
|
ruleset = ruleset.add_rules(
|
||||||
|
hierarchies
|
||||||
|
.iter()
|
||||||
|
.map::<Result<_, MyRestrictError>, _>(|p| {
|
||||||
|
Ok(PathBeneath::new(PathFd::new(p)?, access_all))
|
||||||
|
}),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ruleset.restrict_self()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Restricts the process to only access the given hierarchies using Landlock, if supported.
|
||||||
|
/// Accepts multiple allowed directories as &[&Path].
|
||||||
|
pub fn init_sandbox(allowed_dirs: &[&Path]) {
|
||||||
|
// if std::env::var("CI").is_ok() {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if is_landlock_supported() {
|
||||||
|
let paths: Vec<&str> = allowed_dirs
|
||||||
|
.iter()
|
||||||
|
.map(|p| p.to_str().expect("Cannot convert path"))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let status = if !paths.is_empty() {
|
||||||
|
restrict_paths(&paths)
|
||||||
|
} else {
|
||||||
|
restrict_paths(&[])
|
||||||
|
};
|
||||||
|
|
||||||
|
match status {
|
||||||
|
Ok(_status) => {
|
||||||
|
// check
|
||||||
|
}
|
||||||
|
Err(_e) => {
|
||||||
|
// log warning
|
||||||
|
std::process::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// warn!("Landlock is NOT supported on this platform or kernel (<5.19).");
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user