-
Notifications
You must be signed in to change notification settings - Fork 33
Description
I found Motor OS after the std implementation merged today (congrats on that!) and took a look around.
I noticed that you use the default Read::read_buf implementation, since your runtime read takes &mut [u8]. I've added read_buf implementations much more widely throughout std as a pet project (I want to see it stabilized). For the Hermit unikernel, since it's linked to a user program as a library, I changed their read to take &mut [MaybeUninit<u8>] so it works for both and is sound for their C FFI (hermit-os/kernel#1606). Conversely, for RISC Zero, although they take initialized memory for read, any memory from the guest was already initialized by the host, so it is safe to implement read_buf with it (risc0/risc0#2853). In your case, I don't know which it falls under. It has stronger separation from user programs than Hermit, but I doubt the unique guarantee of RISC Zero holds here.
motor-os/src/sys/lib/rt.vdso/src/rt_fs.rs
Line 687 in 9f47637
| fn read(file: &File, buf: &mut [u8]) -> Result<usize, ErrorCode> { |
Additionally, RtVdsoVtable extensively violates strict provenance by casting function pointers to u64. Is there some reason you're using AtomicU64 instead of AtomicPtr<_>?
motor-os/src/sys/lib/moto-rt/src/lib.rs
Lines 121 to 238 in 9f47637
| pub struct RtVdsoVtable { | |
| // This function is called to initialize this VTable | |
| // (i.e. all fields other than vdso_entry and vdso_bytes_sz). | |
| // Initialized by the loader/parent. | |
| pub vdso_entry: AtomicU64, | |
| // The size of vdso bytes (the address is fixed at RT_VDSO_BYTES_ADDR). | |
| // Initialized by the loader/parent. | |
| pub vdso_bytes_sz: AtomicU64, | |
| // Memory management. | |
| pub alloc: AtomicU64, | |
| pub alloc_zeroed: AtomicU64, | |
| pub realloc: AtomicU64, | |
| pub dealloc: AtomicU64, | |
| pub release_handle: AtomicU64, | |
| // Time management. | |
| pub time_instant_now: AtomicU64, | |
| pub time_ticks_to_nanos: AtomicU64, | |
| pub time_nanos_to_ticks: AtomicU64, | |
| pub time_ticks_in_sec: AtomicU64, | |
| pub time_abs_ticks_to_nanos: AtomicU64, | |
| // Futex. | |
| pub futex_wait: AtomicU64, | |
| pub futex_wake: AtomicU64, | |
| pub futex_wake_all: AtomicU64, | |
| // Process-related. | |
| pub proc_args: AtomicU64, | |
| pub proc_get_full_env: AtomicU64, | |
| pub proc_getenv: AtomicU64, | |
| pub proc_setenv: AtomicU64, | |
| pub proc_spawn: AtomicU64, | |
| pub proc_kill: AtomicU64, | |
| pub proc_wait: AtomicU64, | |
| pub proc_status: AtomicU64, | |
| pub proc_exit: AtomicU64, | |
| // Thread Local Storage. | |
| pub tls_create: AtomicU64, | |
| pub tls_set: AtomicU64, | |
| pub tls_get: AtomicU64, | |
| pub tls_destroy: AtomicU64, | |
| // Thread management. | |
| pub thread_spawn: AtomicU64, | |
| pub thread_sleep: AtomicU64, | |
| pub thread_yield: AtomicU64, | |
| pub thread_set_name: AtomicU64, | |
| pub thread_join: AtomicU64, | |
| // Filesystem. | |
| pub fs_is_terminal: AtomicU64, | |
| pub fs_open: AtomicU64, | |
| pub fs_close: AtomicU64, | |
| pub fs_get_file_attr: AtomicU64, | |
| pub fs_fsync: AtomicU64, | |
| pub fs_datasync: AtomicU64, | |
| pub fs_truncate: AtomicU64, | |
| pub fs_read: AtomicU64, | |
| pub fs_read_vectored: AtomicU64, | |
| pub fs_write: AtomicU64, | |
| pub fs_write_vectored: AtomicU64, | |
| pub fs_flush: AtomicU64, | |
| pub fs_seek: AtomicU64, | |
| pub fs_mkdir: AtomicU64, | |
| pub fs_unlink: AtomicU64, | |
| pub fs_rename: AtomicU64, | |
| pub fs_rmdir: AtomicU64, | |
| pub fs_rmdir_all: AtomicU64, | |
| pub fs_set_perm: AtomicU64, | |
| pub fs_set_file_perm: AtomicU64, | |
| pub fs_stat: AtomicU64, | |
| pub fs_canonicalize: AtomicU64, | |
| pub fs_copy: AtomicU64, | |
| pub fs_opendir: AtomicU64, | |
| pub fs_closedir: AtomicU64, | |
| pub fs_readdir: AtomicU64, | |
| pub fs_getcwd: AtomicU64, | |
| pub fs_chdir: AtomicU64, | |
| pub fs_duplicate: AtomicU64, | |
| // Networking. | |
| pub dns_lookup: AtomicU64, | |
| pub net_bind: AtomicU64, | |
| pub net_listen: AtomicU64, | |
| pub net_accept: AtomicU64, | |
| pub net_tcp_connect: AtomicU64, | |
| pub net_udp_connect: AtomicU64, | |
| pub net_socket_addr: AtomicU64, | |
| pub net_peer_addr: AtomicU64, | |
| pub net_setsockopt: AtomicU64, | |
| pub net_getsockopt: AtomicU64, | |
| pub net_peek: AtomicU64, | |
| pub net_udp_recv_from: AtomicU64, | |
| pub net_udp_peek_from: AtomicU64, | |
| pub net_udp_send_to: AtomicU64, | |
| pub net_udp_multicast_op_v4: AtomicU64, | |
| pub net_udp_multicast_op_v6: AtomicU64, | |
| // Polling. | |
| pub poll_new: AtomicU64, | |
| pub poll_add: AtomicU64, | |
| pub poll_set: AtomicU64, | |
| pub poll_del: AtomicU64, | |
| pub poll_wait: AtomicU64, | |
| pub poll_wake: AtomicU64, | |
| // Some utilities. | |
| pub log_to_kernel: AtomicU64, | |
| pub log_backtrace: AtomicU64, | |
| pub fill_random_bytes: AtomicU64, | |
| pub num_cpus: AtomicU64, | |
| pub internal_helper: AtomicU64, | |
| pub current_exe: AtomicU64, | |
| } |
motor-os/src/sys/lib/rt.vdso/src/main.rs
Lines 44 to 420 in 9f47637
| pub extern "C" fn motor_start(version: u64) { | |
| if version != RT_VERSION { | |
| // Doing an assert or panic will #PF, so we use lower-level API. | |
| moto_log!("VDSO: unsupported version: {version}."); | |
| moto_sys::sys_cpu::SysCpu::exit(1) | |
| } | |
| let vtable = RtVdsoVtable::get(); | |
| let self_addr = motor_start as *const () as usize as u64; | |
| assert_eq!(vtable.vdso_entry.load(Ordering::Acquire), self_addr); | |
| // Memory management. | |
| vtable.alloc.store( | |
| rt_alloc::alloc as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.alloc_zeroed.store( | |
| rt_alloc::alloc_zeroed as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.dealloc.store( | |
| rt_alloc::dealloc as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.realloc.store( | |
| rt_alloc::realloc as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.release_handle.store( | |
| rt_alloc::release_handle as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| // Time management. | |
| vtable.time_instant_now.store( | |
| rt_time::time_instant_now as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.time_ticks_to_nanos.store( | |
| rt_time::ticks_to_nanos as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.time_nanos_to_ticks.store( | |
| rt_time::nanos_to_ticks as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.time_ticks_in_sec.store( | |
| moto_sys::KernelStaticPage::get().tsc_in_sec, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.time_abs_ticks_to_nanos.store( | |
| rt_time::abs_ticks_to_nanos as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| // Futex. | |
| vtable.futex_wait.store( | |
| rt_futex::futex_wait as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.futex_wake.store( | |
| rt_futex::futex_wake as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.futex_wake_all.store( | |
| rt_futex::futex_wake_all as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| // Process-related. | |
| vtable.proc_args.store( | |
| rt_process::args as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.proc_get_full_env.store( | |
| rt_process::get_full_env as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.proc_getenv.store( | |
| rt_process::getenv as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.proc_setenv.store( | |
| rt_process::setenv as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.proc_spawn.store( | |
| rt_process::spawn as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.proc_kill.store( | |
| rt_process::kill as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.proc_wait.store( | |
| rt_process::wait as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.proc_status.store( | |
| rt_process::status as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.proc_exit.store( | |
| rt_process::exit as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| // Thread Local Storage. | |
| vtable.tls_create.store( | |
| rt_tls::create as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable | |
| .tls_set | |
| .store(rt_tls::set as *const () as usize as u64, Ordering::Relaxed); | |
| vtable | |
| .tls_get | |
| .store(rt_tls::get as *const () as usize as u64, Ordering::Relaxed); | |
| vtable.tls_destroy.store( | |
| rt_tls::destroy as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| // Thread management. | |
| vtable.thread_spawn.store( | |
| rt_thread::spawn as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.thread_yield.store( | |
| rt_thread::yield_now as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.thread_sleep.store( | |
| rt_thread::sleep as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.thread_set_name.store( | |
| rt_thread::set_name as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.thread_join.store( | |
| rt_thread::join as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| // Filesystem. | |
| vtable.fs_is_terminal.store( | |
| rt_fs::is_terminal as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable | |
| .fs_open | |
| .store(rt_fs::open as *const () as usize as u64, Ordering::Relaxed); | |
| vtable.fs_close.store( | |
| posix::posix_close as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_get_file_attr.store( | |
| rt_fs::get_file_attr as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable | |
| .fs_fsync | |
| .store(rt_fs::fsync as *const () as usize as u64, Ordering::Relaxed); | |
| vtable.fs_datasync.store( | |
| rt_fs::datasync as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_truncate.store( | |
| rt_fs::truncate as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_read.store( | |
| posix::posix_read as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_read_vectored.store( | |
| posix::posix_read_vectored as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_write.store( | |
| posix::posix_write as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_write_vectored.store( | |
| posix::posix_write_vectored as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_flush.store( | |
| posix::posix_flush as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable | |
| .fs_seek | |
| .store(rt_fs::seek as *const () as usize as u64, Ordering::Relaxed); | |
| vtable | |
| .fs_mkdir | |
| .store(rt_fs::mkdir as *const () as usize as u64, Ordering::Relaxed); | |
| vtable.fs_unlink.store( | |
| rt_fs::unlink as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_rename.store( | |
| rt_fs::rename as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable | |
| .fs_rmdir | |
| .store(rt_fs::rmdir as *const () as usize as u64, Ordering::Relaxed); | |
| vtable.fs_rmdir_all.store( | |
| rt_fs::rmdir_all as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_set_perm.store( | |
| rt_fs::set_perm as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_set_file_perm.store( | |
| rt_fs::set_file_perm as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable | |
| .fs_stat | |
| .store(rt_fs::stat as *const () as usize as u64, Ordering::Relaxed); | |
| vtable.fs_canonicalize.store( | |
| rt_fs::canonicalize as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable | |
| .fs_copy | |
| .store(rt_fs::copy as *const () as usize as u64, Ordering::Relaxed); | |
| vtable.fs_opendir.store( | |
| rt_fs::opendir as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_closedir.store( | |
| rt_fs::closedir as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_readdir.store( | |
| rt_fs::readdir as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fs_getcwd.store( | |
| rt_fs::getcwd as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable | |
| .fs_chdir | |
| .store(rt_fs::chdir as *const () as usize as u64, Ordering::Relaxed); | |
| vtable.fs_duplicate.store( | |
| posix::posix_duplicate as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| // Networking. | |
| vtable.dns_lookup.store( | |
| net::rt_net::dns_lookup as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_bind.store( | |
| net::rt_net::bind as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_listen.store( | |
| net::rt_net::listen as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_accept.store( | |
| net::rt_net::accept as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_tcp_connect.store( | |
| net::rt_net::tcp_connect as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_udp_connect.store( | |
| net::rt_net::udp_connect as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_socket_addr.store( | |
| net::rt_net::socket_addr as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_peer_addr.store( | |
| net::rt_net::peer_addr as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_setsockopt.store( | |
| net::rt_net::setsockopt as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_getsockopt.store( | |
| net::rt_net::getsockopt as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_peek.store( | |
| net::rt_net::peek as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_udp_recv_from.store( | |
| net::rt_net::udp_recv_from as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_udp_peek_from.store( | |
| net::rt_net::udp_peek_from as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_udp_send_to.store( | |
| net::rt_net::udp_send_to as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_udp_multicast_op_v4.store( | |
| vdso_unimplemented as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.net_udp_multicast_op_v6.store( | |
| vdso_unimplemented as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| // Poll. | |
| vtable | |
| .poll_new | |
| .store(rt_poll::new as *const () as usize as u64, Ordering::Relaxed); | |
| vtable | |
| .poll_add | |
| .store(rt_poll::add as *const () as usize as u64, Ordering::Relaxed); | |
| vtable | |
| .poll_set | |
| .store(rt_poll::set as *const () as usize as u64, Ordering::Relaxed); | |
| vtable | |
| .poll_del | |
| .store(rt_poll::del as *const () as usize as u64, Ordering::Relaxed); | |
| vtable.poll_wait.store( | |
| rt_poll::wait as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.poll_wake.store( | |
| rt_poll::wake as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| // Misc. | |
| vtable.log_to_kernel.store( | |
| util::logging::log_to_kernel as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.log_backtrace.store( | |
| util::logging::log_backtrace as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.fill_random_bytes.store( | |
| fill_random_bytes as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.internal_helper.store( | |
| vdso_internal_helper as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable.current_exe.store( | |
| rt_process::current_exe as *const () as usize as u64, | |
| Ordering::Relaxed, | |
| ); | |
| vtable | |
| .num_cpus | |
| .store(num_cpus as *const () as usize as u64, Ordering::Relaxed); | |
| // The final fence. | |
| core::sync::atomic::fence(core::sync::atomic::Ordering::Release); | |
| let _ = moto_sys::set_current_thread_name("main"); | |
| stdio::init(); | |
| } |
Although today's nightly includes the Motor PR, I am unable to install the target. The current instructions in docs/build.md also do not work for me. I'll try again tomorrow?
$ rustup override set nightly-2025-10-17
$ rustup target remove x86_64-unknown-motor --toolchain nightly-2025-10-17
warn: removing the last target; no build targets will be available
error: toolchain 'nightly-2025-10-17-x86_64-unknown-linux-gnu' does not have target 'x86_64-unknown-motor' installedIf either of these issues are worth fixing, I'll send PRs as soon as I can get a local build.