Skip to content

Commit

Permalink
fs: Replace bitflags with enumflags2
Browse files Browse the repository at this point in the history
This is easier to use and more rusty.

Signed-off-by: Mickaël Salaün <mic@digikod.net>
  • Loading branch information
l0kod committed Oct 11, 2021
1 parent 583474c commit 282090a
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 62 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ exclude = [".gitignore"]
readme = "README.md"

[dependencies]
bitflags = "1.2"
enumflags2 = "0.7"
libc = "0.2"

[dev-dependencies]
Expand Down
32 changes: 12 additions & 20 deletions examples/sandboxer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use anyhow::{anyhow, bail};
use landlock::{
AccessFs, Compat, Compatibility, ErrorThreshold, PathBeneath, RulesetCreated, RulesetInit, ABI,
make_bitflags, AccessFs, BitFlags, Compat, Compatibility, ErrorThreshold, PathBeneath,
RulesetCreated, RulesetInit, ABI,
};
use nix::fcntl::{open, OFlag};
use nix::sys::stat::{fstat, Mode, SFlag};
Expand All @@ -14,26 +15,17 @@ use std::process::Command;
const ENV_FS_RO_NAME: &str = "LL_FS_RO";
const ENV_FS_RW_NAME: &str = "LL_FS_RW";

const ACCESS_FS_ROUGHLY_READ: AccessFs = AccessFs::from_bits_truncate(
AccessFs::EXECUTE.bits() | AccessFs::READ_FILE.bits() | AccessFs::READ_DIR.bits(),
);
const ACCESS_FS_ROUGHLY_READ: BitFlags<AccessFs> = make_bitflags!(AccessFs::{
Execute | ReadFile | ReadDir});

const ACCESS_FS_ROUGHLY_WRITE: AccessFs = AccessFs::from_bits_truncate(
AccessFs::WRITE_FILE.bits()
| AccessFs::REMOVE_DIR.bits()
| AccessFs::REMOVE_FILE.bits()
| AccessFs::MAKE_CHAR.bits()
| AccessFs::MAKE_DIR.bits()
| AccessFs::MAKE_REG.bits()
| AccessFs::MAKE_SOCK.bits()
| AccessFs::MAKE_FIFO.bits()
| AccessFs::MAKE_BLOCK.bits()
| AccessFs::MAKE_SYM.bits(),
);
const ACCESS_FS_ROUGHLY_WRITE: BitFlags<AccessFs> = make_bitflags!(AccessFs::{
WriteFile | RemoveDir | RemoveFile | MakeChar | MakeDir | MakeReg | MakeSock | MakeFifo |
MakeBlock | MakeSym
});

const ACCESS_FILE: AccessFs = AccessFs::from_bits_truncate(
AccessFs::READ_FILE.bits() | AccessFs::WRITE_FILE.bits() | AccessFs::EXECUTE.bits(),
);
const ACCESS_FILE: BitFlags<AccessFs> = make_bitflags!(AccessFs::{
ReadFile | WriteFile | Execute
});

