bob/sandbox/
sandbox_linux.rs1use crate::sandbox::Sandbox;
18use anyhow::Context;
19use std::fs;
20use std::path::Path;
21use std::process::{Command, ExitStatus, Stdio};
22
23impl Sandbox {
24 pub fn mount_bindfs(
25 &self,
26 src: &Path,
27 dest: &Path,
28 opts: &[&str],
29 ) -> anyhow::Result<Option<ExitStatus>> {
30 fs::create_dir_all(dest)?;
31 let cmd = "/bin/mount";
32 let mut mount_opts = vec!["bind"];
34 mount_opts.extend(opts.iter().copied());
35 let opts_str = mount_opts.join(",");
36 Ok(Some(
37 Command::new(cmd)
38 .arg("-o")
39 .arg(&opts_str)
40 .arg(src)
41 .arg(dest)
42 .status()
43 .context(format!("Unable to execute {}", cmd))?,
44 ))
45 }
46
47 pub fn mount_devfs(
48 &self,
49 _src: &Path,
50 dest: &Path,
51 opts: &[&str],
52 ) -> anyhow::Result<Option<ExitStatus>> {
53 fs::create_dir_all(dest)?;
54 let cmd = "/bin/mount";
55 Ok(Some(
56 Command::new(cmd)
57 .arg("-t")
58 .arg("devtmpfs")
59 .args(opts)
60 .arg("devtmpfs")
61 .arg(dest)
62 .status()
63 .context(format!("Unable to execute {}", cmd))?,
64 ))
65 }
66
67 pub fn mount_fdfs(
68 &self,
69 _src: &Path,
70 dest: &Path,
71 opts: &[&str],
72 ) -> anyhow::Result<Option<ExitStatus>> {
73 fs::create_dir_all(dest)?;
74 let cmd = "/bin/mount";
75 let mut mount_opts = vec!["bind"];
77 mount_opts.extend(opts.iter().copied());
78 let opts_str = mount_opts.join(",");
79 Ok(Some(
80 Command::new(cmd)
81 .arg("-o")
82 .arg(&opts_str)
83 .arg("/dev/fd")
84 .arg(dest)
85 .status()
86 .context(format!("Unable to execute {}", cmd))?,
87 ))
88 }
89
90 pub fn mount_nfs(
91 &self,
92 src: &Path,
93 dest: &Path,
94 opts: &[&str],
95 ) -> anyhow::Result<Option<ExitStatus>> {
96 fs::create_dir_all(dest)?;
97 let cmd = "/bin/mount";
98 Ok(Some(
99 Command::new(cmd)
100 .arg("-t")
101 .arg("nfs")
102 .args(opts)
103 .arg(src)
104 .arg(dest)
105 .status()
106 .context(format!("Unable to execute {}", cmd))?,
107 ))
108 }
109
110 pub fn mount_procfs(
111 &self,
112 _src: &Path,
113 dest: &Path,
114 opts: &[&str],
115 ) -> anyhow::Result<Option<ExitStatus>> {
116 fs::create_dir_all(dest)?;
117 let cmd = "/bin/mount";
118 Ok(Some(
119 Command::new(cmd)
120 .arg("-t")
121 .arg("proc")
122 .args(opts)
123 .arg("proc")
124 .arg(dest)
125 .status()
126 .context(format!("Unable to execute {}", cmd))?,
127 ))
128 }
129
130 pub fn mount_tmpfs(
131 &self,
132 _src: &Path,
133 dest: &Path,
134 opts: &[&str],
135 ) -> anyhow::Result<Option<ExitStatus>> {
136 fs::create_dir_all(dest)?;
137 let cmd = "/bin/mount";
138 let mut args = vec!["-t", "tmpfs"];
139 let mut mount_opts: Vec<String> = vec![];
141 for opt in opts {
142 if opt.starts_with("size=") || opt.starts_with("mode=") {
143 mount_opts.push(opt.to_string());
144 }
145 }
146 if !mount_opts.is_empty() {
147 args.push("-o");
148 }
149 let opts_str = mount_opts.join(",");
150 Ok(Some(
151 Command::new(cmd)
152 .args(&args)
153 .arg(if !mount_opts.is_empty() { &opts_str } else { "" })
154 .arg("tmpfs")
155 .arg(dest)
156 .status()
157 .context(format!("Unable to execute {}", cmd))?,
158 ))
159 }
160
161 fn unmount_common(
162 &self,
163 dest: &Path,
164 ) -> anyhow::Result<Option<ExitStatus>> {
165 let cmd = "/bin/umount";
166 Ok(Some(
167 Command::new(cmd)
168 .arg(dest)
169 .stdout(Stdio::null())
170 .stderr(Stdio::null())
171 .status()
172 .context(format!("Unable to execute {}", cmd))?,
173 ))
174 }
175
176 pub fn unmount_bindfs(
177 &self,
178 dest: &Path,
179 ) -> anyhow::Result<Option<ExitStatus>> {
180 self.unmount_common(dest)
181 }
182
183 pub fn unmount_devfs(
184 &self,
185 dest: &Path,
186 ) -> anyhow::Result<Option<ExitStatus>> {
187 self.unmount_common(dest)
188 }
189
190 pub fn unmount_fdfs(
191 &self,
192 dest: &Path,
193 ) -> anyhow::Result<Option<ExitStatus>> {
194 self.unmount_common(dest)
195 }
196
197 pub fn unmount_nfs(
198 &self,
199 dest: &Path,
200 ) -> anyhow::Result<Option<ExitStatus>> {
201 self.unmount_common(dest)
202 }
203
204 pub fn unmount_procfs(
205 &self,
206 dest: &Path,
207 ) -> anyhow::Result<Option<ExitStatus>> {
208 self.unmount_common(dest)
209 }
210
211 pub fn unmount_tmpfs(
212 &self,
213 dest: &Path,
214 ) -> anyhow::Result<Option<ExitStatus>> {
215 self.unmount_common(dest)
216 }
217
218 pub fn kill_processes(&self, sandbox: &Path) {
220 let _ = Command::new("fuser")
222 .arg("-k")
223 .arg(sandbox)
224 .stdout(Stdio::null())
225 .stderr(Stdio::null())
226 .status();
227
228 std::thread::sleep(std::time::Duration::from_millis(500));
230 }
231}