Skip to main content

qemu_command_builder/args/
sandbox.rs

1use crate::common::OnOff;
2use crate::parsers::{ARG_SANDBOX, DELIM_COMMA};
3use crate::to_command::{ToArg, ToCommand};
4use bon::Builder;
5use proptest_derive::Arbitrary;
6use std::str::FromStr;
7
8#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Arbitrary)]
9pub enum AllowDeny {
10    Allow,
11    Deny,
12}
13
14impl ToArg for AllowDeny {
15    fn to_arg(&self) -> &str {
16        match self {
17            AllowDeny::Allow => "allow",
18            AllowDeny::Deny => "deny",
19        }
20    }
21}
22#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Arbitrary)]
23pub enum AllowDenyChildren {
24    Allow,
25    Deny,
26    Children,
27}
28
29impl ToArg for AllowDenyChildren {
30    fn to_arg(&self) -> &str {
31        match self {
32            AllowDenyChildren::Allow => "allow",
33            AllowDenyChildren::Deny => "deny",
34            AllowDenyChildren::Children => "children",
35        }
36    }
37}
38#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder, Arbitrary)]
39pub struct Sandbox {
40    /// Whether seccomp sandboxing is enabled.
41    mode: OnOff,
42    /// Handling for obsolete syscalls.
43    obsolete: Option<AllowDeny>,
44    /// Privilege elevation policy.
45    elevateprivileges: Option<AllowDenyChildren>,
46    /// Process/thread spawning policy.
47    spawn: Option<AllowDeny>,
48    /// Resource control policy.
49    resourcecontrol: Option<AllowDeny>,
50}
51
52impl ToCommand for Sandbox {
53    fn command(&self) -> String {
54        ARG_SANDBOX.to_string()
55    }
56    fn to_args(&self) -> Vec<String> {
57        let mut args = vec![];
58        args.push(self.mode.to_arg().to_string());
59
60        if let Some(obsolete) = &self.obsolete {
61            args.push(format!("obsolete={}", obsolete.to_arg()));
62        }
63        if let Some(elevateprivileges) = &self.elevateprivileges {
64            args.push(format!("elevateprivileges={}", elevateprivileges.to_arg()))
65        }
66        if let Some(spawn) = &self.spawn {
67            args.push(format!("spawn={}", spawn.to_arg()));
68        }
69        if let Some(resourcecontrol) = &self.resourcecontrol {
70            args.push(format!("resourcecontrol={}", resourcecontrol.to_arg()));
71        }
72
73        vec![args.join(DELIM_COMMA)]
74    }
75}
76
77impl FromStr for Sandbox {
78    type Err = String;
79
80    fn from_str(s: &str) -> Result<Self, Self::Err> {
81        let mut parts = s.split(DELIM_COMMA);
82        let mode = parts
83            .next()
84            .ok_or_else(|| "empty -sandbox argument".to_string())?
85            .parse::<OnOff>()
86            .map_err(|_| format!("invalid sandbox mode: {s}"))?;
87
88        let mut obsolete = None;
89        let mut elevateprivileges = None;
90        let mut spawn = None;
91        let mut resourcecontrol = None;
92
93        for part in parts {
94            let (key, value) = part.split_once('=').ok_or_else(|| format!("invalid -sandbox option: {part}"))?;
95            match key {
96                "obsolete" => {
97                    obsolete = Some(match value {
98                        "allow" => AllowDeny::Allow,
99                        "deny" => AllowDeny::Deny,
100                        _ => return Err(format!("invalid obsolete value: {value}")),
101                    })
102                }
103                "elevateprivileges" => {
104                    elevateprivileges = Some(match value {
105                        "allow" => AllowDenyChildren::Allow,
106                        "deny" => AllowDenyChildren::Deny,
107                        "children" => AllowDenyChildren::Children,
108                        _ => return Err(format!("invalid elevateprivileges value: {value}")),
109                    })
110                }
111                "spawn" => {
112                    spawn = Some(match value {
113                        "allow" => AllowDeny::Allow,
114                        "deny" => AllowDeny::Deny,
115                        _ => return Err(format!("invalid spawn value: {value}")),
116                    })
117                }
118                "resourcecontrol" => {
119                    resourcecontrol = Some(match value {
120                        "allow" => AllowDeny::Allow,
121                        "deny" => AllowDeny::Deny,
122                        _ => return Err(format!("invalid resourcecontrol value: {value}")),
123                    })
124                }
125                other => return Err(format!("unsupported -sandbox option: {other}")),
126            }
127        }
128
129        Ok(Self {
130            mode,
131            obsolete,
132            elevateprivileges,
133            spawn,
134            resourcecontrol,
135        })
136    }
137}