diff --git a/src/compat.rs b/src/compat.rs index 06c5110..4017b6c 100644 --- a/src/compat.rs +++ b/src/compat.rs @@ -277,6 +277,14 @@ impl Compatibility { } } +pub(crate) mod private { + use crate::CompatLevel; + + pub trait OptionCompatLevelMut { + fn as_option_compat_level_mut(&mut self) -> &mut Option; + } +} + /// Properly handles runtime unsupported features. /// /// This guarantees consistent behaviors across crate users @@ -292,7 +300,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: Sized + AsMut> { +pub trait Compatible: Sized + private::OptionCompatLevelMut { /// To enable a best-effort security approach, /// Landlock features that are not supported by the running system /// are silently ignored by default, @@ -396,7 +404,7 @@ pub trait Compatible: Sized + AsMut> { /// } /// ``` fn set_compatibility(mut self, level: CompatLevel) -> Self { - *self.as_mut() = Some(level); + *self.as_option_compat_level_mut() = Some(level); self } @@ -491,7 +499,7 @@ where // Using a mutable reference is not required but it makes the code simpler (no double AsRef // implementations for each Compatible types), and more importantly it guarantees // consistency with Compatible::set_compatibility(). - match self.as_mut() { + match self.as_option_compat_level_mut() { None => parent_level.into(), // Returns the most constrained compatibility level. Some(ref level) => parent_level.into().max(*level), diff --git a/src/fs.rs b/src/fs.rs index e447475..ec1954e 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -1,3 +1,4 @@ +use crate::compat::private::OptionCompatLevelMut; use crate::{ uapi, Access, AddRuleError, AddRulesError, CompatError, CompatLevel, CompatResult, CompatState, Compatible, HandleAccessError, HandleAccessesError, PathBeneathError, PathFdError, @@ -338,8 +339,14 @@ fn path_beneath_try_compat() { } } -impl AsMut> for PathBeneath { - fn as_mut(&mut self) -> &mut Option { +impl OptionCompatLevelMut for PathBeneath { + fn as_option_compat_level_mut(&mut self) -> &mut Option { + &mut self.compat_level + } +} + +impl OptionCompatLevelMut for &mut PathBeneath { + fn as_option_compat_level_mut(&mut self) -> &mut Option { &mut self.compat_level } } @@ -353,7 +360,7 @@ fn path_beneath_compatibility() { let mut path = PathBeneath::new(PathFd::new("/").unwrap(), AccessFs::from_all(ABI::V1)); let path_ref = &mut path; - let level = path_ref.as_mut(); + let level = path_ref.as_option_compat_level_mut(); assert_eq!(level, &None); assert_eq!( as Into>::into(*level), @@ -361,7 +368,10 @@ fn path_beneath_compatibility() { ); path_ref.set_compatibility(CompatLevel::SoftRequirement); - assert_eq!(path_ref.as_mut(), &Some(CompatLevel::SoftRequirement)); + assert_eq!( + path_ref.as_option_compat_level_mut(), + &Some(CompatLevel::SoftRequirement) + ); path.set_compatibility(CompatLevel::HardRequirement); } diff --git a/src/ruleset.rs b/src/ruleset.rs index d3bfa81..b3a9a8c 100644 --- a/src/ruleset.rs +++ b/src/ruleset.rs @@ -1,3 +1,4 @@ +use crate::compat::private::OptionCompatLevelMut; use crate::{ uapi, Access, AccessFs, AddRuleError, AddRulesError, BitFlags, CompatLevel, CompatState, Compatibility, Compatible, CreateRulesetError, RestrictSelfError, RulesetError, TryCompat, @@ -284,8 +285,14 @@ impl Ruleset { } } -impl AsMut> for Ruleset { - fn as_mut(&mut self) -> &mut Option { +impl OptionCompatLevelMut for Ruleset { + fn as_option_compat_level_mut(&mut self) -> &mut Option { + &mut self.compat.level + } +} + +impl OptionCompatLevelMut for &mut Ruleset { + fn as_option_compat_level_mut(&mut self) -> &mut Option { &mut self.compat.level } } @@ -300,6 +307,20 @@ impl AsMut for Ruleset { } } +// Tests unambiguous type. +#[test] +fn ruleset_as_mut() { + let mut ruleset = Ruleset::from(ABI::Unsupported); + let _ = ruleset.as_mut(); + + let mut ruleset_created = Ruleset::from(ABI::Unsupported) + .handle_access(AccessFs::Execute) + .unwrap() + .create() + .unwrap(); + let _ = ruleset_created.as_mut(); +} + 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. @@ -372,8 +393,14 @@ fn ruleset_created_handle_access_or() { )); } -impl AsMut> for RulesetCreated { - fn as_mut(&mut self) -> &mut Option { +impl OptionCompatLevelMut for RulesetCreated { + fn as_option_compat_level_mut(&mut self) -> &mut Option { + &mut self.compat.level + } +} + +impl OptionCompatLevelMut for &mut RulesetCreated { + fn as_option_compat_level_mut(&mut self) -> &mut Option { &mut self.compat.level } }