naming_srv/
lib.rs

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        // Create and map a handle for the simple buffer.
37        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    // TODO: discard all object pages.
55    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        // Create and map a handle for the simple buffer.
71        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// How would this work if I changed the root while handles were open?
142#[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    // TODO: make not bad
310    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    // TODO: make not bad
340    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}