diff --git a/src/compat.rs b/src/compat.rs index a0a6bfc8..727b6eb5 100644 --- a/src/compat.rs +++ b/src/compat.rs @@ -273,7 +273,7 @@ impl Compatibility { /// (e.g. applications carefully designed to only be run with a specific set of kernel features), /// it may be required to error out if some of these features are not available /// and will then not be enforced. -pub trait Compatible { +pub trait Compatible: Sized + AsMut { /// To enable a best-effort security approach, /// Landlock features that are not supported by the running system /// are silently ignored by default, @@ -349,7 +349,10 @@ pub trait Compatible { /// .create()?) /// } /// ``` - fn set_compatibility(self, level: CompatLevel) -> Self; + fn set_compatibility(mut self, level: CompatLevel) -> Self { + *self.as_mut() = level; + self + } } /// See the [`Compatible`] documentation. diff --git a/src/fs.rs b/src/fs.rs index abed03ac..95db5496 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -262,13 +262,6 @@ where } } -impl Compatible for PathBeneath { - fn set_compatibility(mut self, level: CompatLevel) -> Self { - self.compat_level = level; - self - } -} - #[test] fn path_beneath_try_compat() { use crate::*; @@ -317,6 +310,29 @@ fn path_beneath_try_compat() { } } +impl AsMut for PathBeneath { + fn as_mut(&mut self) -> &mut CompatLevel { + &mut self.compat_level + } +} + +impl Compatible for PathBeneath {} + +impl Compatible for &mut PathBeneath {} + +#[test] +fn path_beneath_compatibility() { + let mut path = PathBeneath::new(PathFd::new("/").unwrap(), AccessFs::from_all(ABI::V1)); + let path_ref = &mut path; + + assert_eq!(path_ref.as_mut(), &CompatLevel::BestEffort); + + path_ref.set_compatibility(CompatLevel::SoftRequirement); + assert_eq!(path_ref.as_mut(), &CompatLevel::SoftRequirement); + + path.set_compatibility(CompatLevel::HardRequirement); +} + // It is useful for documentation generation to explicitely implement Rule for every types, instead // of doing it generically. impl Rule for PathBeneath where F: AsRawFd {} diff --git a/src/ruleset.rs b/src/ruleset.rs index c349e73d..7eea6906 100644 --- a/src/ruleset.rs +++ b/src/ruleset.rs @@ -254,13 +254,23 @@ impl Ruleset { } } +impl AsMut for Ruleset { + fn as_mut(&mut self) -> &mut CompatLevel { + &mut self.compat.level + } +} + +impl Compatible for Ruleset {} + +impl Compatible for &mut Ruleset {} + impl AsMut for Ruleset { fn as_mut(&mut self) -> &mut Ruleset { self } } -pub trait RulesetAttr: Sized + AsMut { +pub trait RulesetAttr: Sized + AsMut + Compatible { /// Attempts to add a set of access rights that will be supported by this ruleset. /// By default, all actions requiring these access rights will be denied. /// Consecutive calls to `handle_access()` will be interpreted as logical ORs @@ -289,6 +299,7 @@ fn ruleset_attr() { // Can pass this reference to prepare the ruleset... ruleset_ref + .set_compatibility(CompatLevel::BestEffort) .handle_access(AccessFs::Execute) .unwrap() .handle_access(AccessFs::ReadFile) @@ -296,6 +307,7 @@ fn ruleset_attr() { // ...and finally create the ruleset (thanks to non-lexical lifetimes). ruleset + .set_compatibility(CompatLevel::BestEffort) .handle_access(AccessFs::Execute) .unwrap() .handle_access(AccessFs::WriteFile) @@ -330,14 +342,17 @@ fn ruleset_created_handle_access_or() { )); } -impl Compatible for Ruleset { - fn set_compatibility(mut self, level: CompatLevel) -> Self { - self.compat.level = level; - self +impl AsMut for RulesetCreated { + fn as_mut(&mut self) -> &mut CompatLevel { + &mut self.compat.level } } -pub trait RulesetCreatedAttr: Sized + AsMut { +impl Compatible for RulesetCreated {} + +impl Compatible for &mut RulesetCreated {} + +pub trait RulesetCreatedAttr: Sized + AsMut + Compatible { /// Attempts to add a new rule to the ruleset. /// /// On error, returns a wrapped [`AddRulesError`]. @@ -476,7 +491,7 @@ pub trait RulesetCreatedAttr: Sized + AsMut { /// call while [`CompatLevel::SoftRequirement`] was set (with /// [`set_compatibility()`](Compatible::set_compatibility)). fn set_no_new_privs(mut self, no_new_privs: bool) -> Self { - self.as_mut().no_new_privs = no_new_privs; + >::as_mut(&mut self).no_new_privs = no_new_privs; self } } @@ -607,6 +622,7 @@ fn ruleset_created_attr() { // Can pass this reference to populate the ruleset... ruleset_created_ref + .set_compatibility(CompatLevel::BestEffort) .add_rule(PathBeneath::new( PathFd::new("/usr").unwrap(), AccessFs::Execute, @@ -620,6 +636,7 @@ fn ruleset_created_attr() { // ...and finally restrict with the last rules (thanks to non-lexical lifetimes). ruleset_created + .set_compatibility(CompatLevel::BestEffort) .add_rule(PathBeneath::new( PathFd::new("/tmp").unwrap(), AccessFs::Execute, @@ -634,13 +651,6 @@ fn ruleset_created_attr() { .unwrap(); } -impl Compatible for RulesetCreated { - fn set_compatibility(mut self, level: CompatLevel) -> Self { - self.compat.level = level; - self - } -} - #[test] fn ruleset_unsupported() { assert_eq!(