/// Populates a given ruleset with PathBeneath landlock rules
///
Expand All @@ -50,7 +42,7 @@ fn populate_ruleset(
compat: &Compatibility,
ruleset: Compat<RulesetCreated>,
paths: OsString,
access: AccessFs,
access: BitFlags<AccessFs>,
) -> Result<Compat<RulesetCreated>, anyhow::Error> {
if paths.len() == 0 {
return Ok(ruleset);
Expand Down
74 changes: 39 additions & 35 deletions src/fs.rs
Original file line number Diff line number Diff line change
@@ -1,44 +1,48 @@
use super::{uapi, Compat, Compatibility, Rule, ABI};
use enumflags2::{bitflags, make_bitflags, BitFlags};
use std::io::Error;
use std::marker::PhantomData;
use std::os::unix::io::AsRawFd;

bitflags! {
pub struct AccessFs: u64 {
const EXECUTE = uapi::LANDLOCK_ACCESS_FS_EXECUTE as u64;
const WRITE_FILE = uapi::LANDLOCK_ACCESS_FS_WRITE_FILE as u64;
const READ_FILE = uapi::LANDLOCK_ACCESS_FS_READ_FILE as u64;
const READ_DIR = uapi::LANDLOCK_ACCESS_FS_READ_DIR as u64;
const REMOVE_DIR = uapi::LANDLOCK_ACCESS_FS_REMOVE_DIR as u64;
const REMOVE_FILE = uapi::LANDLOCK_ACCESS_FS_REMOVE_FILE as u64;
const MAKE_CHAR = uapi::LANDLOCK_ACCESS_FS_MAKE_CHAR as u64;
const MAKE_DIR = uapi::LANDLOCK_ACCESS_FS_MAKE_DIR as u64;
const MAKE_REG = uapi::LANDLOCK_ACCESS_FS_MAKE_REG as u64;
const MAKE_SOCK = uapi::LANDLOCK_ACCESS_FS_MAKE_SOCK as u64;
const MAKE_FIFO = uapi::LANDLOCK_ACCESS_FS_MAKE_FIFO as u64;
const MAKE_BLOCK = uapi::LANDLOCK_ACCESS_FS_MAKE_BLOCK as u64;
const MAKE_SYM = uapi::LANDLOCK_ACCESS_FS_MAKE_SYM as u64;
}
/// WARNING: Don't use `BitFlags::<AccessFs>::all()` nor `BitFlags::ALL` but `ABI::V1.into()`
/// instead.
#[bitflags]
#[repr(u64)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum AccessFs {
Execute = uapi::LANDLOCK_ACCESS_FS_EXECUTE as u64,
WriteFile = uapi::LANDLOCK_ACCESS_FS_WRITE_FILE as u64,
ReadFile = uapi::LANDLOCK_ACCESS_FS_READ_FILE as u64,
ReadDir = uapi::LANDLOCK_ACCESS_FS_READ_DIR as u64,
RemoveDir = uapi::LANDLOCK_ACCESS_FS_REMOVE_DIR as u64,
RemoveFile = uapi::LANDLOCK_ACCESS_FS_REMOVE_FILE as u64,
MakeChar = uapi::LANDLOCK_ACCESS_FS_MAKE_CHAR as u64,
MakeDir = uapi::LANDLOCK_ACCESS_FS_MAKE_DIR as u64,
MakeReg = uapi::LANDLOCK_ACCESS_FS_MAKE_REG as u64,
MakeSock = uapi::LANDLOCK_ACCESS_FS_MAKE_SOCK as u64,
MakeFifo = uapi::LANDLOCK_ACCESS_FS_MAKE_FIFO as u64,
MakeBlock = uapi::LANDLOCK_ACCESS_FS_MAKE_BLOCK as u64,
MakeSym = uapi::LANDLOCK_ACCESS_FS_MAKE_SYM as u64,
}

impl From<ABI> for AccessFs {
impl From<ABI> for BitFlags<AccessFs> {
fn from(abi: ABI) -> Self {
match abi {
ABI::V1 => AccessFs::from_bits_truncate(
AccessFs::EXECUTE.bits()
| AccessFs::WRITE_FILE.bits()
| AccessFs::READ_FILE.bits()
| AccessFs::READ_DIR.bits()
| AccessFs::REMOVE_DIR.bits()
| AccessFs::REMOVE_FILE.bits()
| AccessFs::MAKE_CHAR.bits()
| AccessFs::MAKE_DIR.bits()
| AccessFs::MAKE_REG.bits()
| AccessFs::MAKE_SOCK.bits()
| AccessFs::MAKE_FIFO.bits()
| AccessFs::MAKE_BLOCK.bits()
| AccessFs::MAKE_SYM.bits(),
),
ABI::V1 => make_bitflags!(AccessFs::{
Execute
| WriteFile
| ReadFile
| ReadDir
| RemoveDir
| RemoveFile
| MakeChar
| MakeDir
| MakeReg
| MakeSock
| MakeFifo
| MakeBlock
| MakeSym
}),
}
}
}
Expand All @@ -56,10 +60,10 @@ impl PathBeneath<'_> {
{
compat.create(1, || {
// By default, allows all v1 accesses on this path exception.
let allowed: AccessFs = ABI::V1.into();
let allowed: BitFlags<AccessFs> = ABI::V1.into();
PathBeneath {
attr: uapi::landlock_path_beneath_attr {
allowed_access: allowed.bits,
allowed_access: allowed.bits(),
parent_fd: parent.as_raw_fd(),
},
_parent_fd: PhantomData,
Expand All @@ -84,7 +88,7 @@ impl Rule for PathBeneath<'_> {

impl Compat<PathBeneath<'_>> {
// TODO: Replace with `append_allowed_accesses()`?
pub fn allow_access(self, allowed: AccessFs) -> Result<Self, Error> {
pub fn allow_access(self, allowed: BitFlags<AccessFs>) -> Result<Self, Error> {
self.update(1, |mut data| {
data.attr.allowed_access = allowed.bits();
// TODO: Checks supported bitflags and update accordingly.
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#[macro_use]
extern crate bitflags;
extern crate enumflags2;

pub use enumflags2::{make_bitflags, BitFlags};
pub use fs::{AccessFs, PathBeneath};
pub use ruleset::{RestrictionStatus, Rule, RulesetCreated, RulesetInit};
use std::io::{Error, ErrorKind};
Expand Down Expand Up @@ -284,7 +284,7 @@ mod tests {
RulesetInit::new(&compat)?
// Must have at least the execute check…
.set_error_threshold(ErrorThreshold::PartiallyCompatible)
.handle_fs(AccessFs::EXECUTE)?
.handle_fs(AccessFs::Execute.into())?
.set_error_threshold(ErrorThreshold::NoError)
// …and possibly others.
.handle_fs(ABI::V1.into())?
Expand Down
6 changes: 3 additions & 3 deletions src/ruleset.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::uapi;
use super::{AccessFs, Compat, CompatStatus, Compatibility, ABI};
use super::{AccessFs, BitFlags, Compat, CompatStatus, Compatibility, ABI};
use libc::close;
use std::io::Error;
use std::mem::size_of_val;
Expand Down Expand Up @@ -45,7 +45,7 @@ fn prctl_set_no_new_privs() -> Result<(), Error> {
}

pub struct RulesetInit {
handled_fs: AccessFs,
handled_fs: BitFlags<AccessFs>,
}

impl RulesetInit {
Expand All @@ -61,7 +61,7 @@ impl RulesetInit {
}

impl Compat<RulesetInit> {
pub fn handle_fs(self, access: AccessFs) -> Result<Self, Error> {
pub fn handle_fs(self, access: BitFlags<AccessFs>) -> Result<Self, Error> {
self.update(1, |mut data| {
data.handled_fs = access;
// TODO: Check compatibility and update it accordingly.
Expand Down

0 comments on commit 282090a

Please sign in to comment.