1#![feature(naked_functions)]
2#![feature(linkage)]
3#![feature(io_error_more)]
4#[warn(unused_variables)]
5use std::sync::Mutex;
6use std::{io::ErrorKind, path::PathBuf};
7
8use lazy_init::LazyTransform;
9use lazy_static::lazy_static;
10use naming_core::{GetFlags, NameSession, NameStore, NsNode, Result, PATH_MAX};
11use secgate::{
12 secure_gate,
13 util::{Descriptor, HandleMgr, SimpleBuffer},
14};
15use tracing::Level;
16use twizzler::object::ObjectHandle;
17use twizzler_abi::{
18 aux::KernelInitInfo,
19 object::{Protections, MAX_SIZE, NULLPAGE_SIZE},
20 syscall::{sys_object_create, BackingType, LifetimeType, ObjectCreate, ObjectCreateFlags},
21};
22use twizzler_rt_abi::{
23 error::{ArgumentError, ResourceError},
24 object::{MapFlags, ObjID},
25};
26
27struct SbObjects {
28 objs: Vec<ObjectHandle>,
29}
30
31static SB_OBJECTS: Mutex<SbObjects> = Mutex::new(SbObjects { objs: Vec::new() });
32
33pub fn get_sb_object() -> Result<ObjectHandle> {
34 let mut sbo = SB_OBJECTS.lock().unwrap();
35 if sbo.objs.len() == 0 {
36 drop(sbo);
37 let id = sys_object_create(
39 ObjectCreate::new(
40 BackingType::Normal,
41 LifetimeType::Volatile,
42 None,
43 ObjectCreateFlags::empty(),
44 Protections::all(),
45 ),
46 &[],
47 &[],
48 )?;
49 let handle =
50 twizzler_rt_abi::object::twz_rt_map_object(id, MapFlags::WRITE | MapFlags::READ)?;
51 return Ok(handle);
52 }
53
54 let next = sbo.objs.pop().unwrap();
55 Ok(next)
57}
58
59pub fn release_sb_object(obj: ObjectHandle) {
60 let mut sbo = SB_OBJECTS.lock().unwrap();
61 sbo.objs.push(obj);
62}
63
64struct NamespaceClient<'a> {
65 session: NameSession<'a>,
66 buffer: SimpleBuffer,
67}
68
69impl<'a> NamespaceClient<'a> {
70 fn new(session: NameSession<'a>) -> Option<Self> {
71 let handle = get_sb_object().ok()?;
73 let buffer = SimpleBuffer::new(handle);
74 Some(Self { session, buffer })
75 }
76
77 fn sbid(&self) -> ObjID {
78 self.buffer.handle().id()
79 }
80
81 fn read_buffer(&self, name_len: usize) -> Result<PathBuf> {
82 if name_len >= PATH_MAX {
83 return Err(ArgumentError::InvalidArgument.into());
84 }
85 let mut buf = vec![0; name_len];
86 self.buffer.read(&mut buf);
87 Ok(PathBuf::from(
88 String::from_utf8(buf).map_err(|_| ErrorKind::InvalidFilename)?,
89 ))
90 }
91
92 fn read_buffer_at(&self, name_len: usize, off: usize) -> Result<PathBuf> {
93 if name_len >= PATH_MAX {
94 return Err(ArgumentError::InvalidArgument.into());
95 }
96 let mut buf = vec![0; name_len];
97 self.buffer.read_offset(&mut buf, off);
98 Ok(PathBuf::from(
99 String::from_utf8(buf).map_err(|_| ArgumentError::InvalidArgument)?,
100 ))
101 }
102}
103
104unsafe impl Send for Namer<'_> {}
105unsafe impl Sync for Namer<'_> {}
106
107struct Namer<'a> {
108 handles: Mutex<HandleMgr<NamespaceClient<'a>>>,
109 names: NameStore,
110}
111
112impl Namer<'_> {
113 fn new() -> Self {
114 Self {
115 handles: Mutex::new(HandleMgr::new(None)),
116 names: NameStore::new(),
117 }
118 }
119
120 fn new_with(id: ObjID) -> Result<Self> {
121 let names = NameStore::new_with(id)?;
122 Ok(Self {
123 handles: Mutex::new(HandleMgr::new(None)),
124 names,
125 })
126 }
127}
128
129lazy_static! {
130 static ref NAMINGSERVICE: LazyTransform<(), Namer<'static>> = LazyTransform::new(());
131}
132
133fn get_kernel_init_info() -> &'static KernelInitInfo {
134 unsafe {
135 (((twizzler_abi::slot::RESERVED_KERNEL_INIT * MAX_SIZE) + NULLPAGE_SIZE)
136 as *const KernelInitInfo)
137 .as_ref()
138 .unwrap()
139 }
140}
141
142#[secure_gate(options(info))]
144pub fn namer_start(_info: &secgate::GateCallInfo, bootstrap: ObjID) -> Result<ObjID> {
145 tracing::subscriber::set_global_default(
146 tracing_subscriber::fmt()
147 .with_max_level(Level::INFO)
148 .without_time()
149 .finish(),
150 )
151 .unwrap();
152
153 Ok(NAMINGSERVICE
154 .get_or_create(|_| {
155 let namer = Namer::new_with(bootstrap)
156 .or::<ErrorKind>(Ok(Namer::new()))
157 .unwrap();
158 namer.names.root_session().mkns("/initrd", false).unwrap();
159 for n in get_kernel_init_info().names() {
160 namer
161 .names
162 .root_session()
163 .put(&format!("/initrd/{}", n.name()), n.id())
164 .unwrap();
165 }
166
167 namer
168 })
169 .names
170 .id())
171}
172
173#[secure_gate(options(info))]
174pub fn open_handle(info: &secgate::GateCallInfo) -> Result<(Descriptor, ObjID)> {
175 let service = NAMINGSERVICE.get().ok_or(ResourceError::Unavailable)?;
176 let mut binding = service.handles.lock().unwrap();
177
178 let session = service.names.root_session();
179 let client = NamespaceClient::new(session).ok_or(ResourceError::Unavailable)?;
180 let id = client.sbid();
181
182 let desc = binding
183 .insert(info.source_context().unwrap_or(0.into()), client)
184 .ok_or(ResourceError::OutOfResources)?;
185
186 Ok((desc, id))
187}
188
189#[secure_gate(options(info))]
190pub fn close_handle(info: &secgate::GateCallInfo, desc: Descriptor) -> Result<()> {
191 let service = NAMINGSERVICE.get().unwrap();
192
193 let mut binding = service.handles.lock().unwrap();
194
195 if let Some(client) = binding.remove(info.source_context().unwrap_or(0.into()), desc) {
196 release_sb_object(client.buffer.into_handle());
197 }
198
199 Ok(())
200}
201
202#[secure_gate(options(info))]
203pub fn put(
204 info: &secgate::GateCallInfo,
205 desc: Descriptor,
206 name_len: usize,
207 id: ObjID,
208) -> Result<()> {
209 let service = NAMINGSERVICE.get().unwrap();
210 let mut binding = service.handles.lock().unwrap();
211 let client = binding
212 .lookup_mut(info.source_context().unwrap_or(0.into()), desc)
213 .ok_or(ArgumentError::BadHandle)?;
214
215 let path = client.read_buffer(name_len)?;
216
217 client.session.put(path, id)
218}
219
220#[secure_gate(options(info))]
221pub fn mkns(
222 info: &secgate::GateCallInfo,
223 desc: Descriptor,
224 name_len: usize,
225 persist: bool,
226) -> Result<()> {
227 let service = NAMINGSERVICE.get().unwrap();
228 let mut binding = service.handles.lock().unwrap();
229 let client = binding
230 .lookup_mut(info.source_context().unwrap_or(0.into()), desc)
231 .ok_or(ArgumentError::BadHandle)?;
232
233 let path = client.read_buffer(name_len)?;
234
235 client.session.mkns(path, persist)
236}
237
238#[secure_gate(options(info))]
239pub fn link(
240 info: &secgate::GateCallInfo,
241 desc: Descriptor,
242 name_len: usize,
243 link_len: usize,
244) -> Result<()> {
245 let service = NAMINGSERVICE.get().unwrap();
246 let mut binding = service.handles.lock().unwrap();
247 let client = binding
248 .lookup_mut(info.source_context().unwrap_or(0.into()), desc)
249 .ok_or(ErrorKind::Other)?;
250
251 let path = client.read_buffer(name_len)?;
252 let link = client.read_buffer_at(link_len, name_len)?;
253
254 client.session.link(path, link)
255}
256
257#[secure_gate(options(info))]
258pub fn get(
259 info: &secgate::GateCallInfo,
260 desc: Descriptor,
261 name_len: usize,
262 flags: GetFlags,
263) -> Result<NsNode> {
264 let service = NAMINGSERVICE.get().unwrap();
265 let mut binding = service.handles.lock().unwrap();
266 let client = binding
267 .lookup_mut(info.source_context().unwrap_or(0.into()), desc)
268 .ok_or(ErrorKind::Other)?;
269
270 let path = client.read_buffer(name_len)?;
271
272 client.session.get(path, flags)
273}
274
275#[secure_gate(options(info))]
276pub fn remove(info: &secgate::GateCallInfo, desc: Descriptor, name_len: usize) -> Result<()> {
277 let service = NAMINGSERVICE.get().unwrap();
278 let mut binding = service.handles.lock().unwrap();
279 let client = binding
280 .lookup_mut(info.source_context().unwrap_or(0.into()), desc)
281 .ok_or(ErrorKind::Other)?;
282
283 let path = client.read_buffer(name_len)?;
284
285 client.session.remove(path)?;
286
287 Ok(())
288}
289
290#[secure_gate(options(info))]
291pub fn enumerate_names(
292 info: &secgate::GateCallInfo,
293 desc: Descriptor,
294 name_len: usize,
295) -> Result<usize> {
296 let service = NAMINGSERVICE.get().unwrap();
297 let mut binding = service.handles.lock().unwrap();
298 let client = binding
299 .lookup_mut(info.source_context().unwrap_or(0.into()), desc)
300 .ok_or(ErrorKind::Other)?;
301
302 let path = client.read_buffer(name_len)?;
303
304 let vec1 = client.session.enumerate_namespace(path)?;
306 let len = vec1.len();
307
308 let mut buffer = SimpleBuffer::new(client.buffer.handle().clone());
309 let slice = unsafe {
310 std::slice::from_raw_parts(
311 vec1.as_ptr() as *const u8,
312 len * std::mem::size_of::<NsNode>(),
313 )
314 };
315 buffer.write(slice);
316
317 Ok(len)
318}
319
320#[secure_gate(options(info))]
321pub fn enumerate_names_nsid(
322 info: &secgate::GateCallInfo,
323 desc: Descriptor,
324 id: ObjID,
325) -> Result<usize> {
326 let service = NAMINGSERVICE.get().unwrap();
327 let mut binding = service.handles.lock().unwrap();
328 let client = binding
329 .lookup_mut(info.source_context().unwrap_or(0.into()), desc)
330 .ok_or(ErrorKind::Other)?;
331
332 let vec1 = client.session.enumerate_namespace_nsid(id)?;
334 let len = vec1.len();
335
336 let mut buffer = SimpleBuffer::new(client.buffer.handle().clone());
337 let slice = unsafe {
338 std::slice::from_raw_parts(
339 vec1.as_ptr() as *const u8,
340 len * std::mem::size_of::<NsNode>(),
341 )
342 };
343 buffer.write(slice);
344
345 Ok(len)
346}
347
348#[secure_gate(options(info))]
349pub fn change_namespace(
350 info: &secgate::GateCallInfo,
351 desc: Descriptor,
352 name_len: usize,
353) -> Result<()> {
354 let service = NAMINGSERVICE.get().unwrap();
355 let mut binding = service.handles.lock().unwrap();
356 let client = binding
357 .lookup_mut(info.source_context().unwrap_or(0.into()), desc)
358 .ok_or(ErrorKind::Other)?;
359
360 let path = client.read_buffer(name_len)?;
361
362 client.session.change_namespace(path)
363}