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