naming_srv/
lib.rs

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