Skip to main content

pnut_child/
spec.rs

1//! Typed child-runtime inputs.
2
3use core::ffi::{CStr, c_char};
4
5use crate::fd::FdAction;
6
7/// One complete child-runtime invocation.
8#[derive(Debug)]
9pub struct ChildSpec<'a> {
10    pub sync_fd: Option<libc::c_int>,
11    pub status_fd: Option<libc::c_int>,
12    pub process: ProcessSpec,
13    pub mounts: Option<MountPlan<'a>>,
14    pub hostname: Option<&'a CStr>,
15    pub bring_up_loopback: bool,
16    pub env: Option<EnvSpec<'a>>,
17    pub rlimits: Option<RlimitSpec<'a>>,
18    pub landlock: Option<LandlockSpec<'a>>,
19    pub caps: Option<CapsSpec<'a>>,
20    pub fds: FdSpec<'a>,
21    pub seccomp: Option<SeccompSpec>,
22    pub cwd: Option<&'a CStr>,
23    pub exec: ExecSpec<'a>,
24}
25
26/// Process toggles applied during child setup.
27#[derive(Clone, Copy, Debug, Default)]
28pub struct ProcessSpec {
29    pub pdeathsig: Option<libc::c_int>,
30    pub verify_parent_alive: bool,
31    pub dumpable: bool,
32    pub new_session: bool,
33    pub disable_tsc: bool,
34    pub no_new_privs: bool,
35    pub mdwe_flags: Option<libc::c_ulong>,
36}
37
38/// Prepared filesystem mount plan for child-side execution.
39#[derive(Clone, Copy, Debug)]
40pub struct MountPlan<'a> {
41    pub entries: &'a [MountEntry<'a>],
42}
43
44/// One filesystem mount operation.
45#[derive(Clone, Copy, Debug)]
46pub enum MountEntry<'a> {
47    Bind(BindMount<'a>),
48    Tmpfs(TmpfsMount<'a>),
49    Proc(ProcMount<'a>),
50    Mqueue(MqueueMount<'a>),
51    File(FileMount<'a>),
52}
53
54/// One bind-mount operation.
55#[derive(Clone, Copy, Debug)]
56pub struct BindMount<'a> {
57    pub src: &'a CStr,
58    pub dst_rel: &'a CStr,
59    pub src_is_dir: bool,
60    pub read_only: bool,
61}
62
63/// One tmpfs mount operation.
64#[derive(Clone, Copy, Debug)]
65pub struct TmpfsMount<'a> {
66    pub dst_rel: &'a CStr,
67    pub read_only: bool,
68    pub size_bytes: Option<u64>,
69    pub mode: Option<u32>,
70}
71
72/// Proc mount `subset=` option.
73#[derive(Clone, Copy, Debug, Eq, PartialEq)]
74pub enum ProcSubset {
75    Pid,
76}
77
78/// Proc mount `hidepid=` option.
79#[derive(Clone, Copy, Debug, Eq, PartialEq)]
80pub enum HidePid {
81    Visible,
82    Hidden,
83    Invisible,
84}
85
86/// One procfs mount operation.
87#[derive(Clone, Copy, Debug)]
88pub struct ProcMount<'a> {
89    pub dst_rel: &'a CStr,
90    pub subset: Option<ProcSubset>,
91    pub hidepid: Option<HidePid>,
92}
93
94/// One mqueue mount operation.
95#[derive(Clone, Copy, Debug)]
96pub struct MqueueMount<'a> {
97    pub dst_rel: &'a CStr,
98}
99
100/// One file-content injection operation.
101#[derive(Clone, Copy, Debug)]
102pub struct FileMount<'a> {
103    pub dst_rel: &'a CStr,
104    pub content: &'a [u8],
105    pub read_only: bool,
106}
107
108/// Borrowed view of a fully prepared exec request.
109#[derive(Clone, Copy, Debug)]
110pub struct ExecSpec<'a> {
111    pub path: &'a CStr,
112    pub argv: &'a [*const c_char],
113}
114
115/// Environment policy applied in the child into caller-provided scratch space.
116#[derive(Debug)]
117pub struct EnvSpec<'a> {
118    pub clear: bool,
119    pub keep: &'a [&'a CStr],
120    pub set: &'a [EnvBinding<'a>],
121    pub storage: EnvStorage<'a>,
122}
123
124/// One environment variable assignment.
125#[derive(Clone, Copy, Debug)]
126pub struct EnvBinding<'a> {
127    pub key: &'a CStr,
128    pub value: &'a CStr,
129}
130
131/// Scratch buffers for building the final `envp`.
132#[derive(Debug)]
133pub struct EnvStorage<'a> {
134    pub envp: &'a mut [*const c_char],
135    pub bytes: &'a mut [u8],
136}
137
138/// Prepared file-descriptor policy.
139#[derive(Clone, Copy, Debug)]
140pub struct FdSpec<'a> {
141    pub actions: &'a [FdAction],
142    pub keep: &'a [libc::c_int],
143    pub close_fds: bool,
144}
145
146impl Default for FdSpec<'_> {
147    fn default() -> Self {
148        Self {
149            actions: &[],
150            keep: &[],
151            close_fds: true,
152        }
153    }
154}
155
156/// Precomputed resource limits.
157#[derive(Clone, Copy, Debug)]
158pub struct RlimitSpec<'a> {
159    pub limits: &'a [RlimitEntry],
160}
161
162/// One `setrlimit` call.
163#[derive(Clone, Copy, Debug)]
164#[repr(C)]
165pub struct RlimitEntry {
166    pub resource: libc::c_int,
167    pub limit: libc::rlimit,
168}
169
170/// Prepared Landlock ruleset.
171#[derive(Clone, Copy, Debug)]
172pub struct LandlockSpec<'a> {
173    pub min_abi: u32,
174    pub ruleset: LandlockRulesetAttr,
175    pub path_rules: &'a [LandlockPathRule<'a>],
176    pub net_rules: &'a [LandlockNetRule],
177}
178
179/// Ruleset attributes passed to `landlock_create_ruleset`.
180#[derive(Clone, Copy, Debug, Default)]
181#[repr(C)]
182pub struct LandlockRulesetAttr {
183    pub handled_access_fs: u64,
184    pub handled_access_net: u64,
185}
186
187/// One `LANDLOCK_RULE_PATH_BENEATH` rule.
188#[derive(Clone, Copy, Debug)]
189pub struct LandlockPathRule<'a> {
190    pub path: &'a CStr,
191    pub allowed_access: u64,
192}
193
194/// One `LANDLOCK_RULE_NET_PORT` rule.
195#[derive(Clone, Copy, Debug)]
196#[repr(C)]
197pub struct LandlockNetRule {
198    pub port: u16,
199    pub allowed_access: u64,
200}
201
202/// Prepared Linux capability state.
203#[derive(Clone, Copy, Debug)]
204pub struct CapsSpec<'a> {
205    pub effective: [u32; 2],
206    pub permitted: [u32; 2],
207    pub inheritable: [u32; 2],
208    pub bounding_drop: &'a [u32],
209    pub clear_ambient: bool,
210}
211
212/// Prepared seccomp filter installation request.
213#[derive(Clone, Copy, Debug)]
214pub struct SeccompSpec {
215    pub program: libc::sock_fprog,
216    pub flags: u32,
217}