Skip to content

Commit 03d28b3

Browse files
committed
Fix linux build
1 parent babaf05 commit 03d28b3

File tree

5 files changed

+155
-49
lines changed

5 files changed

+155
-49
lines changed

src/linux.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ use std::{
2424
fs,
2525
os::unix::io::IntoRawFd,
2626
path::PathBuf,
27-
sync::atomic::{AtomicI64, Ordering},
28-
sync::Arc,
27+
sync::{
28+
atomic::{AtomicI64, Ordering},
29+
Arc,
30+
},
2931
time::Duration,
3032
};
3133

@@ -36,7 +38,7 @@ pub struct LinuxChildProcess {
3638
stdin: Option<LinuxWritePipe>,
3739
stdout: Option<LinuxReadPipe>,
3840
stderr: Option<LinuxReadPipe>,
39-
sandbox_ref: LinuxSandbox,
41+
sandbox_ref: Arc<LinuxSandbox>,
4042

4143
pid: Pid,
4244
}

src/linux/sandbox.rs

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,12 @@ struct LinuxSandboxDebugHelper<'a> {
7474
impl Debug for LinuxSandbox {
7575
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7676
let h = LinuxSandboxDebugHelper {
77-
id: &self.0.id,
78-
options: &self.0.options,
79-
zygote_sock: self.0.zygote_sock.lock().unwrap().as_raw_fd(),
80-
zygote_pid: self.0.zygote_pid,
81-
watchdog_chan: self.0.watchdog_chan,
82-
state: self.0.state.snapshot(),
77+
id: &self.id,
78+
options: &self.options,
79+
zygote_sock: self.zygote_sock.lock().unwrap().as_raw_fd(),
80+
zygote_pid: self.zygote_pid,
81+
watchdog_chan: self.watchdog_chan,
82+
state: self.state.snapshot(),
8383
};
8484

8585
h.fmt(f)
@@ -89,29 +89,29 @@ impl Debug for LinuxSandbox {
8989
impl Sandbox for LinuxSandbox {
9090
type Error = Error;
9191

92-
fn id(&self) -> String {
93-
self.0.id
92+
fn id(&self) -> &str {
93+
&self.id
9494
}
9595

9696
fn check_cpu_tle(&self) -> Result<bool, Error> {
9797
self.poll_state()?;
98-
Ok(self.0.state.was_cpu_tle.load(SeqCst))
98+
Ok(self.state.was_cpu_tle.load(SeqCst))
9999
}
100100

101101
fn check_real_tle(&self) -> Result<bool, Error> {
102102
self.poll_state()?;
103-
Ok(self.0.state.was_wall_tle.load(SeqCst))
103+
Ok(self.state.was_wall_tle.load(SeqCst))
104104
}
105105

106106
fn kill(&self) -> Result<(), Error> {
107-
jail_common::kill_sandbox(self.0.zygote_pid, &self.0.id, &self.0.cgroup_driver)
107+
jail_common::kill_sandbox(self.zygote_pid, &self.id, &self.cgroup_driver)
108108
.map_err(|err| Error::Io { source: err })?;
109109
Ok(())
110110
}
111111

112112
fn resource_usage(&self) -> Result<crate::ResourceUsageData, Error> {
113-
let cpu_usage = self.0.cgroup_driver.get_cpu_usage(&self.0.id);
114-
let memory_usage = self.0.cgroup_driver.get_memory_usage(&self.0.id);
113+
let cpu_usage = self.cgroup_driver.get_cpu_usage(&self.id);
114+
let memory_usage = self.cgroup_driver.get_memory_usage(&self.id);
115115
Ok(crate::ResourceUsageData {
116116
memory: memory_usage,
117117
time: Some(cpu_usage),
@@ -142,7 +142,7 @@ impl LinuxSandbox {
142142
break;
143143
}
144144
for ch in &buf[..num_read] {
145-
self.0.state.process_flag(*ch)?;
145+
self.state.process_flag(*ch)?;
146146
}
147147
}
148148

@@ -154,7 +154,7 @@ impl LinuxSandbox {
154154
settings: &crate::linux::Settings,
155155
cgroup_driver: Arc<crate::linux::cgroup::Driver>,
156156
) -> Result<LinuxSandbox, Error> {
157-
let jail_id = jail_common::gen_jail_id();
157+
let jail_id = crate::util::gen_jail_id();
158158
let mut read_end = 0;
159159
let mut write_end = 0;
160160
setup_pipe(&mut read_end, &mut write_end)?;
@@ -176,7 +176,7 @@ impl LinuxSandbox {
176176
};
177177
let startup_info = zygote::start_zygote(jail_options, &cgroup_driver)?;
178178

179-
let inner = LinuxSandboxInner {
179+
let sandbox = LinuxSandbox {
180180
id: jail_id,
181181
options,
182182
zygote_sock: Mutex::new(startup_info.socket),
@@ -189,7 +189,7 @@ impl LinuxSandbox {
189189
cgroup_driver,
190190
};
191191

192-
Ok(LinuxSandbox(Arc::new(inner)))
192+
Ok(sandbox)
193193
}
194194

195195
pub(crate) unsafe fn spawn_job(
@@ -198,7 +198,7 @@ impl LinuxSandbox {
198198
) -> Option<jail_common::JobStartupInfo> {
199199
let q = jail_common::Query::Spawn(query.job_query.clone());
200200

201-
let mut sock = self.0.zygote_sock.lock().unwrap();
201+
let mut sock = self.zygote_sock.lock().unwrap();
202202

203203
// note that we ignore errors, because zygote can be already killed for some reason
204204
sock.send(&q).ok();
@@ -211,7 +211,7 @@ impl LinuxSandbox {
211211

212212
pub(crate) unsafe fn poll_job(&self, pid: Pid, timeout: Option<Duration>) -> Option<ExitCode> {
213213
let q = jail_common::Query::Poll(jail_common::PollQuery { pid, timeout });
214-
let mut sock = self.0.zygote_sock.lock().unwrap();
214+
let mut sock = self.zygote_sock.lock().unwrap();
215215
sock.send(&q).ok();
216216
match sock.recv::<Option<i32>>() {
217217
Ok(x) => x.map(Into::into),
@@ -222,24 +222,18 @@ impl LinuxSandbox {
222222

223223
impl Drop for LinuxSandbox {
224224
fn drop(&mut self) {
225-
match Arc::get_mut(&mut self.0) {
226-
// we are last Sandbox handle, so we can drop it
227-
Some(_) => (),
228-
// there are other handles, so we must not do anyhing
229-
None => return,
230-
};
231225
// Kill all processes.
232226
if let Err(err) = self.kill() {
233227
panic!("unable to kill sandbox: {}", err);
234228
}
235229
// Remove cgroups.
236230
if std::env::var("MINION_DEBUG_KEEP_CGROUPS").is_err() {
237-
self.0
231+
self
238232
.cgroup_driver
239-
.drop_cgroup(&self.0.id, &["pids", "memory", "cpuacct"]);
233+
.drop_cgroup(&self.id, &["pids", "memory", "cpuacct"]);
240234
}
241235

242236
// Close handles
243-
nix::unistd::close(self.0.watchdog_chan).ok();
237+
nix::unistd::close(self.watchdog_chan).ok();
244238
}
245239
}

src/windows.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,6 @@ impl crate::Backend for WindowsBackend {
3838
&self,
3939
options: crate::ChildProcessOptions<Self::Sandbox>,
4040
) -> Result<Self::ChildProcess, Self::Error> {
41-
todo!()
41+
child::WindowsChildProcess::create_process()
4242
}
4343
}

src/windows/child.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ use std::{
77
sync::atomic::{AtomicU32, Ordering::Relaxed},
88
time::Duration,
99
};
10-
use winapi::um::{minwinbase::STILL_ACTIVE, winnt::HANDLE};
10+
use winapi::um::{
11+
handleapi::CloseHandle, minwinbase::STILL_ACTIVE, processthreadsapi::PROCESS_INFORMATION,
12+
winnt::HANDLE,
13+
};
1114

1215
#[derive(Debug)]
1316
pub struct WindowsChildProcess {
@@ -28,7 +31,20 @@ pub struct WindowsChildProcess {
2831
stderr: Option<ReadPipe>,
2932
}
3033

31-
impl WindowsChildProcess {}
34+
impl Drop for WindowsChildProcess {
35+
fn drop(&mut self) {
36+
unsafe {
37+
CloseHandle(self.main_thread);
38+
CloseHandle(self.child);
39+
}
40+
}
41+
}
42+
43+
impl WindowsChildProcess {
44+
pub(in crate::windows) fn create_process() -> Result<Self, Error> {
45+
todo!()
46+
}
47+
}
3248

3349
impl crate::ChildProcess for WindowsChildProcess {
3450
type Error = Error;

src/windows/spawn.rs

Lines changed: 109 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,26 @@ use crate::windows::{
33
pipe::{self, ReadPipe, WritePipe},
44
Cvt, Error, WindowsSandbox,
55
};
6-
use std::mem::size_of;
7-
use winapi::um::{
8-
minwinbase::SECURITY_ATTRIBUTES,
9-
processthreadsapi::{
10-
CreateProcessW, DeleteProcThreadAttributeList, InitializeProcThreadAttributeList,
11-
UpdateProcThreadAttribute, PROC_THREAD_ATTRIBUTE_LIST,
12-
},
13-
userenv::{CreateAppContainerProfile, DeleteAppContainerProfile},
14-
winbase::{
15-
CREATE_UNICODE_ENVIRONMENT, EXTENDED_STARTUPINFO_PRESENT, STARTF_USESTDHANDLES,
16-
STARTUPINFOEXW,
6+
use std::{
7+
ffi::{OsStr, OsString},
8+
mem::size_of,
9+
os::windows::ffi::OsStrExt,
10+
};
11+
use winapi::{
12+
shared::minwindef::TRUE,
13+
um::{
14+
minwinbase::SECURITY_ATTRIBUTES,
15+
processthreadsapi::{
16+
CreateProcessW, DeleteProcThreadAttributeList, InitializeProcThreadAttributeList,
17+
UpdateProcThreadAttribute, PROCESS_INFORMATION, PROC_THREAD_ATTRIBUTE_LIST,
18+
},
19+
userenv::{CreateAppContainerProfile, DeleteAppContainerProfile},
20+
winbase::{
21+
CREATE_UNICODE_ENVIRONMENT, EXTENDED_STARTUPINFO_PRESENT, STARTF_USESTDHANDLES,
22+
STARTUPINFOEXW,
23+
},
24+
winnt::{HANDLE, SECURITY_CAPABILITIES},
1725
},
18-
winnt::{SECURITY_CAPABILITIES, HANDLE},
1926
};
2027

2128
pub(in crate::windows) struct Stdio {
@@ -24,16 +31,25 @@ pub(in crate::windows) struct Stdio {
2431
pub stderr: HANDLE,
2532
}
2633

34+
pub(in crate::windows) struct ChildParams {
35+
pub exe: OsString,
36+
/// Does not contain argv[0] - will be prepended automatically.
37+
pub argv: Vec<OsString>,
38+
pub env: Vec<OsString>,
39+
pub cwd: OsString,
40+
}
41+
2742
// TODO: upstream to winapi: https://github.com/retep998/winapi-rs/pull/933/
2843
const MAGIC_PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES: usize = 131081;
2944

3045
pub(in crate::windows) fn spawn(
3146
sandbox: &WindowsSandbox,
3247
stdio: Stdio,
33-
) -> Result<WindowsChildProcess, Error> {
48+
params: ChildParams,
49+
) -> Result<PROCESS_INFORMATION, Error> {
3450
let mut proc_thread_attr_list_storage: Vec<u64>;
3551
let mut security_capabilities;
36-
let startup_info = unsafe {
52+
let mut startup_info = unsafe {
3753
let mut startup_info: STARTUPINFOEXW = std::mem::zeroed();
3854
let mut proc_thread_attr_list_len = 0;
3955
Cvt::nonzero(InitializeProcThreadAttributeList(
@@ -72,6 +88,84 @@ pub(in crate::windows) fn spawn(
7288
startup_info
7389
};
7490
let creation_flags = CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT;
91+
let mut info: PROCESS_INFORMATION = unsafe { std::mem::zeroed() };
92+
unsafe {
93+
let application_name: Vec<u16> = params.exe.encode_wide().collect();
94+
let mut cmd_line = application_name.clone();
95+
for arg in params.argv {
96+
quote_arg(&mut cmd_line, &arg);
97+
}
98+
let (mut env, env_status) = encode_env(&params.env);
99+
if let EncodeEnvResult::Partial = env_status {
100+
tracing::warn!("skipped zero chars in provided environment");
101+
}
102+
let cwd: Vec<u16> = params.cwd.encode_wide().collect();
103+
Cvt::nonzero(CreateProcessW(
104+
application_name.as_ptr(),
105+
cmd_line.as_mut_ptr(),
106+
// pass null as process attributes to disallow inheritance
107+
std::ptr::null_mut(),
108+
// same for thread
109+
std::ptr::null_mut(),
110+
// inherit handles
111+
TRUE,
112+
creation_flags,
113+
env.as_mut_ptr().cast(),
114+
cwd.as_ptr(),
115+
(&mut startup_info as *mut STARTUPINFOEXW).cast(),
116+
&mut info,
117+
))?;
118+
}
119+
Ok(info)
120+
}
121+
122+
fn ascii_to_u16(ch: u8) -> u16 {
123+
let ch = ch as char;
124+
let mut out: u16 = 0;
125+
ch.encode_utf16(std::slice::from_mut(&mut out));
126+
out
127+
}
128+
129+
fn quote_arg(out: &mut Vec<u16>, data: &OsStr) {
130+
// FIXME incorrectly handles quotes.
131+
out.push(ascii_to_u16(b' '));
132+
out.push(ascii_to_u16(b'"'));
133+
for ch in data.encode_wide() {
134+
assert_ne!(ch, ascii_to_u16(b'"'));
135+
out.push(ch);
136+
}
137+
138+
out.push(ascii_to_u16(b'"'));
139+
}
140+
141+
enum EncodeEnvResult {
142+
/// Success
143+
Ok,
144+
/// Partial success: zero chars were skipped
145+
Partial,
146+
}
75147

76-
todo!()
148+
/// Returns None if data contains zero char.
149+
fn encode_env(data: &[OsString]) -> (Vec<u16>, EncodeEnvResult) {
150+
let mut res = EncodeEnvResult::Ok;
151+
let mut capacity = 1;
152+
for item in data {
153+
capacity += item.encode_wide().count() + 1;
154+
}
155+
let mut out = Vec::with_capacity(capacity);
156+
for item in data {
157+
for char in item.encode_wide() {
158+
if char == 0 {
159+
res = EncodeEnvResult::Partial;
160+
continue;
161+
}
162+
out.push(char);
163+
}
164+
out.push(0);
165+
}
166+
out.push(0);
167+
// let's verify capacity was correct
168+
debug_assert_eq!(out.capacity(), capacity);
169+
debug_assert_eq!(out.len(), capacity);
170+
(out, res)
77171
}

0 commit comments

Comments
 (0)