Skip to content

Commit 44ddabb

Browse files
committed
work
1 parent 1146ebe commit 44ddabb

File tree

8 files changed

+179
-43
lines changed

8 files changed

+179
-43
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ serde_json = "1.0.51"
2121

2222
[target.'cfg(target_os="windows")'.dependencies]
2323
winapi = { version = "0.3.9", features = ["std", "processthreadsapi", "jobapi2", "errhandlingapi",
24-
"namedpipeapi", "fileapi", "synchapi", "winnt"] }
24+
"namedpipeapi", "fileapi", "synchapi", "winnt", "userenv", "handleapi"] }
2525

2626
[workspace]
2727
members = ["minion-ffi", ".", "minion-tests", "minion-cli"]

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ use std::{
2828
error::Error as StdError,
2929
fmt::Debug,
3030
io::{Read, Write},
31-
time::Duration,
3231
sync::Arc,
32+
time::Duration,
3333
};
3434

3535
/// This functions checks for system configurations issues.

src/linux/jail_common.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ pub(crate) struct JailOptions {
2222
pub(crate) allow_mount_ns_failure: bool,
2323
}
2424

25-
2625
#[derive(Serialize, Deserialize, Clone, Debug)]
2726
pub(crate) struct JobQuery {
2827
pub(crate) image_path: PathBuf,

src/linux/sandbox.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ impl SandboxState {
5050
}
5151
}
5252

