1#![feature(naked_functions)]
2#![feature(thread_local)]
3#![feature(new_zeroed_alloc)]
4#![feature(iterator_try_collect)]
5#![feature(linkage)]
6
7use dynlink::context::NewCompartmentFlags;
8use miette::IntoDiagnostic;
9use monitor_api::{CompartmentFlags, CompartmentHandle, CompartmentLoader};
10use tracing::{debug, info, warn, Level};
11use tracing_subscriber::FmtSubscriber;
12use twizzler_abi::object::NULLPAGE_SIZE;
13use twizzler_rt_abi::object::MapFlags;
14
15mod dlengine;
16pub mod init;
17mod mon;
18mod upcall;
19
20pub use monitor_api::MappedObjectAddrs;
21
22#[path = "../secapi/gates.rs"]
23mod gates;
24
25extern crate dynlink;
26extern crate twizzler_runtime;
27
28extern "C-unwind" {
29 fn __monitor_ready();
30}
31
32pub fn main() {
33 std::env::set_var("RUST_BACKTRACE", "full");
35 let subscriber = FmtSubscriber::builder()
36 .with_max_level(Level::INFO)
37 .with_target(false)
38 .without_time()
39 .finish();
40
41 tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
42
43 miette::set_hook(Box::new(|_| {
44 Box::new(miette::NarratableReportHandler::new().with_cause_chain())
45 }))
46 .unwrap();
47
48 debug!("monitor entered, discovering dynlink context");
49 let init =
50 init::bootstrap_dynlink_context().expect("failed to discover initial dynlink context");
51
52 let mon = mon::Monitor::new(init);
53 mon::set_monitor(mon);
54
55 debug!("ok, starting monitor proper");
56 unsafe { __monitor_ready() };
58 mon::get_monitor().start_background_threads();
60
61 std::env::set_var("RUST_BACKTRACE", "1");
62 unsafe {
63 twizzler_rt_abi::bindings::twz_rt_set_upcall_handler(Some(
64 crate::upcall::upcall_monitor_handler_entry,
65 ))
66 };
67
68 let main_thread = std::thread::spawn(monitor_init);
69 let _r = main_thread.join().unwrap().map_err(|e| {
70 tracing::error!("{:?}", e);
71 });
72 warn!("monitor main thread exited");
73}
74
75fn monitor_init() -> miette::Result<()> {
76 if let Some(ki_name) = dlengine::get_kernel_init_info()
78 .names()
79 .iter()
80 .find(|iname| iname.name() == "monitor_test_info")
81 {
82 info!("starting monitor tests [{}]", ki_name.name());
83 const MAX_NAMELEN: usize = 0x1000;
85 let info =
86 twizzler_rt_abi::object::twz_rt_map_object(ki_name.id(), MapFlags::READ).unwrap();
87 let test_name_slice =
88 unsafe { core::slice::from_raw_parts(info.start().add(NULLPAGE_SIZE), MAX_NAMELEN) };
89 let first_null = test_name_slice
90 .iter()
91 .position(|x| *x == 0)
92 .unwrap_or(MAX_NAMELEN - 1);
93 let test_name = String::from_utf8_lossy(&test_name_slice[0..first_null]);
94 debug!("monitor test binary: {}", test_name);
95 if let Some(_ki_name) = dlengine::get_kernel_init_info()
96 .names()
97 .iter()
98 .find(|iname| iname.name() == test_name)
99 {
100 let comp: CompartmentHandle =
102 CompartmentLoader::new("montest", test_name, NewCompartmentFlags::empty())
103 .args(&["montest", "--test-threads=1"])
104 .load()
105 .into_diagnostic()?;
106 let mut flags = comp.info().flags;
107 while !flags.contains(CompartmentFlags::EXITED) {
108 flags = comp.wait(flags);
109 }
110 } else {
111 tracing::error!("failed to start monitor tests: {}", ki_name.name());
112 }
113 }
114
115 info!("monitor early init completed, starting init");
116 let mut args = vec!["init".to_string()];
117 for arg in std::env::args() {
118 args.push(arg);
119 }
120 let comp: CompartmentHandle =
121 CompartmentLoader::new("init", "init", NewCompartmentFlags::empty())
122 .args(&args)
123 .load()
124 .into_diagnostic()?;
125 let mut flags = comp.info().flags;
126 while !flags.contains(CompartmentFlags::EXITED) {
127 flags = comp.wait(flags);
128 }
129
130 tracing::warn!("init exited");
131
132 Ok(())
133}