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