1use crate::ipc::{channel, port, semaphore, shared_ring, ChanId, PortId, RingId, SemId};
17
18use super::{
19 chan, debug, error::SyscallError, exec::sys_execve, fork::sys_fork, ipc_port, ipc_ring, net,
20 numbers::*, pci, process as proc_sys, semaphore as sem_handler, transport, volume,
21 SyscallFrame,
22};
23use crate::{
24 async_io::syscall as async_sys,
25 capability::{release_capability, CapId, CapPermissions, ResourceType},
26 memory::{UserSliceRead, UserSliceWrite},
27 process::current_task_clone,
28 silo,
29};
30use core::sync::atomic::Ordering;
31static SYSCALL_DIAG_DONE: core::sync::atomic::AtomicBool =
33 core::sync::atomic::AtomicBool::new(false);
34
35static SYSCALL_TRACE_COUNT: core::sync::atomic::AtomicU64 = core::sync::atomic::AtomicU64::new(0);
38
39#[no_mangle]
51pub extern "C" fn __strat9_syscall_dispatch(frame: &mut SyscallFrame) -> u64 {
52 let syscall_num = frame.rax as usize;
53 let arg1 = frame.rdi;
54 let arg2 = frame.rsi;
55 let arg3 = frame.rdx;
56
57 if !SYSCALL_DIAG_DONE.swap(true, core::sync::atomic::Ordering::Relaxed) {
59 crate::e9_println!(
60 "[syscall-FIRST] nr={} rip={:#x} tid={:?}",
61 syscall_num,
62 frame.rcx,
63 crate::process::current_task_id().map(|t| t.as_u64())
64 );
65 }
66 let arg4 = frame.r10;
67 let _arg5 = frame.r8;
68 let _arg6 = frame.r9;
69
70 {
81 let n = SYSCALL_TRACE_COUNT.load(core::sync::atomic::Ordering::Relaxed);
82 if n < 20 || n % 10_000 == 0 || n == u64::MAX {
83 let n = SYSCALL_TRACE_COUNT.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
85 if n < 20 || n % 10_000 == 0 {
86 if let Some(tid) = crate::process::current_task_id() {
87 crate::e9_println!(
88 "[syscall] ENTER n={} tid={} nr={} arg1={:#x} arg2={:#x} rip={:#x} cpu={}",
89 n,
90 tid,
91 syscall_num,
92 arg1,
93 arg2,
94 frame.rcx,
95 crate::arch::x86_64::percpu::current_cpu_index()
96 );
97 }
98 }
99 } else {
100 SYSCALL_TRACE_COUNT.store(n + 1, core::sync::atomic::Ordering::Relaxed);
103 }
104 }
105
106 let result = match syscall_num {
107 SYS_NULL => sys_null(),
108 SYS_HANDLE_DUPLICATE => sys_handle_duplicate(arg1),
109 SYS_HANDLE_CLOSE => sys_handle_close(arg1),
110 SYS_HANDLE_WAIT => sys_handle_wait(arg1, arg2),
111 SYS_HANDLE_GRANT => sys_handle_grant(arg1, arg2),
112 SYS_HANDLE_REVOKE => sys_handle_revoke(arg1),
113 SYS_HANDLE_INFO => sys_handle_info(arg1, arg2),
114
115 SYS_MMAP => super::mmap::sys_mmap(arg1, arg2, arg3 as u32, arg4 as u32, frame.r8, frame.r9),
117 SYS_MUNMAP => super::mmap::sys_munmap(arg1, arg2),
118 SYS_BRK => super::mmap::sys_brk(arg1),
119 SYS_MREMAP => super::mmap::sys_mremap(arg1, arg2, arg3, arg4),
120 SYS_MPROTECT => super::mmap::sys_mprotect(arg1, arg2, arg3),
121 SYS_MEM_REGION_EXPORT => super::mmap::sys_mem_region_export(arg1),
122 SYS_MEM_REGION_MAP => super::mmap::sys_mem_region_map(arg1, arg2, arg3),
123 SYS_MEM_REGION_INFO => super::mmap::sys_mem_region_info(arg1, arg2),
124
125 SYS_PROC_EXIT => sys_proc_exit(arg1),
127 SYS_PROC_YIELD => sys_proc_yield(),
128 SYS_PROC_FORK => sys_fork(frame).map(|result| result.child_pid as u64),
129 SYS_PROC_GETPID | SYS_GETPID => proc_sys::sys_getpid(),
130 SYS_PROC_GETPPID => proc_sys::sys_getppid(),
131 SYS_GETTID => proc_sys::sys_gettid(),
132 SYS_PROC_WAITPID => {
133 super::wait::sys_waitpid(arg1 as i64, arg2, arg3 as u32).map(|pid| pid as u64)
134 }
135 SYS_PROC_WAIT => super::wait::sys_wait(arg1),
136 SYS_PROC_EXECVE => sys_execve(frame, arg1, arg2, arg3),
137
138 SYS_FCNTL => super::fcntl::sys_fcntl(arg1, arg2, arg3),
140 SYS_SETPGID => proc_sys::sys_setpgid(arg1 as i64, arg2 as i64),
141 SYS_GETPGID => proc_sys::sys_getpgid(arg1 as i64),
142 SYS_SETSID => proc_sys::sys_setsid(),
143 SYS_GETPGRP => proc_sys::sys_getpgrp(),
144 SYS_GETSID => proc_sys::sys_getsid(arg1 as i64),
145
146 SYS_GETUID => proc_sys::sys_getuid(),
147 SYS_GETEUID => proc_sys::sys_geteuid(),
148 SYS_GETGID => proc_sys::sys_getgid(),
149 SYS_GETEGID => proc_sys::sys_getegid(),
150 SYS_SETUID => proc_sys::sys_setuid(arg1),
151 SYS_SETGID => proc_sys::sys_setgid(arg1),
152 SYS_THREAD_CREATE => proc_sys::sys_thread_create(frame, arg1, arg2, arg3, arg4, frame.r8),
153 SYS_THREAD_JOIN => proc_sys::sys_thread_join(arg1, arg2, arg3),
154 SYS_THREAD_EXIT => proc_sys::sys_thread_exit(arg1),
155 SYS_UNAME => sys_uname(arg1),
156 SYS_SET_TID_ADDRESS => proc_sys::sys_set_tid_address(arg1),
158 SYS_EXIT_GROUP => proc_sys::sys_exit_group(arg1),
159 SYS_ARCH_PRCTL => proc_sys::sys_arch_prctl(arg1, arg2),
161
162 SYS_TGKILL => proc_sys::sys_tgkill(arg1, arg2, arg3),
164 SYS_RT_SIGRETURN => super::signal::sys_rt_sigreturn(frame),
165 SYS_FUTEX_WAIT => super::futex::sys_futex_wait(arg1, arg2 as u32, arg3),
167 SYS_FUTEX_WAKE => super::futex::sys_futex_wake(arg1, arg2 as u32),
168 SYS_FUTEX_REQUEUE => super::futex::sys_futex_requeue(arg1, arg2 as u32, arg3 as u32, arg4),
169 SYS_FUTEX_CMP_REQUEUE => super::futex::sys_futex_cmp_requeue(
170 arg1,
171 arg2 as u32,
172 arg3 as u32,
173 arg4,
174 frame.r8 as u32,
175 ),
176 SYS_FUTEX_WAKE_OP => {
177 super::futex::sys_futex_wake_op(arg1, arg2 as u32, arg3 as u32, arg4, frame.r8 as u32)
178 }
179 SYS_KILL => super::signal::sys_kill(arg1 as i64, arg2 as u32),
180 SYS_SIGPROCMASK => sys_sigprocmask(arg1 as i32, arg2, arg3),
181 SYS_SIGACTION => super::signal::sys_sigaction(arg1, arg2, arg3),
182 SYS_SIGALTSTACK => super::signal::sys_sigaltstack(arg1, arg2),
183 SYS_SIGPENDING => super::signal::sys_sigpending(arg1),
184 SYS_SIGSUSPEND => super::signal::sys_sigsuspend(arg1),
185 SYS_SIGTIMEDWAIT => super::signal::sys_sigtimedwait(arg1, arg2, arg3),
186 SYS_SIGQUEUE => super::signal::sys_sigqueue(arg1 as i64, arg2 as u32, arg3),
187 SYS_KILLPG => super::signal::sys_killpg(arg1, arg2 as u32),
188 SYS_GETITIMER => super::signal::sys_getitimer(arg1 as u32, arg2),
189 SYS_SETITIMER => super::signal::sys_setitimer(arg1 as u32, arg2, arg3),
190
191 SYS_IPC_CREATE_PORT => ipc_port::sys_ipc_create_port(arg1),
193 SYS_IPC_SEND => ipc_port::sys_ipc_send(arg1, arg2),
194 SYS_IPC_RECV => ipc_port::sys_ipc_recv(arg1, arg2),
195 SYS_IPC_TRY_RECV => ipc_port::sys_ipc_try_recv(arg1, arg2),
196 SYS_IPC_CONNECT => ipc_port::sys_ipc_connect(arg1, arg2),
197 SYS_IPC_CALL => ipc_port::sys_ipc_call(arg1, arg2),
198 SYS_IPC_REPLY => ipc_port::sys_ipc_reply(arg1),
199 SYS_IPC_BIND_PORT => ipc_port::sys_ipc_bind_port(arg1, arg2, arg3),
200 SYS_IPC_UNBIND_PORT => ipc_port::sys_ipc_unbind_port(arg1, arg2),
201
202 SYS_IPC_RING_CREATE => ipc_ring::sys_ipc_ring_create(arg1),
204 SYS_IPC_RING_MAP => ipc_ring::sys_ipc_ring_map(arg1, arg2),
205
206 SYS_SEM_CREATE => sem_handler::sys_sem_create(arg1),
208 SYS_SEM_WAIT => sem_handler::sys_sem_wait(arg1),
209 SYS_SEM_TRYWAIT => sem_handler::sys_sem_trywait(arg1),
210 SYS_SEM_POST => sem_handler::sys_sem_post(arg1),
211 SYS_SEM_CLOSE => sem_handler::sys_sem_close(arg1),
212
213 SYS_ASYNC_SETUP => async_sys::sys_async_setup(arg1, arg2),
215 SYS_ASYNC_ENTER => async_sys::sys_async_enter(arg1, arg2, arg3, arg4),
216 SYS_ASYNC_CANCEL => async_sys::sys_async_cancel(arg1, arg2, arg3),
217 SYS_ASYNC_MAP => async_sys::sys_async_map(arg1, arg2),
218 SYS_ASYNC_DESTROY => async_sys::sys_async_destroy(arg1, arg2),
219
220 SYS_TRANSPORT_CREATE => transport::sys_transport_create(arg1, arg2),
222 SYS_TRANSPORT_SEND => transport::sys_transport_send(arg1, arg2, arg3),
223 SYS_TRANSPORT_RECV => transport::sys_transport_recv(arg1, arg2, arg3),
224 SYS_TRANSPORT_CLOSE => transport::sys_transport_close(arg1),
225 SYS_TRANSPORT_INFO => transport::sys_transport_info(arg1, arg2),
226
227 SYS_PCI_ENUM => pci::sys_pci_enum(arg1, arg2, arg3),
229 SYS_PCI_CFG_READ => pci::sys_pci_cfg_read(arg1, arg2, arg3),
230 SYS_PCI_CFG_WRITE => pci::sys_pci_cfg_write(arg1, arg2, arg3, arg4),
231
232 SYS_CHAN_CREATE => chan::sys_chan_create(arg1),
234 SYS_CHAN_SEND => chan::sys_chan_send(arg1, arg2),
235 SYS_CHAN_RECV => chan::sys_chan_recv(arg1, arg2),
236 SYS_CHAN_TRY_RECV => chan::sys_chan_try_recv(arg1, arg2),
237 SYS_CHAN_CLOSE => chan::sys_chan_close(arg1),
238 SYS_MODULE_LOAD => silo::sys_module_load(arg1, arg2),
239 SYS_MODULE_UNLOAD => silo::sys_module_unload(arg1),
240 SYS_MODULE_GET_SYMBOL => silo::sys_module_get_symbol(arg1, arg2),
241 SYS_MODULE_QUERY => silo::sys_module_query(arg1, arg2),
242 SYS_OPEN => sys_open(arg1, arg2, arg3),
243 SYS_WRITE => sys_write(arg1, arg2, arg3),
244 SYS_READ => sys_read(arg1, arg2, arg3),
245 SYS_CLOSE => sys_close(arg1),
246 SYS_LSEEK => sys_lseek(arg1, arg2, arg3),
247 SYS_FSTAT => sys_fstat(arg1, arg2),
248 SYS_STAT => sys_stat(arg1, arg2, arg3),
249 SYS_ACCESS => crate::vfs::sys_access(arg1, arg2, arg3),
250 SYS_GETDENTS => sys_getdents(arg1, arg2, arg3),
251 SYS_PIPE => sys_pipe(arg1),
252 SYS_DUP => sys_dup(arg1),
253 SYS_DUP2 => sys_dup2(arg1, arg2),
254
255 SYS_CHDIR => crate::vfs::sys_chdir(arg1, arg2),
257 SYS_FCHDIR => crate::vfs::sys_fchdir(arg1 as u32),
258 SYS_GETCWD => crate::vfs::sys_getcwd(arg1, arg2),
259 SYS_IOCTL => crate::vfs::sys_ioctl(arg1 as u32, arg2, arg3),
260 SYS_UMASK => crate::vfs::sys_umask(arg1),
261 SYS_UNLINK => crate::vfs::sys_unlink(arg1, arg2),
262 SYS_RMDIR => crate::vfs::sys_rmdir(arg1, arg2),
263 SYS_MKDIR => crate::vfs::sys_mkdir(arg1, arg2, arg3),
264 SYS_RENAME => crate::vfs::sys_rename(arg1, arg2, arg3, arg4),
265 SYS_LINK => crate::vfs::sys_link(arg1, arg2, arg3, arg4),
266 SYS_SYMLINK => crate::vfs::sys_symlink(arg1, arg2, arg3, arg4),
267 SYS_READLINK => crate::vfs::sys_readlink(arg1, arg2, arg3, arg4),
268 SYS_CHMOD => crate::vfs::sys_chmod(arg1, arg2, arg3),
269 SYS_FCHMOD => crate::vfs::sys_fchmod(arg1 as u32, arg2),
270 SYS_TRUNCATE => crate::vfs::sys_truncate(arg1, arg2, arg3),
271 SYS_FTRUNCATE => crate::vfs::sys_ftruncate(arg1 as u32, arg2),
272 SYS_PREAD => crate::vfs::sys_pread(arg1 as u32, arg2, arg3, arg4),
273 SYS_PWRITE => crate::vfs::sys_pwrite(arg1 as u32, arg2, arg3, arg4),
274 SYS_POLL => super::poll::sys_poll(arg1, arg2, arg3),
275 SYS_PPOLL => super::poll::sys_poll(arg1, arg2, 0),
276
277 SYS_OPENAT => crate::vfs::sys_openat(arg1, arg2, arg3, arg4),
279 SYS_FSTATAT => crate::vfs::sys_fstatat(arg1, arg2, arg3, arg4),
280 SYS_FACCESSAT => crate::vfs::sys_faccessat(arg1, arg2, arg3, arg4, frame.r8),
281
282 SYS_NET_RECV => net::sys_net_recv(arg1, arg2),
284 SYS_NET_SEND => net::sys_net_send(arg1, arg2),
285 SYS_NET_INFO => net::sys_net_info(arg1, arg2),
286
287 SYS_VOLUME_READ => volume::sys_volume_read(arg1, arg2, arg3, arg4),
289 SYS_VOLUME_WRITE => volume::sys_volume_write(arg1, arg2, arg3, arg4),
290 SYS_VOLUME_INFO => volume::sys_volume_info(arg1),
291 SYS_CLOCK_GETTIME => super::time::sys_clock_gettime(arg1 as u32, arg2),
292 SYS_NANOSLEEP => super::time::sys_nanosleep(arg1, arg2),
293 SYS_CLOCK_NANOSLEEP => {
294 super::time::sys_clock_nanosleep(arg1 as u32, arg2 as i32, arg3, arg4)
295 }
296 SYS_DEBUG_LOG => debug::sys_debug_log(arg1, arg2),
297 SYS_GETRANDOM => super::random::sys_getrandom(arg1, arg2 as usize, arg3 as u32),
298 SYS_SET_ROBUST_LIST => super::robust_list::sys_set_robust_list(arg1, arg2 as usize),
299 SYS_GET_ROBUST_LIST => super::robust_list::sys_get_robust_list(arg1 as i64, arg2, arg3),
300
301 SYS_SILO_CREATE => silo::sys_silo_create(arg1),
303 SYS_SILO_CONFIG => silo::sys_silo_config(arg1, arg2),
304 SYS_SILO_ATTACH_MODULE => silo::sys_silo_attach_module(arg1, arg2),
305 SYS_SILO_START => silo::sys_silo_start(arg1),
306 SYS_SILO_STOP => silo::sys_silo_stop(arg1),
307 SYS_SILO_KILL => silo::sys_silo_kill(arg1),
308 SYS_SILO_EVENT_NEXT => silo::sys_silo_event_next(arg1),
309 SYS_SILO_SUSPEND => silo::sys_silo_suspend(arg1),
310 SYS_SILO_RESUME => silo::sys_silo_resume(arg1),
311 SYS_SILO_PLEDGE => silo::sys_silo_pledge(arg1),
312 SYS_SILO_UNVEIL => silo::sys_silo_unveil(arg1, arg2, arg3),
313 SYS_SILO_ENTER_SANDBOX => silo::sys_silo_enter_sandbox(),
314 SYS_SILO_RENAME => silo::sys_silo_rename(arg1, arg2, arg3),
315
316 SYS_ABI_VERSION => {
318 Ok(((strat9_abi::ABI_VERSION_MAJOR as u64) << 16)
319 | (strat9_abi::ABI_VERSION_MINOR as u64))
320 }
321 _ => {
322 log::warn!("Unknown syscall: {} (0x{:x})", syscall_num, syscall_num);
323 Err(SyscallError::NotImplemented)
324 }
325 };
326 match result {
329 Ok(val) => {
330 if syscall_num == SYS_PROC_FORK {
331 crate::serial_println!("[syscall] FORK returning Ok({})", val);
332 }
333 frame.rax = val;
334 }
335 Err(e) => {
336 if syscall_num == SYS_PROC_FORK {
337 crate::serial_println!("[syscall] FORK returning err");
338 }
339 frame.rax = e.to_raw();
340 }
341 }
342
343 if crate::arch::x86_64::percpu::test_and_clear_signal_pending_current() {
351 crate::process::signal::deliver_pending_signal(frame);
352 }
353
354 frame.rax
355}
356
357#[no_mangle]
360pub extern "C" fn dispatch(frame: &mut SyscallFrame) -> u64 {
361 __strat9_syscall_dispatch(frame)
362}
363
364fn sys_null() -> Result<u64, SyscallError> {
370 Ok(0x57A79)
371}
372
373fn sys_handle_close(_handle: u64) -> Result<u64, SyscallError> {
375 crate::silo::enforce_cap_for_current_task(_handle)?;
376 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
377 let caps = unsafe { &mut *task.process.capabilities.get() };
378 if let Some(cap) = caps.remove(CapId::from_raw(_handle)) {
379 release_capability(&cap, Some(task.id));
380 log::trace!("syscall: HANDLE_CLOSE({})", _handle);
381 Ok(0)
382 } else {
383 Err(SyscallError::BadHandle)
384 }
385}
386
387pub(crate) fn insert_capability_with_retention(
388 caps: &mut crate::capability::CapabilityTable,
389 cap: crate::capability::Capability,
390) -> Result<CapId, SyscallError> {
391 let id = caps.insert(cap);
392 if let Some(inserted) = caps.get(id) {
393 if inserted.resource_type == ResourceType::MemoryRegion {
394 if let Err(error) =
395 crate::memory::memory_region_registry().retain_handle(inserted.resource as u64, id)
396 {
397 let _ = caps.remove(id);
398 return Err(match error {
399 crate::memory::RegionCapError::NotFound => SyscallError::BadHandle,
400 crate::memory::RegionCapError::InvalidRegion
401 | crate::memory::RegionCapError::IncompleteRegion
402 | crate::memory::RegionCapError::InvalidAddress => {
403 SyscallError::InvalidArgument
404 }
405 crate::memory::RegionCapError::PermissionDenied => {
406 SyscallError::PermissionDenied
407 }
408 crate::memory::RegionCapError::OutOfMemory => SyscallError::OutOfMemory,
409 crate::memory::RegionCapError::InconsistentState => SyscallError::IoError,
410 });
411 }
412 }
413 }
414 Ok(id)
415}
416
417fn sys_handle_duplicate(handle: u64) -> Result<u64, SyscallError> {
419 crate::silo::enforce_cap_for_current_task(handle)?;
420 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
421 let caps = unsafe { &mut *task.process.capabilities.get() };
422 let dup = caps
423 .duplicate(CapId::from_raw(handle))
424 .ok_or(SyscallError::PermissionDenied)?;
425 let id = insert_capability_with_retention(caps, dup)?;
426 Ok(id.as_u64())
427}
428
429const HANDLE_EVENT_READABLE: u64 = 1 << 0;
430const HANDLE_EVENT_WRITABLE: u64 = 1 << 1;
431
432fn poll_handle_events(handle: u64) -> Result<u64, SyscallError> {
434 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
435 let caps = unsafe { &*task.process.capabilities.get() };
436 let cap = caps
437 .get(CapId::from_raw(handle))
438 .ok_or(SyscallError::BadHandle)?;
439
440 match cap.resource_type {
441 ResourceType::Semaphore => {
442 if !cap.permissions.read {
443 return Err(SyscallError::PermissionDenied);
444 }
445 let sem = semaphore::get_semaphore(SemId::from_u64(cap.resource as u64))
446 .ok_or(SyscallError::BadHandle)?;
447 if sem.is_destroyed() {
448 return Err(SyscallError::Pipe);
449 }
450 if sem.count() > 0 {
451 Ok(HANDLE_EVENT_READABLE)
452 } else {
453 Ok(0)
454 }
455 }
456 ResourceType::IpcPort => {
457 let port = port::get_port(PortId::from_u64(cap.resource as u64))
458 .ok_or(SyscallError::BadHandle)?;
459 if port.is_destroyed() {
460 return Err(SyscallError::Pipe);
461 }
462 let mut events = 0u64;
463 if cap.permissions.read && port.has_messages() {
464 events |= HANDLE_EVENT_READABLE;
465 }
466 if cap.permissions.write && port.can_send() {
467 events |= HANDLE_EVENT_WRITABLE;
468 }
469 if events == 0 && !cap.permissions.read && !cap.permissions.write {
470 return Err(SyscallError::PermissionDenied);
471 }
472 Ok(events)
473 }
474 ResourceType::Channel => {
475 let chan = channel::get_channel(ChanId::from_u64(cap.resource as u64))
476 .ok_or(SyscallError::BadHandle)?;
477 if chan.is_destroyed() {
478 return Err(SyscallError::Pipe);
479 }
480 let mut events = 0u64;
481 if cap.permissions.read && !chan.is_empty() {
482 events |= HANDLE_EVENT_READABLE;
483 }
484 if cap.permissions.write && chan.can_send() {
485 events |= HANDLE_EVENT_WRITABLE;
486 }
487 if events == 0 && !cap.permissions.read && !cap.permissions.write {
488 return Err(SyscallError::PermissionDenied);
489 }
490 Ok(events)
491 }
492 ResourceType::SharedRing => {
493 let _ = shared_ring::get_ring(RingId::from_u64(cap.resource as u64))
494 .ok_or(SyscallError::BadHandle)?;
495 let mut events = 0u64;
496 if cap.permissions.read {
497 events |= HANDLE_EVENT_READABLE;
498 }
499 if cap.permissions.write {
500 events |= HANDLE_EVENT_WRITABLE;
501 }
502 if events == 0 {
503 return Err(SyscallError::PermissionDenied);
504 }
505 Ok(events)
506 }
507 ResourceType::IpcTransport => {
508 let tid = crate::ipc::transport::TransportId::from_u64(cap.resource as u64);
509 let endpoint = crate::syscall::transport::TRANSPORT_MANAGER
510 .get_endpoint(tid)
511 .ok_or(SyscallError::BadHandle)?;
512 let mut events = 0u64;
513 if cap.permissions.read && endpoint.has_data() {
514 events |= HANDLE_EVENT_READABLE;
515 }
516 if cap.permissions.write && endpoint.has_space() {
517 events |= HANDLE_EVENT_WRITABLE;
518 }
519 if events == 0 && !cap.permissions.read && !cap.permissions.write {
520 return Err(SyscallError::PermissionDenied);
521 }
522 Ok(events)
523 }
524 _ => Err(SyscallError::NotSupported),
525 }
526}
527
528fn sys_handle_wait(handle: u64, timeout_ns: u64) -> Result<u64, SyscallError> {
530 crate::silo::enforce_cap_for_current_task(handle)?;
531
532 let check_ready = || -> Result<u64, SyscallError> {
533 let events = poll_handle_events(handle)?;
534 if events != 0 {
535 Ok(events)
536 } else {
537 Err(SyscallError::Again)
538 }
539 };
540
541 if timeout_ns == 0 {
542 return check_ready();
543 }
544
545 let deadline = if timeout_ns == u64::MAX {
546 None
547 } else {
548 Some(crate::syscall::time::current_time_ns().saturating_add(timeout_ns))
549 };
550
551 loop {
552 if let Ok(events) = check_ready() {
553 return Ok(events);
554 }
555
556 if crate::process::has_pending_signals() {
557 return Err(SyscallError::Interrupted);
558 }
559
560 let now = crate::syscall::time::current_time_ns();
561 let wake_ns = if let Some(deadline_ns) = deadline {
562 if now >= deadline_ns {
563 return Err(SyscallError::TimedOut);
564 }
565 core::cmp::min(deadline_ns, now.saturating_add(10_000_000))
566 } else {
567 now.saturating_add(10_000_000)
568 };
569
570 if let Some(task) = current_task_clone() {
571 task.wake_deadline_ns.store(wake_ns, Ordering::Relaxed);
572 }
573 crate::process::block_current_task();
574 if let Some(task) = current_task_clone() {
575 task.wake_deadline_ns.store(0, Ordering::Relaxed);
576 }
577 }
578}
579
580fn sys_handle_grant(handle: u64, target_pid: u64) -> Result<u64, SyscallError> {
582 crate::silo::enforce_cap_for_current_task(handle)?;
583 crate::silo::enforce_silo_may_grant()?;
584 let pid = u32::try_from(target_pid).map_err(|_| SyscallError::InvalidArgument)?;
585
586 let source = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
587 let granted = {
588 let source_caps = unsafe { &*source.process.capabilities.get() };
589 let cap = source_caps
590 .get(CapId::from_raw(handle))
591 .ok_or(SyscallError::BadHandle)?;
592 if !cap.permissions.grant {
593 return Err(SyscallError::PermissionDenied);
594 }
595 let mut dup = cap.clone();
596 dup.id = CapId::new();
597 dup
598 };
599
600 let target = crate::process::get_task_by_pid(pid).ok_or(SyscallError::NotFound)?;
601 let target_caps = unsafe { &mut *target.process.capabilities.get() };
602 let new_id = insert_capability_with_retention(target_caps, granted)?;
603 Ok(new_id.as_u64())
604}
605
606fn sys_handle_revoke(handle: u64) -> Result<u64, SyscallError> {
608 crate::silo::enforce_cap_for_current_task(handle)?;
609 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
610 let caps = unsafe { &mut *task.process.capabilities.get() };
611
612 {
613 let cap = caps
614 .get(CapId::from_raw(handle))
615 .ok_or(SyscallError::BadHandle)?;
616 if !cap.permissions.revoke {
617 return Err(SyscallError::PermissionDenied);
618 }
619 }
620
621 let cap = caps
622 .remove(CapId::from_raw(handle))
623 .ok_or(SyscallError::BadHandle)?;
624 release_capability(&cap, Some(task.id));
625 Ok(0)
626}
627
628use strat9_abi::data::HandleInfo as HandleInfoAbi;
629
630fn cap_perm_bits(p: CapPermissions) -> u32 {
632 (if p.read { 1 } else { 0 })
633 | (if p.write { 1 << 1 } else { 0 })
634 | (if p.execute { 1 << 2 } else { 0 })
635 | (if p.grant { 1 << 3 } else { 0 })
636 | (if p.revoke { 1 << 4 } else { 0 })
637}
638
639fn resource_type_code(rt: ResourceType) -> u32 {
641 match rt {
642 ResourceType::MemoryRegion => 1,
643 ResourceType::IoPortRange => 2,
644 ResourceType::InterruptLine => 3,
645 ResourceType::IpcPort => 4,
646 ResourceType::Channel => 5,
647 ResourceType::SharedRing => 6,
648 ResourceType::Semaphore => 7,
649 ResourceType::Device => 8,
650 ResourceType::AddressSpace => 9,
651 ResourceType::Silo => 10,
652 ResourceType::Module => 11,
653 ResourceType::File => 12,
654 ResourceType::Nic => 13,
655 ResourceType::FileSystem => 14,
656 ResourceType::Console => 15,
657 ResourceType::Keyboard => 16,
658 ResourceType::Volume => 17,
659 ResourceType::Namespace => 18,
660 ResourceType::IpcTransport => 19,
661 }
662}
663
664fn sys_handle_info(handle: u64, out_ptr: u64) -> Result<u64, SyscallError> {
666 crate::silo::enforce_cap_for_current_task(handle)?;
667 if out_ptr == 0 {
668 return Err(SyscallError::Fault);
669 }
670 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
671 let caps = unsafe { &*task.process.capabilities.get() };
672 let cap = caps
673 .get(CapId::from_raw(handle))
674 .ok_or(SyscallError::BadHandle)?;
675
676 let info = HandleInfoAbi {
677 resource_type: resource_type_code(cap.resource_type),
678 permissions: cap_perm_bits(cap.permissions),
679 resource: cap.resource as u64,
680 };
681 let user = UserSliceWrite::new(out_ptr, core::mem::size_of::<HandleInfoAbi>())?;
682 let bytes = unsafe {
683 core::slice::from_raw_parts(
684 &info as *const HandleInfoAbi as *const u8,
685 core::mem::size_of::<HandleInfoAbi>(),
686 )
687 };
688 user.copy_from(bytes);
689 Ok(0)
690}
691
692fn sys_proc_exit(exit_code: u64) -> Result<u64, SyscallError> {
696 log::info!("syscall: PROC_EXIT(code={})", exit_code);
697
698 crate::process::scheduler::exit_current_task(exit_code as i32)
701}
702
703fn sys_proc_yield() -> Result<u64, SyscallError> {
705 crate::process::yield_task();
706 Ok(0)
707}
708
709fn sys_sigprocmask(how: i32, set_ptr: u64, oldset_ptr: u64) -> Result<u64, SyscallError> {
713 use crate::process::current_task_clone;
714
715 const SIG_BLOCK: i32 = 0;
716 const SIG_UNBLOCK: i32 = 1;
717 const SIG_SETMASK: i32 = 2;
718
719 let task = current_task_clone().ok_or(SyscallError::PermissionDenied)?;
720
721 let blocked = &task.blocked_signals;
722
723 if oldset_ptr != 0 {
724 let old_mask = blocked.get_mask();
725 let user = UserSliceWrite::new(oldset_ptr, 8)?;
726 user.copy_from(&old_mask.to_ne_bytes());
727 }
728
729 if set_ptr != 0 {
730 let user = UserSliceRead::new(set_ptr, 8)?;
731 let mut buf = [0u8; 8];
732 user.copy_to(&mut buf);
733 let new_mask = u64::from_ne_bytes(buf);
734
735 let old_mask = blocked.get_mask();
736 let updated_mask = match how {
737 SIG_BLOCK => old_mask | new_mask,
738 SIG_UNBLOCK => old_mask & !new_mask,
739 SIG_SETMASK => new_mask,
740 _ => return Err(SyscallError::InvalidArgument),
741 };
742
743 blocked.set_mask(updated_mask);
744 }
745
746 Ok(0)
747}
748
749fn sys_uname(uts_ptr: u64) -> Result<u64, SyscallError> {
751 const UTS_FIELD_LEN: usize = 65;
752 const UTS_TOTAL_LEN: usize = UTS_FIELD_LEN * 6;
753
754 if uts_ptr == 0 {
755 return Err(SyscallError::Fault);
756 }
757
758 fn write_field(dst: &mut [u8], src: &[u8]) {
760 let n = core::cmp::min(src.len(), dst.len().saturating_sub(1));
761 if n > 0 {
762 dst[..n].copy_from_slice(&src[..n]);
763 }
764 dst[n] = 0;
765 }
766
767 let mut uts = [0u8; UTS_TOTAL_LEN];
768 write_field(&mut uts[0 * UTS_FIELD_LEN..1 * UTS_FIELD_LEN], b"Strat9");
769 write_field(&mut uts[1 * UTS_FIELD_LEN..2 * UTS_FIELD_LEN], b"localhost");
770 write_field(&mut uts[2 * UTS_FIELD_LEN..3 * UTS_FIELD_LEN], b"0.1.0");
771 write_field(&mut uts[3 * UTS_FIELD_LEN..4 * UTS_FIELD_LEN], b"Strat9-OS");
772 write_field(&mut uts[4 * UTS_FIELD_LEN..5 * UTS_FIELD_LEN], b"x86_64");
773 write_field(
774 &mut uts[5 * UTS_FIELD_LEN..6 * UTS_FIELD_LEN],
775 b"localdomain",
776 );
777
778 let user = UserSliceWrite::new(uts_ptr, UTS_TOTAL_LEN)?;
779 user.copy_from(&uts);
780 Ok(0)
781}
782
783fn sys_write(fd: u64, buf_ptr: u64, buf_len: u64) -> Result<u64, SyscallError> {
785 crate::vfs::sys_write(fd as u32, buf_ptr, buf_len)
786}
787
788fn sys_open(path_ptr: u64, path_len: u64, flags: u64) -> Result<u64, SyscallError> {
790 crate::vfs::sys_open(path_ptr, path_len, flags)
791}
792
793fn sys_read(fd: u64, buf_ptr: u64, buf_len: u64) -> Result<u64, SyscallError> {
795 crate::vfs::sys_read(fd as u32, buf_ptr, buf_len)
796}
797
798fn sys_close(fd: u64) -> Result<u64, SyscallError> {
800 crate::vfs::sys_close(fd as u32)
801}
802
803fn sys_lseek(fd: u64, offset: u64, whence: u64) -> Result<u64, SyscallError> {
805 crate::vfs::sys_lseek(fd as u32, offset as i64, whence as u32)
806}
807
808fn sys_fstat(fd: u64, stat_ptr: u64) -> Result<u64, SyscallError> {
810 crate::vfs::sys_fstat(fd as u32, stat_ptr)
811}
812
813fn sys_stat(path_ptr: u64, path_len: u64, stat_ptr: u64) -> Result<u64, SyscallError> {
815 crate::vfs::sys_stat(path_ptr, path_len, stat_ptr)
816}
817
818fn sys_getdents(fd: u64, buf_ptr: u64, buf_len: u64) -> Result<u64, SyscallError> {
820 crate::vfs::sys_getdents(fd as u32, buf_ptr, buf_len)
821}
822
823fn sys_pipe(fds_ptr: u64) -> Result<u64, SyscallError> {
825 crate::vfs::sys_pipe(fds_ptr)
826}
827
828fn sys_dup(old_fd: u64) -> Result<u64, SyscallError> {
830 crate::vfs::sys_dup(old_fd as u32)
831}
832
833fn sys_dup2(old_fd: u64, new_fd: u64) -> Result<u64, SyscallError> {
835 crate::vfs::sys_dup2(old_fd as u32, new_fd as u32)
836}