From 44dbf93d20e987d3a8d9209fd9d40cff13f8c70c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Wed, 4 Jan 2023 15:40:43 +0100 Subject: [PATCH 1/3] ruleset: Add Ruleset::new(CompatMode) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WIP: This implementation works by leveraging CompatLevel that may need to be replaced. We also need to remove the public set_compatibility(). The use of new() might change because of future access right groups development. Signed-off-by: Mickaël Salaün --- src/compat.rs | 22 ++++++++++++++++++++++ src/lib.rs | 2 +- src/ruleset.rs | 28 ++++++++++++++++++++++------ 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/compat.rs b/src/compat.rs index e08ceead..ba196c95 100644 --- a/src/compat.rs +++ b/src/compat.rs @@ -459,6 +459,28 @@ fn deprecated_set_best_effort() { ); } +/// See the [`Compatible`] documentation. +#[derive(Default)] +pub enum CompatMode { + /// Takes into account the build requests if they are supported by the running system, + /// or silently ignores them otherwise. + /// Never returns a compatibility error. + #[default] + BestEffort, + /// Takes into account the build requests if they are supported by the running system, + /// or returns a compatibility error otherwise ([`CompatError`]). + ErrorIfUnmet, +} + +impl From for CompatLevel { + fn from(mode: CompatMode) -> Self { + match mode { + CompatMode::BestEffort => CompatLevel::BestEffort, + CompatMode::ErrorIfUnmet => CompatLevel::HardRequirement, + } + } +} + /// See the [`Compatible`] documentation. #[cfg_attr(test, derive(EnumIter))] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] diff --git a/src/lib.rs b/src/lib.rs index 3c26100d..cba3a480 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,7 +80,7 @@ extern crate lazy_static; pub use access::Access; -pub use compat::{CompatLevel, Compatible, ABI}; +pub use compat::{CompatLevel, CompatMode, Compatible, ABI}; pub use enumflags2::{make_bitflags, BitFlags}; pub use errors::{ AccessError, AddRuleError, AddRulesError, CompatError, CreateRulesetError, HandleAccessError, diff --git a/src/ruleset.rs b/src/ruleset.rs index f802c3cc..e4d0e4d5 100644 --- a/src/ruleset.rs +++ b/src/ruleset.rs @@ -1,7 +1,8 @@ use crate::compat::private::OptionCompatLevelMut; use crate::{ - uapi, Access, AccessFs, AddRuleError, AddRulesError, BitFlags, CompatLevel, CompatState, - Compatibility, Compatible, CreateRulesetError, RestrictSelfError, RulesetError, TryCompat, + uapi, Access, AccessFs, AddRuleError, AddRulesError, BitFlags, CompatLevel, CompatMode, + CompatState, Compatibility, Compatible, CreateRulesetError, RestrictSelfError, RulesetError, + TryCompat, }; use libc::close; use std::io::Error; @@ -222,11 +223,26 @@ impl Default for Ruleset { } impl Ruleset { - #[allow(clippy::new_without_default)] - #[deprecated(note = "Use Ruleset::default() instead")] - pub fn new() -> Self { - Ruleset::default() + /// Returns a new `Ruleset` with a specific compatibility mode. + /// + /// In most cases we should use [`Ruleset::default()`] instead. + pub fn new(mode: CompatMode, handle_access: T) -> Result + where + T: Into>, + U: Access, + { + Self::default() + .set_compatibility(mode.into()) + .handle_access(handle_access) + } + + /* + // TODO: + #[cfg(test)] + pub(crate) fn new_from(mode: CompatMode, abi: ABI) -> Self { + Self::from(abi).set_compatibility(mode.into()) } + */ /// Attempts to create a real Landlock ruleset (if supported by the running kernel). /// The returned [`RulesetCreated`] is also a builder. From 92406d4718fc20662a104b7a3022fae5fbafd1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Sun, 8 Jan 2023 19:10:07 +0100 Subject: [PATCH 2/3] access,fs: Add if_unmet() method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WIP: Clean up the CompatLevel side and correctly handle PathBeneath's compat state. WIP: replacing disable_sandbox_if_unmet() with if_unmet(Consequence), which handles ReturnError. Use case appliances handling a minimal kernel version that is known to support a specific set of Landlock features, but that might use a newer kernel and then opportunistically restrict processes furthermore. This is equivalent to call disable_sandbox_if_unmet(true) is equivalent to set_compatibility(CompatLevel::SoftRequirement) and disable_sandbox_if_unmet(false) is equivalent to set_compatibility(previous_compat_level). Signed-off-by: Mickaël Salaün --- src/access.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++---- src/compat.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++++++- src/fs.rs | 21 ++++++++++++++----- src/lib.rs | 4 +++- src/ruleset.rs | 11 +++++----- 5 files changed, 131 insertions(+), 16 deletions(-) diff --git a/src/access.rs b/src/access.rs index 782f8d1d..a6033867 100644 --- a/src/access.rs +++ b/src/access.rs @@ -1,13 +1,22 @@ use crate::{ - AccessError, AddRuleError, AddRulesError, BitFlags, CompatError, CompatResult, - HandleAccessError, HandleAccessesError, Ruleset, TailoredCompatLevel, TryCompat, ABI, + AccessError, AddRuleError, AddRulesError, BitFlags, CompatArg, CompatError, CompatResult, + CompatibleArgument, HandleAccessError, HandleAccessesError, Ruleset, TailoredCompatLevel, + TryCompat, ABI, }; use enumflags2::BitFlag; #[cfg(test)] use crate::{make_bitflags, AccessFs, CompatLevel, CompatState, Compatibility}; -pub trait Access: PrivateAccess { +pub trait Access +where + Self: PrivateAccess + + Into> + + Into>> + + CompatibleArgument>, + BitFlags: + Into>> + CompatibleArgument>, +{ /// Gets the access rights defined by a specific [`ABI`]. /// Union of [`from_read()`](Access::from_read) and [`from_write()`](Access::from_write). fn from_all(abi: ABI) -> BitFlags { @@ -30,7 +39,7 @@ pub trait Access: PrivateAccess { pub trait PrivateAccess: BitFlag { fn ruleset_handle_access( ruleset: &mut Ruleset, - access: BitFlags, + access: CompatArg>, ) -> Result<(), HandleAccessesError> where Self: Access; @@ -191,3 +200,41 @@ fn compat_bit_flags() { if access == v2_access && incompatible == AccessFs::Refer )); } + +impl From for CompatArg> +where + A: Access, +{ + fn from(access: A) -> Self { + let bitflags: BitFlags = access.into(); + bitflags.into() + } +} + +impl CompatibleArgument for A +where + A: Access, +{ + type CompatSelf = BitFlags; +} + +impl CompatibleArgument for BitFlags +where + A: Access, +{ + type CompatSelf = Self; +} + +#[test] +fn compat_arg() { + use crate::{AccessFs, BitFlags, CompatibleArgument, Consequence, Ruleset, RulesetAttr}; + + let exec: BitFlags<_> = AccessFs::Execute.into(); + Ruleset::from(ABI::Unsupported) + .handle_access(exec.if_unmet(Consequence::DisableRuleset)) + .unwrap(); + + Ruleset::from(ABI::Unsupported) + .handle_access(AccessFs::Execute.if_unmet(Consequence::DisableRuleset)) + .unwrap(); +} diff --git a/src/compat.rs b/src/compat.rs index ba196c95..1d8a3693 100644 --- a/src/compat.rs +++ b/src/compat.rs @@ -187,9 +187,10 @@ fn current_kernel_abi() { // CompatState is not public outside this crate. /// Returned by ruleset builder. #[cfg_attr(test, derive(Debug))] -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, Default, PartialEq, Eq)] pub enum CompatState { /// Initial undefined state. + #[default] Init, /// All requested restrictions are enforced. Full, @@ -459,6 +460,59 @@ fn deprecated_set_best_effort() { ); } +// TODO: Add doc +#[derive(Default)] +pub enum Consequence { + /// Best-effort approach. + #[default] + Continue, + DisableRuleset, + ReturnError, +} + +pub struct CompatArg { + inner: T, + if_unmet: Consequence, +} + +impl CompatArg { + pub fn unwrap_update(self, _current_abi: ABI, _compat_state: &mut CompatState) -> T { + /* + match self.disable_sandbox_if_unmet { + // Similar to CompatLevel::SoftRequirement + compat_state.update(CompatState::Dummy); + } + */ + self.inner + } +} + +pub trait CompatibleArgument: Sized + Into { + type CompatSelf; + + fn if_unmet(self, consequence: Consequence) -> CompatArg { + CompatArg { + inner: self.into(), + if_unmet: consequence, + } + } +} + +impl From for CompatArg +where + T: CompatibleArgument, +{ + fn from(inner: T) -> Self { + inner.if_unmet(Consequence::default()) + } +} + +#[test] +fn from_compat_arg_to_compat_arg() { + // TODO: test that a CompatibleArgument with non-Consequence::default() cannot be converted to + // a Consequence::default() through the From trait. +} + /// See the [`Compatible`] documentation. #[derive(Default)] pub enum CompatMode { diff --git a/src/fs.rs b/src/fs.rs index 3ebf9c08..325f4047 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -1,7 +1,7 @@ use crate::compat::private::OptionCompatLevelMut; use crate::{ - uapi, Access, AddRuleError, AddRulesError, CompatError, CompatLevel, CompatResult, CompatState, - Compatible, HandleAccessError, HandleAccessesError, PathBeneathError, PathFdError, + uapi, Access, AddRuleError, AddRulesError, CompatArg, CompatError, CompatLevel, CompatResult, + CompatState, Compatible, HandleAccessError, HandleAccessesError, PathBeneathError, PathFdError, PrivateAccess, PrivateRule, Rule, Ruleset, RulesetCreated, RulesetError, TailoredCompatLevel, TryCompat, ABI, }; @@ -142,8 +142,10 @@ impl AccessFs { impl PrivateAccess for AccessFs { fn ruleset_handle_access( ruleset: &mut Ruleset, - access: BitFlags, + access: CompatArg>, ) -> Result<(), HandleAccessesError> { + // FIXME: test compat state + let access = access.unwrap_update(ABI::V1, &mut ruleset.compat.state); // We need to record the requested accesses for PrivateRule::check_consistency(). ruleset.requested_handled_fs |= access; ruleset.actual_handled_fs |= match access @@ -207,6 +209,8 @@ pub struct PathBeneath { parent_fd: F, allowed_access: BitFlags, compat_level: Option, + // FIXME: Handle compat_state + //compat_state: CompatState, } impl PathBeneath @@ -218,8 +222,14 @@ where /// The `parent` file descriptor will be automatically closed with the returned `PathBeneath`. pub fn new(parent: F, access: A) -> Self where - A: Into>, + A: Into>>, { + // FIXME: + // - properly handle and test compat state and ABI version + // - don't call any kind of unwrap_update() here but set self.allowed_access with this + // CompatArg and deal with it later. + let mut compat_state = Default::default(); + let access = access.into().unwrap_update(ABI::V1, &mut compat_state); PathBeneath { attr: uapi::landlock_path_beneath_attr { // Invalid access-rights until try_compat() is called. @@ -227,8 +237,9 @@ where parent_fd: parent.as_fd().as_raw_fd(), }, parent_fd: parent, - allowed_access: access.into(), + allowed_access: access, compat_level: None, + //compat_state: compat_state, } } diff --git a/src/lib.rs b/src/lib.rs index cba3a480..2572a6ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,7 +80,9 @@ extern crate lazy_static; pub use access::Access; -pub use compat::{CompatLevel, CompatMode, Compatible, ABI}; +pub use compat::{ + CompatArg, CompatLevel, CompatMode, Compatible, CompatibleArgument, Consequence, ABI, +}; pub use enumflags2::{make_bitflags, BitFlags}; pub use errors::{ AccessError, AddRuleError, AddRulesError, CompatError, CreateRulesetError, HandleAccessError, diff --git a/src/ruleset.rs b/src/ruleset.rs index e4d0e4d5..82cbd6de 100644 --- a/src/ruleset.rs +++ b/src/ruleset.rs @@ -1,8 +1,8 @@ use crate::compat::private::OptionCompatLevelMut; use crate::{ - uapi, Access, AccessFs, AddRuleError, AddRulesError, BitFlags, CompatLevel, CompatMode, - CompatState, Compatibility, Compatible, CreateRulesetError, RestrictSelfError, RulesetError, - TryCompat, + uapi, Access, AccessFs, AddRuleError, AddRulesError, BitFlags, CompatArg, CompatLevel, + CompatMode, CompatState, Compatibility, Compatible, CreateRulesetError, RestrictSelfError, + RulesetError, TryCompat, }; use libc::close; use std::io::Error; @@ -233,7 +233,7 @@ impl Ruleset { { Self::default() .set_compatibility(mode.into()) - .handle_access(handle_access) + .handle_access(handle_access.into()) } /* @@ -348,7 +348,8 @@ pub trait RulesetAttr: Sized + AsMut + Compatible { /// E.g., `RulesetError::HandleAccesses(HandleAccessesError::Fs(HandleAccessError))` fn handle_access(mut self, access: T) -> Result where - T: Into>, + T: Into>>, + //T: Into> // XXX: CompatibleArgument is not required but could help users U: Access, { U::ruleset_handle_access(self.as_mut(), access.into())?; From 5d9510a19ab214a9b29833d766823ecd694fce3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Wed, 8 Feb 2023 14:26:47 +0100 Subject: [PATCH 3/3] access: Wrap three BitFlags into CompatAccess MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TODO: Squash with previous commit that adds CompatArg Signed-off-by: Mickaël Salaün --- src/access.rs | 31 +++++---- src/compat.rs | 172 ++++++++++++++++++++++++++++++++++++++++++++----- src/fs.rs | 16 ++--- src/lib.rs | 2 +- src/ruleset.rs | 6 +- 5 files changed, 189 insertions(+), 38 deletions(-) diff --git a/src/access.rs b/src/access.rs index a6033867..88d57ec2 100644 --- a/src/access.rs +++ b/src/access.rs @@ -1,5 +1,5 @@ use crate::{ - AccessError, AddRuleError, AddRulesError, BitFlags, CompatArg, CompatError, CompatResult, + AccessError, AddRuleError, AddRulesError, BitFlags, CompatAccess, CompatError, CompatResult, CompatibleArgument, HandleAccessError, HandleAccessesError, Ruleset, TailoredCompatLevel, TryCompat, ABI, }; @@ -8,14 +8,20 @@ use enumflags2::BitFlag; #[cfg(test)] use crate::{make_bitflags, AccessFs, CompatLevel, CompatState, Compatibility}; +/* pub trait Access where - Self: PrivateAccess + Self: PrivateAccess, + Into> - + Into>> + + Into>, + CompatibleArgument>, BitFlags: - Into>> + CompatibleArgument>, + Into>> + CompatibleArgument>, + Into>, +*/ +pub trait Access +where + Self: PrivateAccess, { /// Gets the access rights defined by a specific [`ABI`]. /// Union of [`from_read()`](Access::from_read) and [`from_write()`](Access::from_write). @@ -39,7 +45,8 @@ where pub trait PrivateAccess: BitFlag { fn ruleset_handle_access( ruleset: &mut Ruleset, - access: CompatArg>, + access: CompatAccess, + //access: CompatAccess>, ) -> Result<(), HandleAccessesError> where Self: Access; @@ -201,28 +208,30 @@ fn compat_bit_flags() { )); } -impl From for CompatArg> +/* +impl From> for CompatAccess where A: Access, { - fn from(access: A) -> Self { - let bitflags: BitFlags = access.into(); - bitflags.into() + fn from(access: BitFlags) -> Self { + // XXX: How? + access.into() } } +*/ impl CompatibleArgument for A where A: Access, { - type CompatSelf = BitFlags; + type CompatSelf = A; } impl CompatibleArgument for BitFlags where A: Access, { - type CompatSelf = Self; + type CompatSelf = A; } #[test] diff --git a/src/compat.rs b/src/compat.rs index 1d8a3693..c98c643f 100644 --- a/src/compat.rs +++ b/src/compat.rs @@ -470,40 +470,145 @@ pub enum Consequence { ReturnError, } -pub struct CompatArg { - inner: T, - if_unmet: Consequence, +use crate::BitFlags; + +// TODO: Remove Clone and Copy +#[derive(Clone, Copy)] +pub struct CompatAccess +where + A: Access, +{ + inner_continue: Option>, + inner_disable_ruleset: Option>, + inner_return_error: Option>, } -impl CompatArg { - pub fn unwrap_update(self, _current_abi: ABI, _compat_state: &mut CompatState) -> T { +impl CompatAccess +where + A: Access, +{ + pub fn unwrap_update(self, _current_abi: ABI, _compat_state: &mut CompatState) -> BitFlags { /* match self.disable_sandbox_if_unmet { // Similar to CompatLevel::SoftRequirement compat_state.update(CompatState::Dummy); } */ - self.inner + // FIXME: + self.inner_continue.unwrap() + } +} + +impl Default for CompatAccess +where + A: Access, +{ + fn default() -> Self { + Self { + inner_continue: None, + inner_disable_ruleset: None, + inner_return_error: None, + } } } -pub trait CompatibleArgument: Sized + Into { +impl CompatAccess +where + A: Access, +{ + // FIXME: Use CompatError + //fn try_inner(self, abi: ABI) -> Result>, CompatError> { + //fn try_compat_inner(self, abi: ABI) -> Result, A>, CompatError> { + fn try_compat_inner(self, abi: ABI) -> Result, UnmetError> { + let mut has_access = false; + if let Some(inner_return_error) = self.inner_return_error { + match inner_return_error.try_compat_inner(abi)? { + CompatResult::Full(_) => has_access = true, + //CompatResult::Partial(_, _) => return Err(UnmetError), + //CompatResult::No(_) => return Err(UnmetError), + // TODO: Include unmet access rights in UnmetError. + _ => return Err(UnmetError), + }; + } + if let Some(inner_disable_ruleset) = self.inner_disable_ruleset { + match inner_disable_ruleset.try_compat_inner(abi)? { + CompatResult::Full(_) => has_access = true, + // TODO: Include unmet access rights in DisableRuleset. + _ => return Ok(UnmetAction::DisableRuleset), + }; + } + if let Some(inner_continue) = self.inner_continue { + let _ = inner_continue.try_compat_inner(abi)?; + has_access = true; + } + if !has_access { + // FIXME: add dedicated error + return Err(UnmetError); + } + Ok(UnmetAction::Continue( + self.inner_return_error.unwrap_or_default() + | self.inner_disable_ruleset.unwrap_or_default() + | self.inner_continue.unwrap_or_default(), + )) + } +} + +pub trait CompatibleArgument +where + Self: Into>, + Self::CompatSelf: Access, +{ type CompatSelf; - fn if_unmet(self, consequence: Consequence) -> CompatArg { - CompatArg { - inner: self.into(), - if_unmet: consequence, + // TODO: Move if_unmet() to the CompatibleArgument trait (and keep its name for genericity), + // implemented for all Access implementation and all BitFlags. + //fn if_unmet(self, consequence: Consequence) -> Self { + fn if_unmet(self, consequence: Consequence) -> CompatAccess { + let compat_self = self.into(); + let has_access = compat_self.inner_continue.is_some() + || compat_self.inner_disable_ruleset.is_some() + || compat_self.inner_return_error.is_some(); + let option_access = || { + if has_access { + Some( + compat_self.inner_continue.unwrap_or_default() + | compat_self.inner_disable_ruleset.unwrap_or_default() + | compat_self.inner_return_error.unwrap_or_default(), + ) + } else { + None + } + }; + match consequence { + Consequence::Continue => CompatAccess { + inner_continue: option_access(), + ..Default::default() + }, + Consequence::DisableRuleset => CompatAccess { + inner_disable_ruleset: option_access(), + ..Default::default() + }, + Consequence::ReturnError => CompatAccess { + inner_return_error: option_access(), + ..Default::default() + }, } } } -impl From for CompatArg +impl From for CompatAccess where - T: CompatibleArgument, + A: Access, + B: Into>, + // TODO: Move as Access requirement + //A: CompatibleArgument, { - fn from(inner: T) -> Self { - inner.if_unmet(Consequence::default()) + fn from(access: B) -> Self { + // Best-effort approach by default: Consequence::Continue + Self { + inner_continue: Some(access.into()), + ..Default::default() + } } } @@ -735,3 +840,40 @@ where } } } + +use thiserror::Error; + +/* +#[derive(Debug, Error)] +#[error(transparent)] +pub struct UnmetError +where + A: Access, +( + #[from] A +); +*/ + +#[derive(Debug, Error)] +#[error("failed to meet the required access")] +pub struct UnmetError; + +impl From> for UnmetError +where + A: Access, +{ + fn from(_: CompatError) -> Self { + Self + } +} + +pub enum UnmetAction +where + A: Access, +{ + // Fully matches the request. + Continue(BitFlags), + // Partially matches the request. + //DisableRuleset(BitFlags), + DisableRuleset, +} diff --git a/src/fs.rs b/src/fs.rs index 325f4047..d4ce8d5f 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -1,9 +1,9 @@ use crate::compat::private::OptionCompatLevelMut; use crate::{ - uapi, Access, AddRuleError, AddRulesError, CompatArg, CompatError, CompatLevel, CompatResult, - CompatState, Compatible, HandleAccessError, HandleAccessesError, PathBeneathError, PathFdError, - PrivateAccess, PrivateRule, Rule, Ruleset, RulesetCreated, RulesetError, TailoredCompatLevel, - TryCompat, ABI, + uapi, Access, AddRuleError, AddRulesError, CompatAccess, CompatError, CompatLevel, + CompatResult, CompatState, Compatible, HandleAccessError, HandleAccessesError, + PathBeneathError, PathFdError, PrivateAccess, PrivateRule, Rule, Ruleset, RulesetCreated, + RulesetError, TailoredCompatLevel, TryCompat, ABI, }; use enumflags2::{bitflags, make_bitflags, BitFlags}; use std::fs::OpenOptions; @@ -142,7 +142,7 @@ impl AccessFs { impl PrivateAccess for AccessFs { fn ruleset_handle_access( ruleset: &mut Ruleset, - access: CompatArg>, + access: CompatAccess, ) -> Result<(), HandleAccessesError> { // FIXME: test compat state let access = access.unwrap_update(ABI::V1, &mut ruleset.compat.state); @@ -222,12 +222,12 @@ where /// The `parent` file descriptor will be automatically closed with the returned `PathBeneath`. pub fn new(parent: F, access: A) -> Self where - A: Into>>, + A: Into>, { // FIXME: // - properly handle and test compat state and ABI version // - don't call any kind of unwrap_update() here but set self.allowed_access with this - // CompatArg and deal with it later. + // CompatAccess and deal with it later. let mut compat_state = Default::default(); let access = access.into().unwrap_update(ABI::V1, &mut compat_state); PathBeneath { @@ -548,7 +548,7 @@ pub fn path_beneath_rules( where I: IntoIterator, P: AsRef, - A: Into>, + A: Into>, { let access = access.into(); paths.into_iter().filter_map(move |p| match PathFd::new(p) { diff --git a/src/lib.rs b/src/lib.rs index 2572a6ef..8e001d23 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -81,7 +81,7 @@ extern crate lazy_static; pub use access::Access; pub use compat::{ - CompatArg, CompatLevel, CompatMode, Compatible, CompatibleArgument, Consequence, ABI, + CompatAccess, CompatLevel, CompatMode, Compatible, CompatibleArgument, Consequence, ABI, }; pub use enumflags2::{make_bitflags, BitFlags}; pub use errors::{ diff --git a/src/ruleset.rs b/src/ruleset.rs index 82cbd6de..36a78f9a 100644 --- a/src/ruleset.rs +++ b/src/ruleset.rs @@ -1,6 +1,6 @@ use crate::compat::private::OptionCompatLevelMut; use crate::{ - uapi, Access, AccessFs, AddRuleError, AddRulesError, BitFlags, CompatArg, CompatLevel, + uapi, Access, AccessFs, AddRuleError, AddRulesError, BitFlags, CompatAccess, CompatLevel, CompatMode, CompatState, Compatibility, Compatible, CreateRulesetError, RestrictSelfError, RulesetError, TryCompat, }; @@ -228,7 +228,7 @@ impl Ruleset { /// In most cases we should use [`Ruleset::default()`] instead. pub fn new(mode: CompatMode, handle_access: T) -> Result where - T: Into>, + T: Into>, U: Access, { Self::default() @@ -348,7 +348,7 @@ pub trait RulesetAttr: Sized + AsMut + Compatible { /// E.g., `RulesetError::HandleAccesses(HandleAccessesError::Fs(HandleAccessError))` fn handle_access(mut self, access: T) -> Result where - T: Into>>, + T: Into>, //T: Into> // XXX: CompatibleArgument is not required but could help users U: Access, {