Skip to main content

proot/
sys.rs

1//! Raw kernel ABI not covered (or not covered stably) by the `libc` crate:
2//! the seccomp user-notification structures and ioctls, plus small helpers.
3//!
4//! Layouts are the x86_64 ones from `linux/seccomp.h`; they were checked
5//! against the C compiler before being written down here.
6#![allow(dead_code)]
7
8/// `errno`-style error: a positive errno value.
9pub type Errno = i32;
10
11/// Result alias used throughout the crate.
12pub type Result<T> = std::result::Result<T, Errno>;
13
14/// Returns the calling thread's current `errno`.
15pub fn errno() -> Errno {
16    std::io::Error::last_os_error()
17        .raw_os_error()
18        .unwrap_or(libc::EIO)
19}
20
21/// Converts a raw syscall return value into a [`Result`].
22///
23/// # Arguments
24/// * `rc` - Return value of a libc call or raw syscall.
25pub fn check(rc: i64) -> Result<i64> {
26    if rc < 0 { Err(errno()) } else { Ok(rc) }
27}
28
29/// Mirror of `struct seccomp_data`.
30#[repr(C)]
31#[derive(Clone, Copy, Default, Debug)]
32pub struct SeccompData {
33    pub nr: i32,
34    pub arch: u32,
35    pub instruction_pointer: u64,
36    pub args: [u64; 6],
37}
38
39/// Mirror of `struct seccomp_notif` (80 bytes).
40#[repr(C)]
41#[derive(Clone, Copy, Default, Debug)]
42pub struct SeccompNotif {
43    pub id: u64,
44    pub pid: u32,
45    pub flags: u32,
46    pub data: SeccompData,
47}
48
49/// Mirror of `struct seccomp_notif_resp` (24 bytes).
50#[repr(C)]
51#[derive(Clone, Copy, Default, Debug)]
52pub struct SeccompNotifResp {
53    pub id: u64,
54    pub val: i64,
55    pub error: i32,
56    pub flags: u32,
57}
58
59/// Mirror of `struct seccomp_notif_addfd` (24 bytes).
60#[repr(C)]
61#[derive(Clone, Copy, Default, Debug)]
62pub struct SeccompNotifAddfd {
63    pub id: u64,
64    pub flags: u32,
65    pub srcfd: u32,
66    pub newfd: u32,
67    pub newfd_flags: u32,
68}
69
70pub const SECCOMP_IOCTL_NOTIF_RECV: u64 = 0xc050_2100;
71pub const SECCOMP_IOCTL_NOTIF_SEND: u64 = 0xc018_2101;
72pub const SECCOMP_IOCTL_NOTIF_ID_VALID: u64 = 0x4008_2102;
73pub const SECCOMP_IOCTL_NOTIF_ADDFD: u64 = 0x4018_2103;
74pub const SECCOMP_FILTER_FLAG_NEW_LISTENER: u64 = 1 << 3;
75pub const SECCOMP_USER_NOTIF_FLAG_CONTINUE: u32 = 1;
76pub const SECCOMP_ADDFD_FLAG_SETFD: u32 = 1;
77pub const SECCOMP_ADDFD_FLAG_SEND: u32 = 2;
78pub const SECCOMP_RET_ALLOW: u32 = 0x7fff_0000;
79pub const SECCOMP_RET_TRACE: u32 = 0x7ff0_0000;
80pub const SECCOMP_RET_USER_NOTIF: u32 = 0x7fc0_0000;
81pub const SECCOMP_RET_ERRNO: u32 = 0x0005_0000;
82pub const SECCOMP_SET_MODE_FILTER: i64 = 1;
83pub const AUDIT_ARCH_X86_64: u32 = 0xc000_003e;
84pub const AUDIT_ARCH_I386: u32 = 0x4000_0003;
85pub const AUDIT_ARCH_AARCH64: u32 = 0xc000_00b7;
86pub const AUDIT_ARCH_ARM: u32 = 0x4000_0028;
87
88/// Maximum path length we read out of a tracee.
89pub const PATH_MAX: usize = 4096;
90
91/// Bytes a 64-bit ABI guarantees below the stack pointer (the red zone).
92pub const RED_ZONE_SIZE: u64 = 128;
93
94/// Formats an errno for log messages.
95pub fn strerror(e: Errno) -> String {
96    std::io::Error::from_raw_os_error(e).to_string()
97}
98
99/// Logs to stderr when `verbose` is at least `level`.
100#[macro_export]
101macro_rules! note {
102    ($ctx:expr, $level:expr, $($arg:tt)*) => {
103        if $ctx.config.verbose >= $level { eprintln!("proot: {}", format!($($arg)*)); }
104    };
105}