Skip to main content

sandlock_core/
lib.rs

1pub mod error;
2pub mod policy;
3pub mod profile;
4pub mod result;
5pub mod sandbox;
6pub(crate) mod sys;
7pub mod landlock;
8pub mod seccomp;
9pub(crate) mod resource;
10pub(crate) mod network;
11pub mod context;
12pub(crate) mod vdso;
13pub(crate) mod random;
14pub(crate) mod time;
15pub(crate) mod cow;
16pub(crate) mod checkpoint;
17pub(crate) mod procfs;
18pub(crate) mod port_remap;
19pub mod pipeline;
20pub mod policy_fn;
21pub mod image;
22pub mod fork;
23pub(crate) mod chroot;
24pub mod dry_run;
25
26pub use error::SandlockError;
27pub use checkpoint::Checkpoint;
28pub use policy::{Policy, PolicyBuilder};
29pub use result::{RunResult, ExitStatus};
30pub use sandbox::Sandbox;
31pub use pipeline::{Stage, Pipeline};
32pub use dry_run::{Change, ChangeKind, DryRunResult};
33
34/// Query the Landlock ABI version supported by the running kernel.
35pub fn landlock_abi_version() -> Result<u32, error::ConfinementError> {
36    landlock::abi_version()
37}
38
39/// Minimum Landlock ABI version required by sandlock.
40pub const MIN_LANDLOCK_ABI: u32 = landlock::MIN_ABI;
41
42/// Confine the calling process with Landlock restrictions.
43///
44/// This applies `PR_SET_NO_NEW_PRIVS` and Landlock rules from the policy's
45/// filesystem (`fs_readable`, `fs_writable`), IPC (`isolate_ipc`), and
46/// signal (`isolate_signals`) fields. The confinement is **irreversible**.
47///
48/// `fs_denied` is not enforced here because it requires supervisor-mediated
49/// path interception rather than Landlock's allowlist model.
50///
51/// Network, seccomp, resource limits, and other policy fields are ignored.
52///
53/// This does NOT fork or exec — it confines the current process in-place.
54pub fn confine_current_process(policy: &Policy) -> Result<(), SandlockError> {
55    // Set NO_NEW_PRIVS (required for Landlock)
56    if unsafe { libc::prctl(libc::PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) } != 0 {
57        return Err(SandlockError::Sandbox(
58            error::SandboxError::Confinement(
59                error::ConfinementError::Landlock(format!(
60                    "prctl(PR_SET_NO_NEW_PRIVS): {}",
61                    std::io::Error::last_os_error()
62                ))
63            )
64        ));
65    }
66
67    // Build a stripped policy with only Landlock-native fields that
68    // confine_current_process supports: filesystem + IPC + signals.
69    // Network port rules are excluded — they require the full sandbox.
70    let mut stripped = policy.clone();
71    stripped.net_bind.clear();
72    stripped.net_connect.clear();
73
74    // Apply Landlock rules
75    landlock::confine(&stripped)
76}