1use std::fmt::Debug;
2
3use dynlink::context::NewCompartmentFlags;
4use secgate::{util::Descriptor, Crossing};
5use twizzler_rt_abi::{
6 debug::{DlPhdrInfo, LinkMap},
7 error::{ArgumentError, ResourceError, TwzError},
8 object::ObjID,
9 thread::ThreadSpawnArgs,
10};
11
12extern "C-unwind" {
13 fn __is_monitor_ready() -> bool;
14}
15
16pub const MONITOR_INSTANCE_ID: ObjID = ObjID::new(0);
18
19#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
20#[cfg_attr(
21 not(feature = "secgate-impl"),
22 secgate::secure_gate(options(info, api))
23)]
24pub fn monitor_rt_spawn_thread(
25 info: &secgate::GateCallInfo,
26 args: ThreadSpawnArgs,
27 thread_pointer: usize,
28 stack_pointer: usize,
29) -> Result<ObjID, TwzError> {
30 let monitor = crate::mon::get_monitor();
31 monitor.spawn_compartment_thread(
32 info.source_context().unwrap_or(0.into()),
33 args,
34 stack_pointer,
35 thread_pointer,
36 )
37}
38
39#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
40#[cfg_attr(
41 not(feature = "secgate-impl"),
42 secgate::secure_gate(options(info, api))
43)]
44pub fn monitor_rt_get_comp_config(info: &secgate::GateCallInfo) -> Result<usize, TwzError> {
45 let monitor = crate::mon::get_monitor();
46 Ok(monitor
47 .get_comp_config(info.source_context().unwrap_or(MONITOR_INSTANCE_ID))
48 .map(|ptr| ptr as usize)
49 .unwrap_or(0))
50}
51
52#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
53#[cfg_attr(
54 not(feature = "secgate-impl"),
55 secgate::secure_gate(options(info, api))
56)]
57pub fn monitor_rt_get_library_info(
58 info: &secgate::GateCallInfo,
59 desc: Descriptor,
60) -> Result<LibraryInfo, TwzError> {
61 let monitor = crate::mon::get_monitor();
62 let instance = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
63 let thread = info.thread_id();
64 monitor.get_library_info(instance, thread, desc)
65}
66
67#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
68#[cfg_attr(
69 not(feature = "secgate-impl"),
70 secgate::secure_gate(options(info, api))
71)]
72pub fn monitor_rt_get_library_handle(
73 info: &secgate::GateCallInfo,
74 compartment: Option<Descriptor>,
75 lib_n: usize,
76) -> Result<Descriptor, TwzError> {
77 let monitor = crate::mon::get_monitor();
78 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
79 monitor.get_library_handle(caller, compartment, lib_n)
80}
81
82#[repr(C)]
83#[derive(Clone, Copy, Debug)]
84pub struct LibraryInfo {
85 pub name_len: usize,
86 pub compartment_id: ObjID,
87 pub objid: ObjID,
88 pub slot: usize,
89 pub start: *const u8,
90 pub len: usize,
91 pub dl_info: DlPhdrInfo,
92 pub link_map: LinkMap,
93 pub desc: Descriptor,
94}
95
96#[repr(C)]
97#[derive(Clone, Copy, Debug)]
98pub struct CompartmentInfo {
99 pub name_len: usize,
100 pub id: ObjID,
101 pub sctx: ObjID,
102 pub flags: u64,
103 pub nr_libs: usize,
104}
105
106#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
107#[cfg_attr(
108 not(feature = "secgate-impl"),
109 secgate::secure_gate(options(info, api))
110)]
111pub fn monitor_rt_get_compartment_handle(
112 info: &secgate::GateCallInfo,
113 compartment: ObjID,
114) -> Result<Descriptor, TwzError> {
115 let monitor = crate::mon::get_monitor();
116 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
117 let compartment = if compartment.raw() == 0 {
118 caller
119 } else {
120 compartment
121 };
122 monitor.get_compartment_handle(caller, compartment)
123}
124
125#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
126#[cfg_attr(
127 not(feature = "secgate-impl"),
128 secgate::secure_gate(options(info, api))
129)]
130pub fn monitor_rt_get_compartment_info(
131 info: &secgate::GateCallInfo,
132 desc: Option<Descriptor>,
133) -> Result<CompartmentInfo, TwzError> {
134 let monitor = crate::mon::get_monitor();
135 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
136 monitor.get_compartment_info(caller, info.thread_id(), desc)
137}
138
139#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
140#[cfg_attr(
141 not(feature = "secgate-impl"),
142 secgate::secure_gate(options(info, api))
143)]
144pub fn monitor_rt_compartment_dynamic_gate(
145 info: &secgate::GateCallInfo,
146 desc: Option<Descriptor>,
147 name_len: usize,
148) -> Result<usize, TwzError> {
149 let monitor = crate::mon::get_monitor();
150 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
151 monitor.get_compartment_gate_address(caller, info.thread_id(), desc, name_len)
152}
153
154#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
155#[cfg_attr(
156 not(feature = "secgate-impl"),
157 secgate::secure_gate(options(info, api))
158)]
159pub fn monitor_rt_get_compartment_deps(
160 info: &secgate::GateCallInfo,
161 desc: Option<Descriptor>,
162 dep_n: usize,
163) -> Result<Descriptor, TwzError> {
164 let monitor = crate::mon::get_monitor();
165 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
166 monitor.get_compartment_deps(caller, desc, dep_n)
167}
168
169#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, Copy)]
170#[repr(C)]
171pub struct ThreadInfo {
172 pub repr_id: ObjID,
173}
174
175#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
176#[cfg_attr(
177 not(feature = "secgate-impl"),
178 secgate::secure_gate(options(info, api))
179)]
180pub fn monitor_rt_get_compartment_thread(
181 info: &secgate::GateCallInfo,
182 desc: Option<Descriptor>,
183 dep_n: usize,
184) -> Result<ThreadInfo, TwzError> {
185 let monitor = crate::mon::get_monitor();
186 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
187 monitor.get_compartment_thread_info(caller, desc, dep_n)
188}
189
190#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
191#[cfg_attr(
192 not(feature = "secgate-impl"),
193 secgate::secure_gate(options(info, api))
194)]
195pub fn monitor_rt_lookup_compartment(
196 info: &secgate::GateCallInfo,
197 name_len: usize,
198) -> Result<Descriptor, TwzError> {
199 let monitor = crate::mon::get_monitor();
200 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
201 monitor.lookup_compartment(caller, info.thread_id(), name_len)
202}
203
204unsafe impl Crossing for LibraryInfo {}
207
208#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
209#[cfg_attr(
210 not(feature = "secgate-impl"),
211 secgate::secure_gate(options(info, api))
212)]
213pub fn monitor_rt_load_compartment(
214 info: &secgate::GateCallInfo,
215 name_len: u64,
216 args_len: u64,
217 env_len: u64,
218 flags: u32,
219) -> Result<Descriptor, TwzError> {
220 let monitor = crate::mon::get_monitor();
221 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
222 monitor.load_compartment(
223 caller,
224 info.thread_id(),
225 name_len as usize,
226 args_len as usize,
227 env_len as usize,
228 NewCompartmentFlags::from_bits(flags).ok_or(ArgumentError::InvalidArgument)?,
229 )
230}
231
232#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
233#[cfg_attr(
234 not(feature = "secgate-impl"),
235 secgate::secure_gate(options(info, api))
236)]
237pub fn monitor_rt_compartment_wait(
238 info: &secgate::GateCallInfo,
239 desc: Option<Descriptor>,
240 flags: u64,
241) -> Result<u64, TwzError> {
242 let monitor = crate::mon::get_monitor();
243 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
244 Ok(monitor.compartment_wait(caller, desc, flags))
245}
246
247#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
248#[cfg_attr(
249 not(feature = "secgate-impl"),
250 secgate::secure_gate(options(info, api))
251)]
252pub fn monitor_rt_drop_compartment_handle(
253 info: &secgate::GateCallInfo,
254 desc: Descriptor,
255) -> Result<(), TwzError> {
256 let monitor = crate::mon::get_monitor();
257 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
258 monitor.drop_compartment_handle(caller, desc);
259 Ok(())
260}
261
262#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
263#[cfg_attr(
264 not(feature = "secgate-impl"),
265 secgate::secure_gate(options(info, api))
266)]
267pub fn monitor_rt_load_library(
268 info: &secgate::GateCallInfo,
269 compartment: Option<Descriptor>,
270 id: ObjID,
271) -> Result<Descriptor, TwzError> {
272 let monitor = crate::mon::get_monitor();
273 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
274 monitor.load_library(caller, id, compartment)
275}
276
277#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
278#[cfg_attr(
279 not(feature = "secgate-impl"),
280 secgate::secure_gate(options(info, api))
281)]
282pub fn monitor_rt_drop_library_handle(
283 info: &secgate::GateCallInfo,
284 desc: Descriptor,
285) -> Result<(), TwzError> {
286 let monitor = crate::mon::get_monitor();
287 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
288 monitor.drop_library_handle(caller, desc);
289 Ok(())
290}
291
292#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
293#[cfg_attr(
294 not(feature = "secgate-impl"),
295 secgate::secure_gate(options(info, api))
296)]
297pub fn monitor_rt_object_map(
298 info: &secgate::GateCallInfo,
299 id: ObjID,
300 flags: twizzler_rt_abi::object::MapFlags,
301) -> Result<crate::MappedObjectAddrs, TwzError> {
302 use crate::mon::space::MapInfo;
303 if unsafe { __is_monitor_ready() } {
304 let is_monitor_recursed =
309 { happylock::ThreadKey::get().is_none() && info.source_context().is_none() };
310 if is_monitor_recursed {
311 tracing::debug!(
312 "performing early object mapping (recursed), {} {:?}",
313 id,
314 flags
315 );
316 return Ok(crate::mon::early_object_map(MapInfo { id, flags }));
317 }
318 let monitor = crate::mon::get_monitor();
319 monitor
320 .map_object(
321 info.source_context().unwrap_or(MONITOR_INSTANCE_ID),
322 MapInfo { id, flags },
323 )
324 .map(|handle| handle.addrs())
325 } else {
326 tracing::debug!("performing early object mapping, {} {:?}", id, flags);
329 Ok(crate::mon::early_object_map(MapInfo { id, flags }))
330 }
331}
332
333#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
334#[cfg_attr(
335 not(feature = "secgate-impl"),
336 secgate::secure_gate(options(info, api))
337)]
338pub fn monitor_rt_object_pair_map(
339 info: &secgate::GateCallInfo,
340 id: ObjID,
341 flags: twizzler_rt_abi::object::MapFlags,
342 id2: ObjID,
343 flags2: twizzler_rt_abi::object::MapFlags,
344) -> Result<(crate::MappedObjectAddrs, crate::MappedObjectAddrs), TwzError> {
345 use crate::mon::space::MapInfo;
346 if unsafe { !__is_monitor_ready() } {
347 return Err(ResourceError::Unavailable.into());
348 }
349 let monitor = crate::mon::get_monitor();
350 monitor
351 .map_pair(
352 info.source_context().unwrap_or(MONITOR_INSTANCE_ID),
353 MapInfo { id, flags },
354 MapInfo {
355 id: id2,
356 flags: flags2,
357 },
358 )
359 .map(|(one, two)| (one.addrs(), two.addrs()))
360}
361
362#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
363#[cfg_attr(
364 not(feature = "secgate-impl"),
365 secgate::secure_gate(options(info, api))
366)]
367pub fn monitor_rt_object_unmap(
368 info: &secgate::GateCallInfo,
369 id: ObjID,
370 flags: twizzler_rt_abi::object::MapFlags,
371) -> Result<(), TwzError> {
372 if unsafe { __is_monitor_ready() } {
373 let monitor = crate::mon::get_monitor();
374 monitor.unmap_object(
375 info.source_context().unwrap_or(MONITOR_INSTANCE_ID),
376 crate::mon::space::MapInfo { id, flags },
377 );
378 }
379 Ok(())
380}
381
382#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
383#[cfg_attr(
384 not(feature = "secgate-impl"),
385 secgate::secure_gate(options(info, api))
386)]
387pub fn monitor_rt_get_thread_simple_buffer(
388 info: &secgate::GateCallInfo,
389) -> Result<ObjID, TwzError> {
390 let monitor = crate::mon::get_monitor();
391 let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID);
392 monitor.get_thread_simple_buffer(caller, info.thread_id())
393}
394
395#[derive(Debug, Copy, Clone)]
396#[repr(C)]
397#[allow(dead_code)]
398pub enum MonitorCompControlCmd {
399 RuntimeReady,
400 RuntimePostMain,
401}
402
403#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
404#[cfg_attr(
405 not(feature = "secgate-impl"),
406 secgate::secure_gate(options(info, api))
407)]
408pub fn monitor_rt_comp_ctrl(
409 info: &secgate::GateCallInfo,
410 cmd: MonitorCompControlCmd,
411) -> Result<Option<i32>, TwzError> {
412 let monitor = crate::mon::get_monitor();
413 Ok(monitor.compartment_ctrl(info, cmd))
414}
415
416#[derive(Copy, Clone, Debug)]
417#[repr(C)]
418pub struct MonitorStats {
419 pub space: SpaceStats,
420 pub thread_mgr: ThreadMgrStats,
421 pub comp_mgr: CompartmentMgrStats,
422 pub handles: HandleStats,
423 pub dynlink: DynlinkStats,
424}
425
426#[derive(Copy, Clone, Debug)]
427#[repr(C)]
428pub struct SpaceStats {
429 pub mapped: usize,
430}
431
432#[derive(Copy, Clone, Debug)]
433#[repr(C)]
434pub struct ThreadMgrStats {
435 pub nr_threads: usize,
436}
437
438#[derive(Copy, Clone, Debug)]
439#[repr(C)]
440pub struct CompartmentMgrStats {
441 pub nr_compartments: usize,
442}
443
444#[derive(Copy, Clone, Debug)]
445#[repr(C)]
446pub struct HandleStats {
447 pub nr_comp_handles: usize,
448 pub nr_lib_handles: usize,
449}
450
451#[derive(Copy, Clone, Debug)]
452#[repr(C)]
453pub struct DynlinkStats {
454 pub nr_libs: usize,
455 pub nr_comps: usize,
456}
457
458#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
459#[cfg_attr(
460 not(feature = "secgate-impl"),
461 secgate::secure_gate(options(info, api))
462)]
463pub fn monitor_rt_stats(_info: &secgate::GateCallInfo) -> Result<MonitorStats, TwzError> {
464 let monitor = crate::mon::get_monitor();
465 Ok(monitor.stats())
466}
467
468#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))]
469#[cfg_attr(
470 not(feature = "secgate-impl"),
471 secgate::secure_gate(options(info, api))
472)]
473pub fn monitor_rt_set_nameroot(info: &secgate::GateCallInfo, root: ObjID) -> Result<(), TwzError> {
474 let monitor = crate::mon::get_monitor();
475 monitor.set_nameroot(info, root)
476}