53-
5453
#[repr(C)]
5554
pub struct LinuxSandbox {
5655
id: String,

src/windows.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod child;
44
pub mod error;
55
mod pipe;
66
mod sandbox;
7+
mod spawn;
78

89
pub use error::Error;
910
pub use pipe::{ReadPipe, WritePipe};
@@ -27,13 +28,13 @@ impl crate::Backend for WindowsBackend {
2728
type ChildProcess = child::WindowsChildProcess;
2829

2930
fn new_sandbox(&self, options: crate::SandboxOptions) -> Result<Self::Sandbox, Self::Error> {
30-
sandbox::WindowsSandbox::create()
31+
let sandbox = sandbox::WindowsSandbox::create(options)?;
32+
Ok(sandbox)
3133
}
3234

3335
fn spawn(
3436
&self,
3537
options: crate::ChildProcessOptions<Self::Sandbox>,
3638
) -> Result<Self::ChildProcess, Self::Error> {
37-
todo!()
3839
}
3940
}

src/windows/child.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ pub struct WindowsChildProcess {
1414
/// Handle to winapi Process object
1515
child: HANDLE,
1616

17+
/// Handle to main process of child
18+
main_thread: HANDLE,
19+
1720
/// Contains exit code or STILL_ACTIVE otherwise
1821
exit_code: AtomicU32,
1922

src/windows/sandbox.rs

Lines changed: 109 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,58 +7,77 @@ use crate::{
77
};
88

99
use winapi::um::{
10-
jobapi2::{CreateJobObjectW, QueryInformationJobObject, TerminateJobObject},
10+
handleapi::CloseHandle,
11+
jobapi2::{
12+
AssignProcessToJobObject, CreateJobObjectW, QueryInformationJobObject,
13+
SetInformationJobObject, TerminateJobObject,
14+
},
1115
winnt::{
1216
JobObjectBasicAccountingInformation, JobObjectExtendedLimitInformation,
1317
JobObjectLimitViolationInformation, HANDLE, JOBOBJECT_BASIC_ACCOUNTING_INFORMATION,
1418
JOBOBJECT_EXTENDED_LIMIT_INFORMATION, JOBOBJECT_LIMIT_VIOLATION_INFORMATION,
15-
JOB_OBJECT_LIMIT_JOB_TIME,
19+
JOB_OBJECT_LIMIT_ACTIVE_PROCESS, JOB_OBJECT_LIMIT_JOB_MEMORY, JOB_OBJECT_LIMIT_JOB_TIME,
20+
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,
1621
},
1722
};
1823

24+
/// Responsible for resource isolation & adding & killing
1925
#[derive(Debug)]
20-
pub struct WindowsSandbox {
21-
job: HANDLE,
22-
id: String,
26+
struct Job {
27+
handle: HANDLE,
2328
}
2429

25-
unsafe impl Send for WindowsSandbox {}
26-
unsafe impl Sync for WindowsSandbox {}
30+
unsafe impl Send for Job {}
31+
unsafe impl Sync for Job {}
2732

28-
impl WindowsSandbox {
29-
pub(in crate::windows) fn create() -> Result<Self, Error> {
30-
let id = crate::util::gen_jail_id();
31-
let name: OsString = format!("minion-sandbox-{}", id).into();
32-
let wide_name: Vec<u16> = name.encode_wide().collect();
33-
let job = unsafe {
34-
Cvt::nonzero(CreateJobObjectW(std::ptr::null_mut(), wide_name.as_ptr()) as i32)? as HANDLE
33+
impl Job {
34+
fn new(jail_id: &str) -> Result<Self, Error> {
35+
let name: OsString = format!("minion-sandbox-job-{}", jail_id).into();
36+
let name: Vec<u16> = name.encode_wide().collect();
37+
let handle = unsafe {
38+
Cvt::nonzero(CreateJobObjectW(std::ptr::null_mut(), name.as_ptr()) as i32)? as HANDLE
3539
};
36-
Ok(Self { job, id })
40+
Ok(Self { handle })
3741
}
38-
}
39-
40-
impl crate::Sandbox for WindowsSandbox {
41-
type Error = Error;
42-
43-
fn id(&self) -> &str {
44-
todo!()
45-
}
46-
47-
fn kill(&self) -> Result<(), Self::Error> {
42+
fn enable_resource_limits(&mut self, options: &crate::SandboxOptions) -> Result<(), Error> {
43+
let mut info: JOBOBJECT_EXTENDED_LIMIT_INFORMATION = unsafe { std::mem::zeroed() };
44+
info.JobMemoryLimit = options.memory_limit as usize;
45+
info.BasicLimitInformation.ActiveProcessLimit = options.max_alive_process_count;
46+
unsafe {
47+
*info
48+
.BasicLimitInformation
49+
.PerJobUserTimeLimit
50+
.QuadPart_mut() = (options.cpu_time_limit.as_nanos() / 100) as i64;
51+
};
52+
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_JOB_MEMORY
53+
| JOB_OBJECT_LIMIT_ACTIVE_PROCESS
54+
| JOB_OBJECT_LIMIT_JOB_TIME
55+
// let's make sure sandbox will die if we panic / abort
56+
| JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
4857
unsafe {
49-
Cvt::nonzero(TerminateJobObject(self.job, 0xDEADBEEF))?;
58+
Cvt::nonzero(SetInformationJobObject(
59+
self.handle,
60+
JobObjectExtendedLimitInformation,
61+
(&mut info as *mut JOBOBJECT_EXTENDED_LIMIT_INFORMATION).cast(),
62+
sizeof::<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>(),
63+
))?;
5064
}
5165
Ok(())
5266
}
53-
54-
fn resource_usage(&self) -> Result<ResourceUsageData, Self::Error> {
67+
fn kill(&self) -> Result<(), Error> {
68+
unsafe { Cvt::nonzero(TerminateJobObject(self.handle, 0xDEADBEEF)).map(|_| ()) }
69+
}
70+
fn add_process(&self, process_handle: HANDLE) -> Result<(), Error> {
71+
unsafe { Cvt::nonzero(AssignProcessToJobObject(self.handle, process_handle)).map(|_| ()) }
72+
}
73+
fn resource_usage(&self) -> Result<crate::ResourceUsageData, Error> {
5574
let cpu = unsafe {
5675
let mut info: JOBOBJECT_BASIC_ACCOUNTING_INFORMATION = std::mem::zeroed();
5776
Cvt::nonzero(QueryInformationJobObject(
58-
self.job,
77+
self.handle,
5978
JobObjectBasicAccountingInformation,
6079
(&mut info as *mut JOBOBJECT_BASIC_ACCOUNTING_INFORMATION).cast(),
61-
std::mem::size_of::<JOBOBJECT_BASIC_ACCOUNTING_INFORMATION>() as u32,
80+
sizeof::<JOBOBJECT_BASIC_ACCOUNTING_INFORMATION>(),
6281
std::ptr::null_mut(),
6382
))?;
6483

@@ -69,10 +88,10 @@ impl crate::Sandbox for WindowsSandbox {
6988
let memory = unsafe {
7089
let mut info: JOBOBJECT_EXTENDED_LIMIT_INFORMATION = std::mem::zeroed();
7190
Cvt::nonzero(QueryInformationJobObject(
72-
self.job,
91+
self.handle,
7392
JobObjectExtendedLimitInformation,
7493
(&mut info as *mut JOBOBJECT_EXTENDED_LIMIT_INFORMATION).cast(),
75-
std::mem::size_of::<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>() as u32,
94+
sizeof::<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>(),
7695
std::ptr::null_mut(),
7796
))?;
7897
info.PeakJobMemoryUsed as u64
@@ -83,23 +102,76 @@ impl crate::Sandbox for WindowsSandbox {
83102
memory: Some(memory),
84103
})
85104
}
86-
87-
fn check_cpu_tle(&self) -> Result<bool, Self::Error> {
105+
fn check_cpu_tle(&self) -> Result<bool, Error> {
88106
unsafe {
89107
let mut info: JOBOBJECT_LIMIT_VIOLATION_INFORMATION = std::mem::zeroed();
90108
Cvt::nonzero(QueryInformationJobObject(
91-
self.job,
109+
self.handle,
92110
JobObjectLimitViolationInformation,
93111
(&mut info as *mut JOBOBJECT_LIMIT_VIOLATION_INFORMATION).cast(),
94-
std::mem::size_of::<JOBOBJECT_LIMIT_VIOLATION_INFORMATION>() as u32,
112+
sizeof::<JOBOBJECT_LIMIT_VIOLATION_INFORMATION>(),
95113
std::ptr::null_mut(),
96114
))?;
97115
let viol = info.ViolationLimitFlags & JOB_OBJECT_LIMIT_JOB_TIME;
98116
Ok(viol != 0)
99117
}
100118
}
101119

102-
fn check_real_tle(&self) -> Result<bool, Self::Error> {
120+
fn check_real_tle(&self) -> Result<bool, Error> {
103121
todo!()
104122
}
105123
}
124+
125+
impl Drop for Job {
126+
fn drop(&mut self) {
127+
unsafe {
128+
CloseHandle(self.handle);
129+
}
130+
}
131+
}
132+
133+
#[derive(Debug)]
134+
pub struct WindowsSandbox {
135+
job: Job,
136+
id: String,
137+
}
138+
139+
impl WindowsSandbox {
140+
pub(in crate::windows) fn create(options: crate::SandboxOptions) -> Result<Self, Error> {
141+
let id = crate::util::gen_jail_id();
142+
let mut job = Job::new(&id)?;
143+
job.enable_resource_limits(&options)?;
144+
145+
Ok(Self { job, id })
146+
}
147+
}
148+
149+
impl crate::Sandbox for WindowsSandbox {
150+
type Error = Error;
151+
152+
fn id(&self) -> &str {
153+
todo!()
154+
}
155+
156+
fn kill(&self) -> Result<(), Self::Error> {
157+
self.job.kill()
158+
}
159+
160+
fn resource_usage(&self) -> Result<ResourceUsageData, Self::Error> {
161+
self.job.resource_usage()
162+
}
163+
164+
fn check_cpu_tle(&self) -> Result<bool, Self::Error> {
165+
self.job.check_cpu_tle()
166+
}
167+
168+
fn check_real_tle(&self) -> Result<bool, Self::Error> {
169+
self.job.check_real_tle()
170+
}
171+
}
172+
173+
fn sizeof<T>() -> u32 {
174+
let sz = std::mem::size_of::<T>();
175+
assert!(sz <= (u32::max_value() as usize));
176+
sz as u32
177+
}

src/windows/spawn.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use crate::windows::{
2+
child::WindowsChildProcess,
3+
pipe::{self, ReadPipe, WritePipe},
4+
Cvt, Error, WindowsSandbox,
5+
};
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::{STARTF_USESTDHANDLES, STARTUPINFOEXW, CREATE_UNICODE_ENVIRONMENT,EXTENDED_STARTUPINFO_PRESENT},
15+
winnt::HANDLE,
16+
};
17+
18+
pub(in crate::windows) struct Stdio {
19+
pub stdin: HANDLE,
20+
pub stdout: HANDLE,
21+
pub stderr: HANDLE,
22+
}
23+
24+
pub(in crate::windows) fn spawn(
25+
sandbox: &WindowsSandbox,
26+
stdio: Stdio,
27+
) -> Result<WindowsChildProcess, Error> {
28+
let mut proc_thread_attr_list_storage: Vec<u64>;
29+
let startup_info = unsafe {
30+
let mut startup_info: STARTUPINFOEXW = std::mem::zeroed();
31+
let mut proc_thread_attr_list_len = 0;
32+
Cvt::nonzero(InitializeProcThreadAttributeList(
33+
std::ptr::null_mut(),
34+
1,
35+
0,
36+
&mut proc_thread_attr_list_len,
37+
))?;
38+
proc_thread_attr_list_storage = Vec::with_capacity((proc_thread_attr_list_len - 1) / 8 + 1);
39+
let proc_thread_attr_list: *mut u8 = proc_thread_attr_list_storage.as_mut_ptr().cast();
40+
proc_thread_attr_list.write_bytes(0, proc_thread_attr_list_len);
41+
startup_info.lpAttributeList = proc_thread_attr_list.cast();
42+
Cvt::nonzero(InitializeProcThreadAttributeList(
43+
startup_info.lpAttributeList,
44+
1,
45+
0,
46+
&mut proc_thread_attr_list_len,
47+
))?;
48+
Cvt::nonzero(UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PRO, lpValue, cbSize, lpPreviousValue, lpReturnSize))?;
49+
50+
51+
52+
startup_info.StartupInfo.cb = size_of::<STARTUPINFOEXW>() as u32;
53+
startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
54+
startup_info.StartupInfo.hStdInput = stdio.stdin;
55+
startup_info.StartupInfo.hStdOutput = stdio.stdout;
56+
startup_info.StartupInfo.hStdError = stdio.stderr;
57+
startup_info
58+
};
59+
let creation_flags = CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT;
60+
61+
todo!()
62+
}

0 commit comments

Comments
 (0)