@@ -7,58 +7,77 @@ use crate::{
7
7
} ;
8
8
9
9
use winapi:: um:: {
10
- jobapi2:: { CreateJobObjectW , QueryInformationJobObject , TerminateJobObject } ,
10
+ handleapi:: CloseHandle ,
11
+ jobapi2:: {
12
+ AssignProcessToJobObject , CreateJobObjectW , QueryInformationJobObject ,
13
+ SetInformationJobObject , TerminateJobObject ,
14
+ } ,
11
15
winnt:: {
12
16
JobObjectBasicAccountingInformation , JobObjectExtendedLimitInformation ,
13
17
JobObjectLimitViolationInformation , HANDLE , JOBOBJECT_BASIC_ACCOUNTING_INFORMATION ,
14
18
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 ,
16
21
} ,
17
22
} ;
18
23
24
+ /// Responsible for resource isolation & adding & killing
19
25
#[ derive( Debug ) ]
20
- pub struct WindowsSandbox {
21
- job : HANDLE ,
22
- id : String ,
26
+ struct Job {
27
+ handle : HANDLE ,
23
28
}
24
29
25
- unsafe impl Send for WindowsSandbox { }
26
- unsafe impl Sync for WindowsSandbox { }
30
+ unsafe impl Send for Job { }
31
+ unsafe impl Sync for Job { }
27
32
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
35
39
} ;
36
- Ok ( Self { job , id } )
40
+ Ok ( Self { handle } )
37
41
}
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 ;
48
57
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
+ ) ) ?;
50
64
}
51
65
Ok ( ( ) )
52
66
}
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 > {
55
74
let cpu = unsafe {
56
75
let mut info: JOBOBJECT_BASIC_ACCOUNTING_INFORMATION = std:: mem:: zeroed ( ) ;
57
76
Cvt :: nonzero ( QueryInformationJobObject (
58
- self . job ,
77
+ self . handle ,
59
78
JobObjectBasicAccountingInformation ,
60
79
( & 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 > ( ) ,
62
81
std:: ptr:: null_mut ( ) ,
63
82
) ) ?;
64
83
@@ -69,10 +88,10 @@ impl crate::Sandbox for WindowsSandbox {
69
88
let memory = unsafe {
70
89
let mut info: JOBOBJECT_EXTENDED_LIMIT_INFORMATION = std:: mem:: zeroed ( ) ;
71
90
Cvt :: nonzero ( QueryInformationJobObject (
72
- self . job ,
91
+ self . handle ,
73
92
JobObjectExtendedLimitInformation ,
74
93
( & 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 > ( ) ,
76
95
std:: ptr:: null_mut ( ) ,
77
96
) ) ?;
78
97
info. PeakJobMemoryUsed as u64
@@ -83,23 +102,76 @@ impl crate::Sandbox for WindowsSandbox {
83
102
memory : Some ( memory) ,
84
103
} )
85
104
}
86
-
87
- fn check_cpu_tle ( & self ) -> Result < bool , Self :: Error > {
105
+ fn check_cpu_tle ( & self ) -> Result < bool , Error > {
88
106
unsafe {
89
107
let mut info: JOBOBJECT_LIMIT_VIOLATION_INFORMATION = std:: mem:: zeroed ( ) ;
90
108
Cvt :: nonzero ( QueryInformationJobObject (
91
- self . job ,
109
+ self . handle ,
92
110
JobObjectLimitViolationInformation ,
93
111
( & 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 > ( ) ,
95
113
std:: ptr:: null_mut ( ) ,
96
114
) ) ?;
97
115
let viol = info. ViolationLimitFlags & JOB_OBJECT_LIMIT_JOB_TIME ;
98
116
Ok ( viol != 0 )
99
117
}
100
118
}
101
119
102
- fn check_real_tle ( & self ) -> Result < bool , Self :: Error > {
120
+ fn check_real_tle ( & self ) -> Result < bool , Error > {
103
121
todo ! ( )
104
122
}
105
123
}
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
+ }
0 commit comments