landlock

Struct Ruleset

source
pub struct Ruleset { /* private fields */ }
Expand description

Landlock ruleset builder.

Ruleset enables to create a Landlock ruleset in a flexible way following the builder pattern. Most build steps return a Result with RulesetError.

You should probably not create more than one ruleset per application. Creating multiple rulesets is only useful when gradually restricting an application (e.g., a first set of generic restrictions before reading any file, then a second set of tailored restrictions after reading the configuration).

§Simple example

Simple helper handling only Landlock-related errors.

use landlock::{
    Access, AccessFs, PathBeneath, PathFd, RestrictionStatus, Ruleset, RulesetAttr,
    RulesetCreatedAttr, RulesetError, ABI,
};
use std::os::unix::io::AsFd;

fn restrict_fd<T>(hierarchy: T) -> Result<RestrictionStatus, RulesetError>
where
    T: AsFd,
{
    // The Landlock ABI should be incremented (and tested) regularly.
    let abi = ABI::V1;
    let access_all = AccessFs::from_all(abi);
    let access_read = AccessFs::from_read(abi);
    Ok(Ruleset::default()
        .handle_access(access_all)?
        .create()?
        .add_rule(PathBeneath::new(hierarchy, access_read))?
        .restrict_self()?)
}

let fd = PathFd::new("/home").expect("failed to open /home");
let status = restrict_fd(fd).expect("failed to build the ruleset");

§Generic example

More generic helper handling a set of file hierarchies and multiple types of error (i.e. RulesetError and PathFdError.

use landlock::{
    Access, AccessFs, PathBeneath, PathFd, PathFdError, RestrictionStatus, Ruleset,
    RulesetAttr, RulesetCreatedAttr, RulesetError, ABI,
};
use thiserror::Error;

#[derive(Debug, Error)]
enum MyRestrictError {
    #[error(transparent)]
    Ruleset(#[from] RulesetError),
    #[error(transparent)]
    AddRule(#[from] PathFdError),
}

fn restrict_paths(hierarchies: &[&str]) -> Result<RestrictionStatus, MyRestrictError> {
    // The Landlock ABI should be incremented (and tested) regularly.
    let abi = ABI::V1;
    let access_all = AccessFs::from_all(abi);
    let access_read = AccessFs::from_read(abi);
    Ok(Ruleset::default()
        .handle_access(access_all)?
        .create()?
        .add_rules(
            hierarchies
                .iter()
                .map::<Result<_, MyRestrictError>, _>(|p| {
                    Ok(PathBeneath::new(PathFd::new(p)?, access_read))
                }),
        )?
        .restrict_self()?)
}

let status = restrict_paths(&["/usr", "/home"]).expect("failed to build the ruleset");

Implementations§

source§

impl Ruleset

source

pub fn new() -> Self

👎Deprecated: Use Ruleset::default() instead
source

pub fn create(self) -> Result<RulesetCreated, RulesetError>

Attempts to create a real Landlock ruleset (if supported by the running kernel). The returned RulesetCreated is also a builder.

On error, returns a wrapped CreateRulesetError.

Trait Implementations§

source§

impl AsMut<Ruleset> for Ruleset

source§

fn as_mut(&mut self) -> &mut Ruleset

Converts this type into a mutable reference of the (usually inferred) input type.
source§

impl Compatible for &mut Ruleset

source§

fn set_compatibility(self, level: CompatLevel) -> Self

To enable a best-effort security approach, Landlock features that are not supported by the running system are silently ignored by default, which is a sane choice for most use cases. However, on some rare circumstances, developers may want to have some guarantees that their applications will not run if a certain level of sandboxing is not possible. If we really want to error out when not all our requested requirements are met, then we can configure it with set_compatibility(). Read more
source§

fn set_best_effort(self, best_effort: bool) -> Self
where Self: Sized,

👎Deprecated: Use set_compatibility() instead
source§

impl Compatible for Ruleset

source§

fn set_compatibility(self, level: CompatLevel) -> Self

To enable a best-effort security approach, Landlock features that are not supported by the running system are silently ignored by default, which is a sane choice for most use cases. However, on some rare circumstances, developers may want to have some guarantees that their applications will not run if a certain level of sandboxing is not possible. If we really want to error out when not all our requested requirements are met, then we can configure it with set_compatibility(). Read more
source§

fn set_best_effort(self, best_effort: bool) -> Self
where Self: Sized,

👎Deprecated: Use set_compatibility() instead
source§

impl Default for Ruleset

source§

fn default() -> Self

Returns a new Ruleset. This call automatically probes the running kernel to know if it supports Landlock.

To be able to successfully call create(), it is required to set the handled accesses with handle_access().

source§

impl RulesetAttr for &mut Ruleset

source§

fn handle_access<T, U>(self, access: T) -> Result<Self, RulesetError>
where T: Into<BitFlags<U>>, U: Access,

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 with the previous handled accesses. Read more
source§

impl RulesetAttr for Ruleset

source§

fn handle_access<T, U>(self, access: T) -> Result<Self, RulesetError>
where T: Into<BitFlags<U>>, U: Access,

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 with the previous handled accesses. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.