diff --git a/litebox_common_linux/src/lib.rs b/litebox_common_linux/src/lib.rs index e44b701d5..4554a97c3 100644 --- a/litebox_common_linux/src/lib.rs +++ b/litebox_common_linux/src/lib.rs @@ -11,7 +11,6 @@ use core::time::Duration; use int_enum::IntEnum; use litebox::{ fs::OFlags, - platform::{RawConstPointer, RawMutPointer}, utils::{ReinterpretSignedExt as _, ReinterpretUnsignedExt as _, TruncateExt as _}, }; use syscalls::Sysno; @@ -24,10 +23,13 @@ pub mod loader; pub mod mm; pub mod physical_pointers; pub mod signal; +pub mod user_pointers; pub mod vmap; extern crate alloc; +use user_pointers::{UserPtr, UserPtrMut}; + /// Number of AArch64 general-purpose registers saved by the Linux user ABI /// (`x0` through `x30`). #[cfg(target_arch = "aarch64")] @@ -344,39 +346,23 @@ pub struct FileStat { } /// Linux's `iovec` struct for `writev` -#[derive(FromBytes, IntoBytes)] +#[derive(Clone, Copy, FromBytes, IntoBytes)] #[repr(C, packed)] -pub struct IoWriteVec> { - pub iov_base: P, +pub struct IoWriteVec { + pub iov_base: UserPtr, pub iov_len: usize, } /// Linux's `iovec` struct for `readv` -#[derive(FromBytes, IntoBytes)] +#[derive(Clone, Copy, FromBytes, IntoBytes)] #[repr(C, packed)] -pub struct IoReadVec> { - pub iov_base: P, +pub struct IoReadVec { + pub iov_base: UserPtrMut, pub iov_len: usize, } /// `iovec` struct for both read and write -pub type IoVec

= IoReadVec

; - -impl> Clone for IoWriteVec

{ - fn clone(&self) -> Self { - *self - } -} - -impl> Copy for IoWriteVec

{} - -impl> Clone for IoReadVec

{ - fn clone(&self) -> Self { - *self - } -} - -impl> Copy for IoReadVec

{} +pub type IoVec = IoReadVec; impl From for FileStat { fn from(value: litebox::fs::FileStatus) -> Self { @@ -592,7 +578,7 @@ impl From for Statx { /// Commands for use with `fcntl`. #[derive(Debug)] #[non_exhaustive] -pub enum FcntlArg { +pub enum FcntlArg { /// Get the file descriptor flags GETFD, /// Set the file descriptor flags @@ -602,11 +588,11 @@ pub enum FcntlArg { /// Set descriptor status flags SETFL(OFlags), /// Get a file lock - GETLK(Platform::RawMutPointer), + GETLK(UserPtrMut), /// Set a file lock - SETLK(Platform::RawConstPointer), + SETLK(UserPtr), /// Set a file lock and wait if blocked - SETLKW(Platform::RawConstPointer), + SETLKW(UserPtr), /// Duplicate file descriptor DUPFD { cloexec: bool, min_fd: u32 }, } @@ -663,16 +649,16 @@ bitflags::bitflags! { } } -impl FcntlArg { +impl FcntlArg { pub fn try_from(cmd: i32, arg: usize) -> Option { Some(match cmd { F_GETFD => Self::GETFD, F_SETFD => Self::SETFD(FileDescriptorFlags::from_bits_truncate(arg.trunc())), F_GETFL => Self::GETFL, F_SETFL => Self::SETFL(OFlags::from_bits_truncate(arg.trunc())), - F_GETLK => Self::GETLK(Platform::RawMutPointer::from_usize(arg)), - F_SETLK => Self::SETLK(Platform::RawConstPointer::from_usize(arg)), - F_SETLKW => Self::SETLKW(Platform::RawConstPointer::from_usize(arg)), + F_GETLK => Self::GETLK(UserPtrMut::from_usize(arg)), + F_SETLK => Self::SETLK(UserPtr::from_usize(arg)), + F_SETLKW => Self::SETLKW(UserPtr::from_usize(arg)), F_DUPFD => Self::DUPFD { cloexec: false, min_fd: arg.trunc(), @@ -729,23 +715,23 @@ pub const TIOCGPTN: u32 = 0x80045430; /// Commands for use with `ioctl`. #[non_exhaustive] #[derive(Debug)] -pub enum IoctlArg { +pub enum IoctlArg { /// Get the current serial port settings. - TCGETS(Platform::RawMutPointer), + TCGETS(UserPtrMut), /// Set the current serial port settings. - TCSETS(Platform::RawConstPointer), + TCSETS(UserPtr), /// Get window size. - TIOCGWINSZ(Platform::RawMutPointer), + TIOCGWINSZ(UserPtrMut), /// Obtain device unit number, which can be used to generate /// the filename of the pseudo-terminal slave device. - TIOCGPTN(Platform::RawMutPointer), + TIOCGPTN(UserPtrMut), /// Enables or disables non-blocking mode - FIONBIO(Platform::RawConstPointer), + FIONBIO(UserPtr), /// Set close on exec FIOCLEX, Raw { cmd: u32, - arg: Platform::RawMutPointer, + arg: UserPtrMut, }, } @@ -1080,19 +1066,15 @@ pub enum ArchPrctlCode { /// Argument for the `arch_prctl` syscall, corresponding to the [`ArchPrctlCode`] enum. #[non_exhaustive] #[derive(Debug)] -pub enum ArchPrctlArg { +pub enum ArchPrctlArg { #[cfg(target_arch = "x86_64")] SetFs(usize), #[cfg(target_arch = "x86_64")] - GetFs(Platform::RawMutPointer), + GetFs(UserPtrMut), CETStatus, CETDisable, CETLock, - - #[doc(hidden)] - #[allow(non_camel_case_types)] - __Phantom(core::marker::PhantomData), } /// Reads the FS segment base address @@ -1698,25 +1680,25 @@ bitflags::bitflags! { #[non_exhaustive] #[derive(Debug)] -pub enum FutexArgs { +pub enum FutexArgs { Wait { - addr: Platform::RawMutPointer, + addr: UserPtrMut, flags: FutexFlags, val: u32, /// Note: for FUTEX_WAIT, timeout is interpreted as a relative /// value. This differs from other futex operations, where /// timeout is interpreted as an absolute value. - timeout: TimeParam, + timeout: TimeParam, }, WaitBitset { - addr: Platform::RawMutPointer, + addr: UserPtrMut, flags: FutexFlags, val: u32, - timeout: TimeParam, + timeout: TimeParam, bitmask: u32, }, Wake { - addr: Platform::RawMutPointer, + addr: UserPtrMut, flags: FutexFlags, count: u32, }, @@ -1778,9 +1760,9 @@ pub enum PrctlOption { #[non_exhaustive] #[derive(Debug)] -pub enum PrctlArg { - SetName(Platform::RawConstPointer), - GetName(Platform::RawMutPointer), +pub enum PrctlArg { + SetName(UserPtr), + GetName(UserPtrMut), CapBSetRead(usize), } @@ -1855,16 +1837,16 @@ bitflags::bitflags! { /// Packaged sigset pointer with its size, used by `pselect6` syscall. #[derive(Clone, Copy, FromBytes)] #[repr(C)] -pub struct SigSetPack { - pub sigset: Platform::RawConstPointer, +pub struct SigSetPack { + pub sigset: UserPtr, pub size: usize, } -#[derive(Debug, FromBytes, IntoBytes)] +#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)] #[repr(C, packed)] -pub struct UserMsgHdr { +pub struct UserMsgHdr { /// ptr to socket address structure - pub msg_name: Platform::RawMutPointer, + pub msg_name: UserPtrMut, /// size of socket address structure pub msg_namelen: u32, /// Explicit padding to match the 4-byte gap that Linux's naturally-aligned @@ -1872,11 +1854,11 @@ pub struct UserMsgHdr { #[cfg(target_pointer_width = "64")] _pad: u32, /// ptr to an array of `iovec` structures - pub msg_iov: Platform::RawConstPointer>>, + pub msg_iov: UserPtr, /// number of elements in msg_iov pub msg_iovlen: usize, /// ptr to ancillary data - pub msg_control: Platform::RawConstPointer, + pub msg_control: UserPtr, /// number of bytes of ancillary data pub msg_controllen: usize, /// flags on received message @@ -1887,35 +1869,19 @@ pub struct UserMsgHdr { _pad2: u32, } -impl Clone for UserMsgHdr { - fn clone(&self) -> Self { - *self - } -} - -impl Copy for UserMsgHdr {} - /// Linux's `struct mmsghdr`: a `msghdr` paired with the number of bytes /// transmitted, used by `sendmmsg`/`recvmmsg`. -#[derive(Debug, FromBytes, IntoBytes)] +#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)] #[repr(C, packed)] -pub struct UserMmsgHdr { +pub struct UserMmsgHdr { /// the per-message `msghdr` - pub msg_hdr: UserMsgHdr, + pub msg_hdr: UserMsgHdr, /// bytes transmitted for this entry, written back by the kernel pub msg_len: u32, #[cfg(target_pointer_width = "64")] _pad: u32, } -impl Clone for UserMmsgHdr { - fn clone(&self) -> Self { - *self - } -} - -impl Copy for UserMmsgHdr {} - #[repr(i32)] #[derive(Debug, IntEnum)] pub enum SocketcallType { @@ -1969,7 +1935,7 @@ impl ShutdownHow { /// Request to syscall handler #[non_exhaustive] #[derive(Debug)] -pub enum SyscallRequest { +pub enum SyscallRequest { Exit { status: i32, }, @@ -1978,12 +1944,12 @@ pub enum SyscallRequest { }, Read { fd: i32, - buf: Platform::RawMutPointer, + buf: UserPtrMut, count: usize, }, Write { fd: i32, - buf: Platform::RawConstPointer, + buf: UserPtr, count: usize, }, Lseek { @@ -1995,24 +1961,24 @@ pub enum SyscallRequest { fd: i32, }, Stat { - pathname: Platform::RawConstPointer, - buf: Platform::RawMutPointer, + pathname: UserPtr, + buf: UserPtrMut, }, Fstat { fd: i32, - buf: Platform::RawMutPointer, + buf: UserPtrMut, }, Lstat { - pathname: Platform::RawConstPointer, - buf: Platform::RawMutPointer, + pathname: UserPtr, + buf: UserPtrMut, }, Mkdirat { dirfd: i32, - pathname: Platform::RawConstPointer, + pathname: UserPtr, mode: u32, }, Chdir { - pathname: Platform::RawConstPointer, + pathname: UserPtr, }, Mmap { addr: usize, @@ -2023,34 +1989,34 @@ pub enum SyscallRequest { offset: usize, }, Mprotect { - addr: Platform::RawMutPointer, + addr: UserPtrMut, length: usize, prot: ProtFlags, }, Munmap { - addr: Platform::RawMutPointer, + addr: UserPtrMut, length: usize, }, Mremap { - old_addr: Platform::RawMutPointer, + old_addr: UserPtrMut, old_size: usize, new_size: usize, flags: MRemapFlags, new_addr: usize, }, Brk { - addr: Platform::RawMutPointer, + addr: UserPtrMut, }, RtSigprocmask { how: signal::SigmaskHow, - set: Option>, - oldset: Option>, + set: Option>, + oldset: Option>, sigsetsize: usize, }, RtSigaction { signum: signal::Signal, - act: Option>, - oldact: Option>, + act: Option>, + oldact: Option>, sigsetsize: usize, }, RtSigreturn, @@ -2068,63 +2034,63 @@ pub enum SyscallRequest { sig: i32, }, Sigaltstack { - ss: Option>, - old_ss: Option>, + ss: Option>, + old_ss: Option>, }, Ioctl { fd: i32, - arg: IoctlArg, + arg: IoctlArg, }, Pread64 { fd: i32, - buf: Platform::RawMutPointer, + buf: UserPtrMut, count: usize, offset: i64, }, Pwrite64 { fd: i32, - buf: Platform::RawConstPointer, + buf: UserPtr, count: usize, offset: i64, }, Sendfile { out_fd: i32, in_fd: i32, - offset: Option>, + offset: Option>, count: usize, }, Readv { fd: i32, - iovec: Platform::RawConstPointer>>, + iovec: UserPtr, iovcnt: usize, }, Writev { fd: i32, - iovec: Platform::RawConstPointer>>, + iovec: UserPtr, iovcnt: usize, }, Preadv { fd: i32, - iovec: Platform::RawConstPointer>>, + iovec: UserPtr, iovcnt: usize, pos_l: usize, pos_h: usize, }, Pwritev { fd: i32, - iovec: Platform::RawConstPointer>>, + iovec: UserPtr, iovcnt: usize, pos_l: usize, pos_h: usize, }, Faccessat { dirfd: i32, - pathname: Platform::RawConstPointer, + pathname: UserPtr, mode: AccessFlags, flags: AtFlags, }, Madvise { - addr: Platform::RawMutPointer, + addr: UserPtrMut, length: usize, behavior: MadviseBehavior, }, @@ -2142,57 +2108,57 @@ pub enum SyscallRequest { domain: u32, type_and_flags: u32, protocol: u8, - sockvec: Platform::RawMutPointer, + sockvec: UserPtrMut, }, Connect { sockfd: i32, - sockaddr: Platform::RawConstPointer, + sockaddr: UserPtr, addrlen: usize, }, Accept { sockfd: i32, - addr: Option>, - addrlen: Option>, + addr: Option>, + addrlen: Option>, flags: SockFlags, }, Sendto { sockfd: i32, - buf: Platform::RawConstPointer, + buf: UserPtr, len: usize, flags: SendFlags, - addr: Option>, + addr: Option>, addrlen: u32, }, Sendmsg { sockfd: i32, - msg: Platform::RawConstPointer>, + msg: UserPtr, flags: SendFlags, }, Sendmmsg { sockfd: i32, - msgvec: Platform::RawMutPointer>, + msgvec: UserPtrMut, vlen: u32, flags: SendFlags, }, Recvfrom { sockfd: i32, - buf: Platform::RawMutPointer, + buf: UserPtrMut, len: usize, flags: ReceiveFlags, - addr: Option>, - addrlen: Platform::RawMutPointer, + addr: Option>, + addrlen: UserPtrMut, }, Recvmsg { sockfd: i32, - msg: Platform::RawMutPointer>, + msg: UserPtrMut, flags: ReceiveFlags, }, Recvmmsg { sockfd: i32, - msgvec: Platform::RawMutPointer>, + msgvec: UserPtrMut, vlen: u32, flags: ReceiveFlags, - timeout: TimeParam, + timeout: TimeParam, }, Shutdown { sockfd: i32, @@ -2200,7 +2166,7 @@ pub enum SyscallRequest { }, Bind { sockfd: i32, - sockaddr: Platform::RawConstPointer, + sockaddr: UserPtr, addrlen: usize, }, Listen { @@ -2211,49 +2177,49 @@ pub enum SyscallRequest { sockfd: i32, level: u32, optname: u32, - optval: Platform::RawConstPointer, + optval: UserPtr, optlen: usize, }, Getsockopt { sockfd: i32, level: u32, optname: u32, - optval: Platform::RawMutPointer, - optlen: Platform::RawMutPointer, + optval: UserPtrMut, + optlen: UserPtrMut, }, Getsockname { sockfd: i32, - addr: Platform::RawMutPointer, - addrlen: Platform::RawMutPointer, + addr: UserPtrMut, + addrlen: UserPtrMut, }, Getpeername { sockfd: i32, - addr: Platform::RawMutPointer, - addrlen: Platform::RawMutPointer, + addr: UserPtrMut, + addrlen: UserPtrMut, }, Uname { - buf: Platform::RawMutPointer, + buf: UserPtrMut, }, Fcntl { fd: i32, - arg: FcntlArg, + arg: FcntlArg, }, Getcwd { - buf: Platform::RawMutPointer, + buf: UserPtrMut, size: usize, }, EpollCtl { epfd: i32, op: EpollOp, fd: i32, - event: Platform::RawConstPointer, + event: UserPtr, }, EpollPwait { epfd: i32, - events: Platform::RawMutPointer, + events: UserPtrMut, maxevents: u32, timeout: i32, - sigmask: Option>, + sigmask: Option>, sigsetsize: usize, }, EpollCreate { @@ -2261,37 +2227,37 @@ pub enum SyscallRequest { flags: EpollCreateFlags, }, Ppoll { - fds: Platform::RawMutPointer, + fds: UserPtrMut, nfds: usize, - timeout: TimeParam, - sigmask: Option>, + timeout: TimeParam, + sigmask: Option>, sigsetsize: usize, }, Pselect { nfds: u32, - readfds: Option>, - writefds: Option>, - exceptfds: Option>, - timeout: TimeParam, - sigsetpack: Option>>, + readfds: Option>, + writefds: Option>, + exceptfds: Option>, + timeout: TimeParam, + sigsetpack: Option>, }, ArchPrctl { - arg: ArchPrctlArg, + arg: ArchPrctlArg, }, Readlink { - pathname: Platform::RawConstPointer, - buf: Platform::RawMutPointer, + pathname: UserPtr, + buf: UserPtrMut, bufsiz: usize, }, Readlinkat { dirfd: i32, - pathname: Platform::RawConstPointer, - buf: Platform::RawMutPointer, + pathname: UserPtr, + buf: UserPtrMut, bufsiz: usize, }, Openat { dirfd: i32, - pathname: Platform::RawConstPointer, + pathname: UserPtr, flags: litebox::fs::OFlags, mode: litebox::fs::Mode, }, @@ -2301,19 +2267,19 @@ pub enum SyscallRequest { }, Mknodat { dirfd: i32, - pathname: Platform::RawConstPointer, + pathname: UserPtr, mode_and_type: u32, dev: u32, }, Unlinkat { dirfd: i32, - pathname: Platform::RawConstPointer, + pathname: UserPtr, flags: AtFlags, }, Newfstatat { dirfd: i32, - pathname: Platform::RawConstPointer, - buf: Platform::RawMutPointer, + pathname: UserPtr, + buf: UserPtrMut, flags: AtFlags, }, Eventfd2 { @@ -2321,48 +2287,48 @@ pub enum SyscallRequest { flags: EfdFlags, }, Pipe2 { - pipefd: Platform::RawMutPointer, + pipefd: UserPtrMut, flags: litebox::fs::OFlags, }, Clone { args: CloneArgs, }, Clone3 { - args: Platform::RawConstPointer, + args: UserPtr, }, /// Manipulate thread-local storage information. /// Returns `ENOSYS` on x86_64. SetThreadArea { - user_desc: Platform::RawMutPointer, + user_desc: UserPtrMut, }, ClockGettime { clockid: i32, - tp: TimeParam, + tp: TimeParam, }, ClockGetres { clockid: i32, - res: TimeParam, + res: TimeParam, }, ClockNanosleep { clockid: i32, flags: TimerFlags, - request: TimeParam, - remain: TimeParam, + request: TimeParam, + remain: TimeParam, }, Gettimeofday { - tv: Option>, - tz: Option>, + tv: Option>, + tz: Option>, }, Time { - tloc: Option>, + tloc: Option>, }, Getrlimit { resource: RlimitResource, - rlim: Platform::RawMutPointer, + rlim: UserPtrMut, }, Setrlimit { resource: RlimitResource, - rlim: Platform::RawConstPointer, + rlim: UserPtr, }, Prlimit { pid: i32, @@ -2370,13 +2336,13 @@ pub enum SyscallRequest { resource: RlimitResource, /// If the new_limit argument is not a None, then the rlimit structure to which it points /// is used to set new values for the soft and hard limits for resource. - new_limit: Option>, + new_limit: Option>, /// If the old_limit argument is not a None, then a successful call to prlimit() places the /// previous soft and hard limits for resource in the rlimit structure pointed to by old_limit. - old_limit: Option>, + old_limit: Option>, }, SetTidAddress { - tidptr: Platform::RawMutPointer, + tidptr: UserPtrMut, }, Gettid, SetRobustList { @@ -2384,11 +2350,11 @@ pub enum SyscallRequest { }, GetRobustList { pid: Option, - head: Platform::RawMutPointer, - len: Platform::RawMutPointer, + head: UserPtrMut, + len: UserPtrMut, }, GetRandom { - buf: Platform::RawMutPointer, + buf: UserPtrMut, count: usize, flags: RngFlags, }, @@ -2399,36 +2365,36 @@ pub enum SyscallRequest { Getgid, Getegid, Sysinfo { - buf: Platform::RawMutPointer, + buf: UserPtrMut, }, CapGet { - header: Platform::RawMutPointer, - data: Option>, + header: UserPtrMut, + data: Option>, }, GetDirent64 { fd: i32, - dirp: Platform::RawMutPointer, + dirp: UserPtrMut, count: usize, }, SchedGetAffinity { pid: Option, len: usize, - mask: Platform::RawMutPointer, + mask: UserPtrMut, }, SchedYield, Futex { - args: FutexArgs, + args: FutexArgs, }, Execve { - pathname: Platform::RawConstPointer, - argv: Platform::RawConstPointer>, - envp: Platform::RawConstPointer>, + pathname: UserPtr, + argv: UserPtr>, + envp: UserPtr>, }, Umask { mask: u32, }, Prctl { - args: PrctlArg, + args: PrctlArg, }, Alarm { seconds: u32, @@ -2436,23 +2402,23 @@ pub enum SyscallRequest { Pause, SetITimer { which: IntervalTimer, - new_value: Option>, - old_value: Option>, + new_value: Option>, + old_value: Option>, }, GetITimer { which: IntervalTimer, - curr_value: Platform::RawMutPointer, + curr_value: UserPtrMut, }, Statx { dirfd: i32, - pathname: Option>, + pathname: Option>, flags: AtFlags, mask: StatxMask, - statxbuf: Platform::RawMutPointer, + statxbuf: UserPtrMut, }, } -impl SyscallRequest { +impl SyscallRequest { /// Take the raw syscall number and arguments, and provide a stronger-typed `SyscallRequest`. /// /// Returns `Ok` if a valid translation exists, if no such translation exists, returns the [`Errno`](errno::Errno) for it. @@ -2990,9 +2956,9 @@ impl SyscallRequest { fn parse_futex( ctx: &PtRegs, - time_param: impl FnOnce(Option>) -> TimeParam, + time_param: impl FnOnce(Option>) -> TimeParam, unsupported_einval: impl Fn(core::fmt::Arguments<'_>) -> errno::Errno, - ) -> Result, errno::Errno> { + ) -> Result { let addr = ctx.sys_req_ptr(0); let op_and_flags: i32 = ctx.sys_req_arg(1); let op = op_and_flags & FutexFlags::FUTEX_CMD_MASK.bits(); @@ -3028,38 +2994,40 @@ impl SyscallRequest { } #[derive(Debug)] -pub enum TimeParam { +pub enum TimeParam { None, Milliseconds(i32), - TimeVal(Platform::RawMutPointer), - Timespec32(Platform::RawMutPointer), - Timespec64(Platform::RawMutPointer), + TimeVal(UserPtrMut), + Timespec32(UserPtrMut), + Timespec64(UserPtrMut), } -impl TimeParam { +impl TimeParam { /// Return a `TimeParam` for a 64-bit timespec pointer. - pub fn timespec64(tp: Option>) -> Self { + pub fn timespec64(tp: Option>) -> Self { tp.map_or(TimeParam::None, TimeParam::Timespec64) } /// Return a `TimeParam` for a 32-bit timespec pointer. - pub fn timespec32(tp: Option>) -> Self { + pub fn timespec32(tp: Option>) -> Self { tp.map_or(TimeParam::None, TimeParam::Timespec32) } /// Return a `TimeParam` for the old timespec pointer type, which is /// architecture dependent. - pub fn timespec_old(tp: Option>) -> Self { + pub fn timespec_old(tp: Option>) -> Self { Self::timespec64(tp) } /// Return a `TimeParam` for a timeval pointer. - pub fn timeval(tp: Option>) -> Self { + pub fn timeval(tp: Option>) -> Self { tp.map_or(TimeParam::None, TimeParam::TimeVal) } /// Convert a generic timeout argument into a `Timeout` enum. - pub fn read(&self) -> Result, errno::Errno> { + pub fn read( + &self, + ) -> Result, errno::Errno> { let v = match *self { TimeParam::None => return Ok(None), TimeParam::Milliseconds(s) => { @@ -3070,15 +3038,15 @@ impl TimeParam { Duration::from_millis(s) } TimeParam::TimeVal(tv) => { - let tv = tv.read_at_offset(0).ok_or(errno::Errno::EFAULT)?; + let tv = tv.read_at_offset::

(0).ok_or(errno::Errno::EFAULT)?; Duration::try_from(tv).map_err(|_| errno::Errno::EINVAL)? } TimeParam::Timespec32(ts) => { - let ts = ts.read_at_offset(0).ok_or(errno::Errno::EFAULT)?; + let ts = ts.read_at_offset::

(0).ok_or(errno::Errno::EFAULT)?; Duration::try_from(ts).map_err(|_| errno::Errno::EINVAL)? } TimeParam::Timespec64(ts) => { - let ts = ts.read_at_offset(0).ok_or(errno::Errno::EFAULT)?; + let ts = ts.read_at_offset::

(0).ok_or(errno::Errno::EFAULT)?; Duration::try_from(ts).map_err(|_| errno::Errno::EINVAL)? } }; @@ -3086,24 +3054,27 @@ impl TimeParam { } /// Write a value to the time parameter. - pub fn write(&self, duration: Duration) -> Result<(), errno::Errno> { + pub fn write( + &self, + duration: Duration, + ) -> Result<(), errno::Errno> { match *self { TimeParam::None | TimeParam::Milliseconds(_) => Ok(()), TimeParam::TimeVal(tv_ptr) => { tv_ptr - .write_at_offset(0, duration.into()) + .write_at_offset::

(0, duration.into()) .ok_or(errno::Errno::EFAULT)?; Ok(()) } TimeParam::Timespec32(ts_ptr) => { ts_ptr - .write_at_offset(0, duration.into()) + .write_at_offset::

(0, duration.into()) .ok_or(errno::Errno::EFAULT)?; Ok(()) } TimeParam::Timespec64(ts_ptr) => { ts_ptr - .write_at_offset(0, duration.into()) + .write_at_offset::

(0, duration.into()) .ok_or(errno::Errno::EFAULT)?; Ok(()) } @@ -3441,17 +3412,31 @@ reinterpret_truncated_from_usize_for! { pub trait ReinterpretUsizeAsPtr: Sized { fn reinterpret_usize_as_ptr(v: usize) -> Self; } -impl> ReinterpretUsizeAsPtr> - for P -{ +impl ReinterpretUsizeAsPtr> for UserPtr { + fn reinterpret_usize_as_ptr(v: usize) -> Self { + UserPtr::from_usize(v) + } +} +impl ReinterpretUsizeAsPtr> for UserPtrMut { + fn reinterpret_usize_as_ptr(v: usize) -> Self { + UserPtrMut::from_usize(v) + } +} +impl ReinterpretUsizeAsPtr> for Option> { fn reinterpret_usize_as_ptr(v: usize) -> Self { - P::from_usize(v) + if v == 0 { + None + } else { + Some(UserPtr::from_usize(v)) + } } } -impl> - ReinterpretUsizeAsPtr> for Option

-{ +impl ReinterpretUsizeAsPtr> for Option> { fn reinterpret_usize_as_ptr(v: usize) -> Self { - if v == 0 { None } else { Some(P::from_usize(v)) } + if v == 0 { + None + } else { + Some(UserPtrMut::from_usize(v)) + } } } diff --git a/litebox_common_linux/src/mm.rs b/litebox_common_linux/src/mm.rs index 0c66c4016..9fe3c332d 100644 --- a/litebox_common_linux/src/mm.rs +++ b/litebox_common_linux/src/mm.rs @@ -7,10 +7,10 @@ use litebox::{ mm::linux::{ CreatePagesFlags, MappingError, NonZeroAddress, NonZeroPageSize, PAGE_SIZE, VmemUnmapError, }, - platform::{RawConstPointer, page_mgmt::DeallocationError}, + platform::page_mgmt::DeallocationError, }; -use crate::{MRemapFlags, MapFlags, ProtFlags, errno::Errno}; +use crate::{MRemapFlags, MapFlags, ProtFlags, UserPtrMut, errno::Errno}; const PAGE_MASK: usize = !(PAGE_SIZE - 1); @@ -25,8 +25,9 @@ pub fn do_mmap< prot: ProtFlags, flags: MapFlags, ensure_space_after: bool, - op: impl FnOnce(Platform::RawMutPointer) -> Result, -) -> Result, litebox::mm::linux::MappingError> { + op: impl FnOnce(UserPtrMut) -> Result, +) -> Result, litebox::mm::linux::MappingError> { + let op = |p: Platform::RawMutPointer| op(UserPtrMut::from_platform_ptr::(p)); let flags = { let mut create_flags = CreatePagesFlags::empty(); // MAP_FIXED_NOREPLACE implies MAP_FIXED behavior (exact address, not a hint) @@ -82,6 +83,7 @@ pub fn do_mmap< } } } + .map(UserPtrMut::from_platform_ptr::) } /// Handle syscall `munmap` @@ -91,7 +93,7 @@ pub fn sys_munmap< + litebox::platform::PageManagementProvider<{ litebox::mm::linux::PAGE_SIZE }>, >( pm: &litebox::mm::PageManager, - addr: Platform::RawMutPointer, + addr: UserPtrMut, len: usize, ) -> Result<(), Errno> { if addr.as_usize() & !PAGE_MASK != 0 { @@ -107,7 +109,7 @@ pub fn sys_munmap< return Err(Errno::EINVAL); } - match unsafe { pm.remove_pages(addr, aligned_len) } { + match unsafe { pm.remove_pages(addr.to_platform_ptr::(), aligned_len) } { Err(VmemUnmapError::UnAligned) => Err(Errno::EINVAL), Err(VmemUnmapError::UnmapError(e)) => match e { DeallocationError::Unaligned => Err(Errno::EINVAL), @@ -126,7 +128,7 @@ pub fn sys_mprotect< + litebox::platform::PageManagementProvider<{ litebox::mm::linux::PAGE_SIZE }>, >( pm: &litebox::mm::PageManager, - addr: Platform::RawMutPointer, + addr: UserPtrMut, len: usize, prot: ProtFlags, ) -> Result<(), Errno> { @@ -137,6 +139,7 @@ pub fn sys_mprotect< return Ok(()); } + let addr = addr.to_platform_ptr::(); match prot { ProtFlags::PROT_READ_EXEC => unsafe { pm.make_pages_executable(addr, len) }, ProtFlags::PROT_READ_WRITE => unsafe { pm.make_pages_writable(addr, len) }, @@ -160,12 +163,12 @@ pub fn sys_mremap< + litebox::platform::PageManagementProvider<{ litebox::mm::linux::PAGE_SIZE }>, >( pm: &litebox::mm::PageManager, - old_addr: Platform::RawMutPointer, + old_addr: UserPtrMut, old_size: usize, new_size: usize, flags: MRemapFlags, _new_addr: usize, -) -> Result, Errno> { +) -> Result, Errno> { if flags.intersects( (MRemapFlags::MREMAP_FIXED | MRemapFlags::MREMAP_MAYMOVE | MRemapFlags::MREMAP_DONTUNMAP) .complement(), @@ -207,12 +210,13 @@ pub fn sys_mremap< unsafe { pm.remap_pages( - old_addr, + old_addr.to_platform_ptr::(), old_size, new_size, flags.contains(MRemapFlags::MREMAP_MAYMOVE), ) } + .map(UserPtrMut::from_platform_ptr::) .map_err(Errno::from) } @@ -222,7 +226,7 @@ pub fn sys_brk< + litebox::platform::PageManagementProvider<{ litebox::mm::linux::PAGE_SIZE }>, >( pm: &litebox::mm::PageManager, - addr: Platform::RawMutPointer, + addr: UserPtrMut, ) -> Result { unsafe { pm.brk(addr.as_usize()) }.map_err(Errno::from) } @@ -233,7 +237,7 @@ pub fn sys_madvise< + litebox::platform::PageManagementProvider<{ litebox::mm::linux::PAGE_SIZE }>, >( pm: &litebox::mm::PageManager, - addr: Platform::RawMutPointer, + addr: UserPtrMut, len: usize, advice: crate::MadviseBehavior, ) -> Result<(), Errno> { @@ -252,6 +256,7 @@ pub fn sys_madvise< return Err(Errno::EINVAL); }; + let addr = addr.to_platform_ptr::(); match advice { crate::MadviseBehavior::Normal | crate::MadviseBehavior::DontFork diff --git a/litebox_common_linux/src/user_pointers.rs b/litebox_common_linux/src/user_pointers.rs new file mode 100644 index 000000000..1a3f421e9 --- /dev/null +++ b/litebox_common_linux/src/user_pointers.rs @@ -0,0 +1,230 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +//! Address-only user pointer types. +//! +//! These wrap a bare `usize` address and, unlike +//! [`litebox::platform::RawConstPointer`]/[`litebox::platform::RawMutPointer`], +//! carry no [`RawPointerProvider`] (`Platform`) parameter. This keeps `Platform` +//! from being viral across every type that merely *stores* a user pointer value. +//! Memory is accessed by converting back to the platform pointer type via +//! [`UserPtr::to_platform_ptr`]/[`UserPtrMut::to_platform_ptr`] (or the +//! convenience access methods), which take the platform as an explicit witness +//! `P`. + +use litebox::platform::{RawConstPointer, RawMutPointer, RawPointerProvider}; +use zerocopy::{FromBytes, IntoBytes}; + +/// A user-space const pointer represented purely as an address (`usize`). +/// +/// Unlike [`litebox::platform::RawConstPointer`], this type carries no +/// [`RawPointerProvider`] (`Platform`) parameter: it only *stores* the address +/// of a user pointer. Memory is accessed by converting back to the platform +/// pointer type via the [`Self::read_at_offset`]/[`Self::to_owned_slice`] +/// methods, which take the platform as an explicit witness `P`. +/// +/// This keeps `Platform` from being viral across every type that merely holds a +/// user pointer value. +// NOTE: We explicitly write the `T: Sized` bound to document that these need to +// be "thin" pointers; "fat" pointers (i.e., pointers to DSTs) are unsupported. +#[derive(FromBytes, IntoBytes)] +#[repr(transparent)] +pub struct UserPtr { + /// An exposed-provenance address of the pointer. + addr: usize, + /// Note: This keeps user pointers `!Send + !Sync`; see + /// . + _phantom: core::marker::PhantomData<*const T>, +} + +impl UserPtr { + /// Create a pointer from a raw address. + pub fn from_usize(addr: usize) -> Self { + Self { + addr, + _phantom: core::marker::PhantomData, + } + } + + /// Create a pointer from a native `*const T`, exposing its provenance. + pub fn from_ptr(ptr: *const T) -> Self { + Self::from_usize(ptr.expose_provenance()) + } + + /// Get the address of the pointer as a `usize`. + pub fn as_usize(&self) -> usize { + self.addr + } + + /// Whether this pointer's address is null (zero). + pub fn is_null(&self) -> bool { + self.addr == 0 + } + + /// Reinterpret this pointer as pointing to a different type `U`. + pub fn cast(self) -> UserPtr { + UserPtr::from_usize(self.addr) + } +} + +impl Clone for UserPtr { + fn clone(&self) -> Self { + *self + } +} +impl Copy for UserPtr {} +impl core::fmt::Debug for UserPtr { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_tuple("UserPtr").field(&self.addr).finish() + } +} + +impl UserPtr { + /// Convert platform `P`'s const pointer type into an address-only pointer. + pub fn from_platform_ptr(ptr: P::RawConstPointer) -> Self { + Self::from_usize(ptr.as_usize()) + } + + /// Convert this address-only pointer into platform `P`'s const pointer type, + /// through which memory can actually be accessed. + pub fn to_platform_ptr(self) -> P::RawConstPointer { + as RawConstPointer>::from_usize(self.addr) + } + + /// See [`RawConstPointer::read_at_offset`]. + pub fn read_at_offset(self, count: isize) -> Option { + self.to_platform_ptr::

().read_at_offset(count) + } + + /// See [`RawConstPointer::to_owned_slice`]. + pub fn to_owned_slice( + self, + len: usize, + ) -> Option> { + self.to_platform_ptr::

().to_owned_slice(len) + } +} + +impl UserPtr { + /// See [`RawConstPointer::to_cstring`]. + pub fn to_cstring(self) -> Option { + self.to_platform_ptr::

().to_cstring() + } +} + +/// A user-space mutable pointer represented purely as an address (`usize`). +/// +/// The mutable counterpart of [`UserPtr`]. See [`UserPtr`] for the rationale. +// NOTE: We explicitly write the `T: Sized` bound to document that these need to +// be "thin" pointers; "fat" pointers (i.e., pointers to DSTs) are unsupported. +#[derive(FromBytes, IntoBytes)] +#[repr(transparent)] +pub struct UserPtrMut { + /// An exposed-provenance address of the pointer. + addr: usize, + /// Note: This keeps user pointers `!Send + !Sync`; see + /// . + _phantom: core::marker::PhantomData<*mut T>, +} + +impl UserPtrMut { + /// Create a pointer from a raw address. + pub fn from_usize(addr: usize) -> Self { + Self { + addr, + _phantom: core::marker::PhantomData, + } + } + + /// Create a pointer from a native `*mut T`, exposing its provenance. + pub fn from_ptr(ptr: *mut T) -> Self { + Self::from_usize(ptr.expose_provenance()) + } + + /// Get the address of the pointer as a `usize`. + pub fn as_usize(&self) -> usize { + self.addr + } + + /// Whether this pointer's address is null (zero). + pub fn is_null(&self) -> bool { + self.addr == 0 + } + + /// Reinterpret this pointer as pointing to a different type `U`. + pub fn cast(self) -> UserPtrMut { + UserPtrMut::from_usize(self.addr) + } +} + +impl Clone for UserPtrMut { + fn clone(&self) -> Self { + *self + } +} +impl Copy for UserPtrMut {} +impl core::fmt::Debug for UserPtrMut { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_tuple("UserPtrMut").field(&self.addr).finish() + } +} + +impl UserPtrMut { + /// Convert platform `P`'s mutable pointer type into an address-only pointer. + pub fn from_platform_ptr(ptr: P::RawMutPointer) -> Self { + Self::from_usize(ptr.as_usize()) + } + + /// Convert this address-only pointer into platform `P`'s mutable pointer type, + /// through which memory can actually be accessed. + pub fn to_platform_ptr(self) -> P::RawMutPointer { + as RawConstPointer>::from_usize(self.addr) + } + + /// See [`RawConstPointer::read_at_offset`]. + pub fn read_at_offset(self, count: isize) -> Option { + self.to_platform_ptr::

().read_at_offset(count) + } + + /// See [`RawConstPointer::to_owned_slice`]. + pub fn to_owned_slice( + self, + len: usize, + ) -> Option> { + self.to_platform_ptr::

().to_owned_slice(len) + } + + /// See [`RawMutPointer::write_at_offset`]. + #[must_use] + pub fn write_at_offset(self, count: isize, value: T) -> Option<()> { + self.to_platform_ptr::

().write_at_offset(count, value) + } + + /// See [`RawMutPointer::write_slice_at_offset`]. + #[must_use] + pub fn write_slice_at_offset( + self, + count: isize, + values: &[T], + ) -> Option<()> + where + T: Clone, + { + self.to_platform_ptr::

() + .write_slice_at_offset(count, values) + } + + /// See [`RawMutPointer::copy_from_slice`]. + #[must_use] + pub fn copy_from_slice( + self, + start_offset: usize, + buf: &[T], + ) -> Option<()> + where + T: Copy, + { + self.to_platform_ptr::

() + .copy_from_slice(start_offset, buf) + } +} diff --git a/litebox_shim_linux/src/lib.rs b/litebox_shim_linux/src/lib.rs index ebe36c9c7..35e74866a 100644 --- a/litebox_shim_linux/src/lib.rs +++ b/litebox_shim_linux/src/lib.rs @@ -25,12 +25,16 @@ use litebox::{ mm::{PageManager, linux::PAGE_SIZE}, net::Network, pipes::Pipes, - platform::{RawConstPointer as _, RawMutPointer as _, TimeProvider}, + platform::TimeProvider, shim::ContinueOperation, sync::futex::FutexManager, utils::{ReinterpretSignedExt as _, ReinterpretUnsignedExt as _}, }; -use litebox_common_linux::{SyscallRequest, errno::Errno}; +use litebox_common_linux::{ + SyscallRequest, + errno::Errno, + user_pointers::{UserPtr, UserPtrMut}, +}; use litebox_platform_multiplex::Platform; /// On debug builds, logs that the user attempted to use an unsupported feature. @@ -394,10 +398,6 @@ impl syscalls::file::FilesState { } } -// Convenience type aliases -type ConstPtr = ::RawConstPointer; -type MutPtr = ::RawMutPointer; - impl Task { fn close_on_exec(&self) { let files = self.files.borrow(); @@ -484,7 +484,7 @@ impl Task { fn pread_with_user_buf( &self, fd: i32, - buf: MutPtr, + buf: UserPtrMut, count: usize, offset: i64, ) -> Result { @@ -499,7 +499,7 @@ impl Task { ) { Ok(0) => break, // EOF Ok(size) => { - buf.copy_from_slice(read_total, &kernel_buf[..size]) + buf.copy_from_slice::(read_total, &kernel_buf[..size]) .ok_or(Errno::EFAULT)?; read_total += size; } @@ -536,8 +536,7 @@ impl Task { #[cfg(target_arch = "x86_64")] let syscall_number = ctx.orig_rax; - let request = - SyscallRequest::::try_from_raw(syscall_number, ctx, log_unsupported_fmt)?; + let request = SyscallRequest::try_from_raw(syscall_number, ctx, log_unsupported_fmt)?; match request { SyscallRequest::Exit { status } => { @@ -559,7 +558,7 @@ impl Task { if count <= MAX_KERNEL_BUF_SIZE { let mut kernel_buf = vec![0u8; count.min(MAX_KERNEL_BUF_SIZE)]; self.sys_read(fd, &mut kernel_buf, None).and_then(|size| { - buf.copy_from_slice(0, &kernel_buf[..size]) + buf.copy_from_slice::(0, &kernel_buf[..size]) .map(|()| size) .ok_or(Errno::EFAULT) }) @@ -596,7 +595,8 @@ impl Task { }) } } - SyscallRequest::Write { fd, buf, count } => match buf.to_owned_slice(count) { + SyscallRequest::Write { fd, buf, count } => match buf.to_owned_slice::(count) + { Some(buf) => self.sys_write(fd, &buf, None), None => Err(Errno::EFAULT), }, @@ -611,11 +611,13 @@ impl Task { dirfd, pathname, mode, - } => pathname.to_cstring().map_or(Err(Errno::EFAULT), |path| { - syscall!(sys_mkdirat(dirfd, path, mode)) - }), + } => pathname + .to_cstring::() + .map_or(Err(Errno::EFAULT), |path| { + syscall!(sys_mkdirat(dirfd, path, mode)) + }), SyscallRequest::Chdir { pathname } => pathname - .to_cstring() + .to_cstring::() .map_or(Err(Errno::EINVAL), |path| syscall!(sys_chdir(path))), SyscallRequest::RtSigprocmask { how, @@ -642,7 +644,7 @@ impl Task { buf, count, offset, - } => match buf.to_owned_slice(count) { + } => match buf.to_owned_slice::(count) { Some(buf) => self.sys_pwrite64(fd, &buf, offset), None => Err(Errno::EFAULT), }, @@ -697,9 +699,11 @@ impl Task { pathname, mode, flags, - } => pathname.to_cstring().map_or(Err(Errno::EFAULT), |path| { - syscall!(sys_faccessat(dirfd, path, mode, flags)) - }), + } => pathname + .to_cstring::() + .map_or(Err(Errno::EFAULT), |path| { + syscall!(sys_faccessat(dirfd, path, mode, flags)) + }), SyscallRequest::Madvise { addr, length, @@ -801,7 +805,7 @@ impl Task { SyscallRequest::Getcwd { buf, size: count } => { let mut kernel_buf = vec![0u8; count.min(MAX_KERNEL_BUF_SIZE)]; self.sys_getcwd(&mut kernel_buf).and_then(|size| { - buf.copy_from_slice(0, &kernel_buf[..size]) + buf.copy_from_slice::(0, &kernel_buf[..size]) .map(|()| size) .ok_or(Errno::EFAULT) }) @@ -834,14 +838,16 @@ impl Task { pathname, buf, bufsiz, - } => pathname.to_cstring().map_or(Err(Errno::EFAULT), |path| { - let mut kernel_buf = vec![0u8; bufsiz.min(MAX_KERNEL_BUF_SIZE)]; - self.sys_readlink(path, &mut kernel_buf).and_then(|size| { - buf.copy_from_slice(0, &kernel_buf[..size]) - .map(|()| size) - .ok_or(Errno::EFAULT) - }) - }), + } => pathname + .to_cstring::() + .map_or(Err(Errno::EFAULT), |path| { + let mut kernel_buf = vec![0u8; bufsiz.min(MAX_KERNEL_BUF_SIZE)]; + self.sys_readlink(path, &mut kernel_buf).and_then(|size| { + buf.copy_from_slice::(0, &kernel_buf[..size]) + .map(|()| size) + .ok_or(Errno::EFAULT) + }) + }), SyscallRequest::Ppoll { fds, nfds, @@ -862,15 +868,17 @@ impl Task { pathname, buf, bufsiz, - } => pathname.to_cstring().map_or(Err(Errno::EFAULT), |path| { - let mut kernel_buf = vec![0u8; bufsiz.min(MAX_KERNEL_BUF_SIZE)]; - self.sys_readlinkat(dirfd, path, &mut kernel_buf) - .and_then(|size| { - buf.copy_from_slice(0, &kernel_buf[..size]) - .map(|()| size) - .ok_or(Errno::EFAULT) - }) - }), + } => pathname + .to_cstring::() + .map_or(Err(Errno::EFAULT), |path| { + let mut kernel_buf = vec![0u8; bufsiz.min(MAX_KERNEL_BUF_SIZE)]; + self.sys_readlinkat(dirfd, path, &mut kernel_buf) + .and_then(|size| { + buf.copy_from_slice::(0, &kernel_buf[..size]) + .map(|()| size) + .ok_or(Errno::EFAULT) + }) + }), SyscallRequest::Gettimeofday { tv, tz } => syscall!(sys_gettimeofday(tv, tz)), SyscallRequest::ClockGettime { clockid, tp } => { litebox_common_linux::ClockId::try_from(clockid) @@ -909,45 +917,55 @@ impl Task { pathname, flags, mode, - } => pathname.to_cstring().map_or(Err(Errno::EFAULT), |path| { - syscall!(sys_openat(dirfd, path, flags, mode)) - }), + } => pathname + .to_cstring::() + .map_or(Err(Errno::EFAULT), |path| { + syscall!(sys_openat(dirfd, path, flags, mode)) + }), SyscallRequest::Ftruncate { fd, length } => syscall!(sys_ftruncate(fd, length)), SyscallRequest::Mknodat { dirfd, pathname, mode_and_type, dev, - } => pathname.to_cstring().map_or(Err(Errno::EFAULT), |path| { - syscall!(sys_mknodat(dirfd, path, mode_and_type, dev)) - }), + } => pathname + .to_cstring::() + .map_or(Err(Errno::EFAULT), |path| { + syscall!(sys_mknodat(dirfd, path, mode_and_type, dev)) + }), SyscallRequest::Unlinkat { dirfd, pathname, flags, - } => pathname.to_cstring().map_or(Err(Errno::EFAULT), |path| { - syscall!(sys_unlinkat(dirfd, path, flags)) - }), + } => pathname + .to_cstring::() + .map_or(Err(Errno::EFAULT), |path| { + syscall!(sys_unlinkat(dirfd, path, flags)) + }), SyscallRequest::Stat { pathname, buf } => { - pathname.to_cstring().map_or(Err(Errno::EFAULT), |path| { - self.sys_stat(path).and_then(|stat| { - buf.write_at_offset(0, stat) - .ok_or(Errno::EFAULT) - .map(|()| 0) + pathname + .to_cstring::() + .map_or(Err(Errno::EFAULT), |path| { + self.sys_stat(path).and_then(|stat| { + buf.write_at_offset::(0, stat) + .ok_or(Errno::EFAULT) + .map(|()| 0) + }) }) - }) } SyscallRequest::Lstat { pathname, buf } => { - pathname.to_cstring().map_or(Err(Errno::EFAULT), |path| { - self.sys_lstat(path).and_then(|stat| { - buf.write_at_offset(0, stat) - .ok_or(Errno::EFAULT) - .map(|()| 0) + pathname + .to_cstring::() + .map_or(Err(Errno::EFAULT), |path| { + self.sys_lstat(path).and_then(|stat| { + buf.write_at_offset::(0, stat) + .ok_or(Errno::EFAULT) + .map(|()| 0) + }) }) - }) } SyscallRequest::Fstat { fd, buf } => self.sys_fstat(fd).and_then(|stat| { - buf.write_at_offset(0, stat) + buf.write_at_offset::(0, stat) .ok_or(Errno::EFAULT) .map(|()| 0) }), @@ -957,13 +975,15 @@ impl Task { pathname, buf, flags, - } => pathname.to_cstring().map_or(Err(Errno::EFAULT), |path| { - self.sys_newfstatat(dirfd, path, flags).and_then(|stat| { - buf.write_at_offset(0, stat) - .ok_or(Errno::EFAULT) - .map(|()| 0) - }) - }), + } => pathname + .to_cstring::() + .map_or(Err(Errno::EFAULT), |path| { + self.sys_newfstatat(dirfd, path, flags).and_then(|stat| { + buf.write_at_offset::(0, stat) + .ok_or(Errno::EFAULT) + .map(|()| 0) + }) + }), SyscallRequest::Statx { dirfd, pathname, @@ -977,12 +997,12 @@ impl Task { Ok(c"".into()), flags | litebox_common_linux::AtFlags::AT_EMPTY_PATH, ), - Some(p) => (p.to_cstring().ok_or(Errno::EFAULT), flags), + Some(p) => (p.to_cstring::().ok_or(Errno::EFAULT), flags), }; path.and_then(|path| { self.sys_statx(dirfd, path, flags, mask).and_then(|sx| { statxbuf - .write_at_offset(0, sx) + .write_at_offset::(0, sx) .ok_or(Errno::EFAULT) .map(|()| 0) }) @@ -993,8 +1013,12 @@ impl Task { } SyscallRequest::Pipe2 { pipefd, flags } => { self.sys_pipe2(flags).and_then(|(read_fd, write_fd)| { - pipefd.write_at_offset(0, read_fd).ok_or(Errno::EFAULT)?; - pipefd.write_at_offset(1, write_fd).ok_or(Errno::EFAULT)?; + pipefd + .write_at_offset::(0, read_fd) + .ok_or(Errno::EFAULT)?; + pipefd + .write_at_offset::(1, write_fd) + .ok_or(Errno::EFAULT)?; Ok(0) }) } @@ -1030,8 +1054,11 @@ impl Task { SyscallRequest::GetRobustList { pid, head, len } => self .sys_get_robust_list(pid, head) .and_then(|()| { - len.write_at_offset(0, size_of::()) - .ok_or(Errno::EFAULT) + len.write_at_offset::( + 0, + size_of::(), + ) + .ok_or(Errno::EFAULT) }) .map(|()| 0), SyscallRequest::GetRandom { buf, count, flags } => { @@ -1045,7 +1072,7 @@ impl Task { SyscallRequest::Getegid => Ok(self.sys_getegid() as usize), SyscallRequest::Sysinfo { buf } => { let sysinfo = self.sys_sysinfo(); - buf.write_at_offset(0, sysinfo) + buf.write_at_offset::(0, sysinfo) .ok_or(Errno::EFAULT) .map(|()| 0) } @@ -1062,7 +1089,7 @@ impl Task { Err(Errno::EINVAL) } else { let raw_bytes = cpuset.as_bytes(); - mask.copy_from_slice(0, raw_bytes) + mask.copy_from_slice::(0, raw_bytes) .map(|()| raw_bytes.len()) .ok_or(Errno::EFAULT) } diff --git a/litebox_shim_linux/src/loader/elf.rs b/litebox_shim_linux/src/loader/elf.rs index fef7fa45a..475cf4c0f 100644 --- a/litebox_shim_linux/src/loader/elf.rs +++ b/litebox_shim_linux/src/loader/elf.rs @@ -7,14 +7,15 @@ use alloc::{ffi::CString, vec::Vec}; use litebox::{ fs::{Mode, OFlags}, mm::linux::{CreatePagesFlags, MappingError, PAGE_SIZE}, - platform::{RawConstPointer as _, SystemInfoProvider as _}, + platform::SystemInfoProvider as _, utils::{ReinterpretSignedExt, TruncateExt}, }; use litebox_common_linux::{MapFlags, errno::Errno, loader::ElfParsedFile}; +use litebox_platform_multiplex::Platform; use thiserror::Error; use crate::{ - MutPtr, + UserPtrMut, loader::auxv::{AuxKey, AuxVec}, }; @@ -116,10 +117,10 @@ impl litebox_common_linux::loader::MapMemory for ElfFile<'_, FS> { align, ); if let Some((addr, size)) = regions.head_unmap { - self.task.sys_munmap(MutPtr::from_usize(addr), size)?; + self.task.sys_munmap(UserPtrMut::from_usize(addr), size)?; } if let Some((addr, size)) = regions.tail_unmap { - self.task.sys_munmap(MutPtr::from_usize(addr), size)?; + self.task.sys_munmap(UserPtrMut::from_usize(addr), size)?; } Ok(regions.aligned_ptr) } @@ -165,7 +166,7 @@ impl litebox_common_linux::loader::MapMemory for ElfFile<'_, FS> { len: usize, prot: &litebox_common_linux::loader::Protection, ) -> Result<(), Self::Error> { - let addr = crate::MutPtr::::from_usize(address); + let addr = UserPtrMut::::from_usize(address); self.task.sys_mprotect(addr, len, prot.flags()) } } @@ -294,8 +295,11 @@ impl<'a, FS: ShimFS> ElfLoader<'a, FS> { .create_stack_pages(None, length, CreatePagesFlags::empty()) .map_err(ElfLoaderError::MappingError)? }; - let mut stack = UserStack::new(sp, super::DEFAULT_STACK_SIZE) - .ok_or(ElfLoaderError::InvalidStackAddr)?; + let mut stack = UserStack::new( + UserPtrMut::from_platform_ptr::(sp), + super::DEFAULT_STACK_SIZE, + ) + .ok_or(ElfLoaderError::InvalidStackAddr)?; stack .init(argv, envp, aux) .ok_or(ElfLoaderError::InvalidStackAddr)?; diff --git a/litebox_shim_linux/src/loader/stack.rs b/litebox_shim_linux/src/loader/stack.rs index ebb65de82..2f81bff18 100644 --- a/litebox_shim_linux/src/loader/stack.rs +++ b/litebox_shim_linux/src/loader/stack.rs @@ -4,13 +4,11 @@ //! This module manages the stack layout for the user process. use alloc::{collections::btree_map::BTreeMap, ffi::CString, vec::Vec}; -use litebox::{ - platform::{RawConstPointer, RawMutPointer}, - utils::ReinterpretSignedExt as _, -}; +use litebox::utils::ReinterpretSignedExt as _; +use litebox_platform_multiplex::Platform; use crate::{ - MutPtr, + UserPtrMut, loader::auxv::{AuxKey, AuxVec}, }; @@ -54,7 +52,7 @@ use crate::{ /// values, rather than 64-bit values) is used for 32-bit processes. pub(super) struct UserStack { /// The top of the stack (base address) - stack_top: MutPtr, + stack_top: UserPtrMut, /// The length of the stack #[expect(dead_code, reason = "should we remove this?")] len: usize, @@ -69,8 +67,8 @@ impl UserStack { /// Create a new stack for the user process. /// /// `stack_top` and `len` must be aligned to [`Self::STACK_ALIGNMENT`] - pub(super) fn new(stack_top: MutPtr, len: usize) -> Option { - if stack_top.as_usize() % Self::STACK_ALIGNMENT != 0 { + pub(super) fn new(stack_top: UserPtrMut, len: usize) -> Option { + if !stack_top.as_usize().is_multiple_of(Self::STACK_ALIGNMENT) { return None; } if !len.is_multiple_of(Self::STACK_ALIGNMENT) { @@ -94,7 +92,8 @@ impl UserStack { fn push_bytes(&mut self, bytes: &[u8]) -> Option<()> { let _end = isize::try_from(self.pos).ok()?; self.pos = self.pos.checked_sub(bytes.len())?; - self.stack_top.copy_from_slice(self.pos, bytes)?; + self.stack_top + .copy_from_slice::(self.pos, bytes)?; Some(()) } @@ -136,10 +135,10 @@ impl UserStack { self.push_usize(0)?; let size = offsets.len().checked_mul(size_of::())?; self.pos = self.pos.checked_sub(size)?; - let ptr: MutPtr = MutPtr::from_usize(self.stack_top.as_usize() + self.pos); + let ptr: UserPtrMut = UserPtrMut::from_usize(self.stack_top.as_usize() + self.pos); for (i, p) in offsets.iter().enumerate() { let addr: usize = self.stack_top.as_usize() + *p; - ptr.write_at_offset(i.reinterpret_as_signed(), addr)?; + ptr.write_at_offset::(i.reinterpret_as_signed(), addr)?; } Some(()) } @@ -168,7 +167,7 @@ impl UserStack { // end markers self.pos = self.pos.checked_sub(size_of::())?; self.stack_top - .write_at_offset(isize::try_from(self.pos).ok()?, 0)?; + .write_at_offset::(isize::try_from(self.pos).ok()?, 0)?; let envp = self.push_cstrings(&env)?; let argvp = self.push_cstrings(&argv)?; diff --git a/litebox_shim_linux/src/syscalls/file.rs b/litebox_shim_linux/src/syscalls/file.rs index 9d6bb5ce4..5200a6d44 100644 --- a/litebox_shim_linux/src/syscalls/file.rs +++ b/litebox_shim_linux/src/syscalls/file.rs @@ -14,7 +14,7 @@ use litebox::{ fs::{Mode, OFlags, SeekWhence}, mm::linux::PAGE_SIZE, path, - platform::{RawConstPointer, RawMutPointer, StdioProvider, StdioStream}, + platform::{StdioProvider, StdioStream}, utils::{ReinterpretSignedExt as _, ReinterpretUnsignedExt as _, TruncateExt as _}, }; use litebox_common_linux::{ @@ -25,7 +25,7 @@ use litebox_common_linux::{ use litebox_platform_multiplex::Platform; use thiserror::Error; -use crate::{ConstPtr, GlobalState, MutPtr, ShimFS, Task, syscalls::signal}; +use crate::{GlobalState, ShimFS, Task, UserPtr, UserPtrMut, syscalls::signal}; use core::sync::atomic::{AtomicUsize, Ordering}; #[derive(Clone, Copy)] @@ -565,7 +565,7 @@ impl Task { &self, out_fd: i32, in_fd: i32, - offset_ptr: Option>, + offset_ptr: Option>, count: usize, ) -> Result { let Ok(in_raw_fd) = u32::try_from(in_fd).and_then(usize::try_from) else { @@ -576,7 +576,7 @@ impl Task { let mut cur_off = offset_ptr .map(|p| { - let off = p.read_at_offset(0).ok_or(Errno::EFAULT)?; + let off = p.read_at_offset::(0).ok_or(Errno::EFAULT)?; if off < 0 { return Err(Errno::EINVAL); } @@ -647,7 +647,7 @@ impl Task { if let (Some(p), Some(off)) = (offset_ptr, cur_off) { let off = i64::try_from(off).map_err(|_| Errno::EOVERFLOW)?; - p.write_at_offset(0, off).ok_or(Errno::EFAULT)?; + p.write_at_offset::(0, off).ok_or(Errno::EFAULT)?; } Ok(total) @@ -858,14 +858,16 @@ impl Task { pub(crate) fn sys_preadv( &self, fd: i32, - iovec: ConstPtr>>, + iovec: UserPtr, iovcnt: usize, offset: i64, ) -> Result { let base_offset = usize::try_from(offset).map_err(|_| Errno::EINVAL)?; self.check_raw_fd_exists(fd)?; check_iovcnt(iovcnt)?; - let iovs: &[IoReadVec>] = &iovec.to_owned_slice(iovcnt).ok_or(Errno::EFAULT)?; + let iovs: &[IoReadVec] = &iovec + .to_owned_slice::(iovcnt) + .ok_or(Errno::EFAULT)?; let mut kernel_buffer = vec![0u8; PAGE_SIZE]; read_from_iovec(iovs, &mut kernel_buffer, |buf, total| { let cur_offset = base_offset.checked_add(total).ok_or(Errno::EOVERFLOW)?; @@ -877,15 +879,16 @@ impl Task { pub(crate) fn sys_pwritev( &self, fd: i32, - iovec: ConstPtr>>, + iovec: UserPtr, iovcnt: usize, offset: i64, ) -> Result { let base_offset = usize::try_from(offset).map_err(|_| Errno::EINVAL)?; self.check_raw_fd_exists(fd)?; check_iovcnt(iovcnt)?; - let iovs: &[IoWriteVec>] = - &iovec.to_owned_slice(iovcnt).ok_or(Errno::EFAULT)?; + let iovs: &[IoWriteVec] = &iovec + .to_owned_slice::(iovcnt) + .ok_or(Errno::EFAULT)?; // TODO: Linux ignores pwritev's offset for O_APPEND files; see the O_APPEND bug documented in pwrite(2). write_to_iovec(iovs, |buf, total| { let cur_offset = base_offset.checked_add(total).ok_or(Errno::EOVERFLOW)?; @@ -897,12 +900,14 @@ impl Task { pub(crate) fn sys_readv( &self, fd: i32, - iovec: ConstPtr>>, + iovec: UserPtr, iovcnt: usize, ) -> Result { self.check_raw_fd_exists(fd)?; check_iovcnt(iovcnt)?; - let iovs: &[IoReadVec>] = &iovec.to_owned_slice(iovcnt).ok_or(Errno::EFAULT)?; + let iovs: &[IoReadVec] = &iovec + .to_owned_slice::(iovcnt) + .ok_or(Errno::EFAULT)?; let mut kernel_buffer = vec![0u8; PAGE_SIZE]; // TODO: The data transfers performed by readv() and writev() are atomic: the data // written by writev() is written as a single block that is not intermingled with @@ -955,13 +960,12 @@ fn check_iov_lens(iov_lens: impl IntoIterator) -> Result<(), Errno } /// Drain reads into a sequence of user iovecs. -fn read_from_iovec( - iovs: &[IoReadVec

], +fn read_from_iovec( + iovs: &[IoReadVec], kernel_buffer: &mut [u8], mut read_fn: F, ) -> Result where - P: RawMutPointer, F: FnMut(&mut [u8], usize) -> Result, { check_iov_lens(iovs.iter().map(|iov| iov.iov_len))?; @@ -983,7 +987,7 @@ where Err(e) => return bail(total_read, e), }; if iov_base - .copy_from_slice(iov_filled, &kernel_buffer[..size]) + .copy_from_slice::(iov_filled, &kernel_buffer[..size]) .is_none() { return bail(total_read, Errno::EFAULT); @@ -1003,9 +1007,8 @@ where /// /// `write_fn` receives the contents of each iovec along with the total number of /// bytes already written from earlier iovecs. -pub(super) fn write_to_iovec(iovs: &[IoWriteVec

], mut write_fn: F) -> Result +pub(super) fn write_to_iovec(iovs: &[IoWriteVec], mut write_fn: F) -> Result where - P: RawConstPointer, F: FnMut(&[u8], usize) -> Result, { check_iov_lens(iovs.iter().map(|iov| iov.iov_len))?; @@ -1029,7 +1032,8 @@ where let to_write = (iov_len - iov_written).min(kernel_buffer.len()); let base_offset = isize::try_from(iov_written).unwrap(); for (byte_offset, byte) in (0_isize..).zip(kernel_buffer[..to_write].iter_mut()) { - let Some(value) = iov_base.read_at_offset(base_offset + byte_offset) else { + let Some(value) = iov_base.read_at_offset::(base_offset + byte_offset) + else { return bail(total_written, Errno::EFAULT); }; *byte = value; @@ -1054,13 +1058,14 @@ impl Task { pub(crate) fn sys_writev( &self, fd: i32, - iovec: ConstPtr>>, + iovec: UserPtr, iovcnt: usize, ) -> Result { self.check_raw_fd_exists(fd)?; check_iovcnt(iovcnt)?; - let iovs: &[IoWriteVec>] = - &iovec.to_owned_slice(iovcnt).ok_or(Errno::EFAULT)?; + let iovs: &[IoWriteVec] = &iovec + .to_owned_slice::(iovcnt) + .ok_or(Errno::EFAULT)?; // TODO: The data transfers performed by readv() and writev() are atomic: the data // written by writev() is written as a single block that is not intermingled with // output from writes in other processes @@ -1453,11 +1458,7 @@ impl Task { self.do_fstatat(dirfd, pathname, flags) } - pub(crate) fn sys_fcntl( - &self, - fd: i32, - arg: FcntlArg, - ) -> Result { + pub(crate) fn sys_fcntl(&self, fd: i32, arg: FcntlArg) -> Result { let Ok(desc) = u32::try_from(fd).and_then(usize::try_from) else { return Err(Errno::EBADF); }; @@ -1593,7 +1594,8 @@ impl Task { .run_on_raw_fd( desc, |_fd| { - let mut flock = lock.read_at_offset(0).ok_or(Errno::EFAULT)?; + let mut flock = + lock.read_at_offset::(0).ok_or(Errno::EFAULT)?; let lock_type = litebox_common_linux::FlockType::try_from(flock.type_) .map_err(|_| Errno::EINVAL)?; if let litebox_common_linux::FlockType::Unlock = lock_type { @@ -1603,7 +1605,8 @@ impl Task { // Note LiteBox does not support multiple processes yet, and one process // can always acquire the lock it owns, so return `Unlock` unconditionally. flock.type_ = litebox_common_linux::FlockType::Unlock as i16; - lock.write_at_offset(0, flock).ok_or(Errno::EFAULT)?; + lock.write_at_offset::(0, flock) + .ok_or(Errno::EFAULT)?; Ok(0) }, |_fd| todo!("net"), @@ -1620,7 +1623,7 @@ impl Task { .run_on_raw_fd( desc, |_fd| { - let flock = lock.read_at_offset(0).ok_or(Errno::EFAULT)?; + let flock = lock.read_at_offset::(0).ok_or(Errno::EFAULT)?; let _ = litebox_common_linux::FlockType::try_from(flock.type_) .map_err(|_| Errno::EINVAL)?; @@ -1763,14 +1766,11 @@ impl Task { Ok(raw_fd.try_into().unwrap()) } - fn stdio_ioctl( - &self, - arg: &IoctlArg, - ) -> Result { + fn stdio_ioctl(&self, arg: &IoctlArg) -> Result { match arg { IoctlArg::TCGETS(termios) => { termios - .write_at_offset( + .write_at_offset::( 0, litebox_common_linux::Termios { c_iflag: 0, @@ -1786,7 +1786,7 @@ impl Task { } IoctlArg::TCSETS(_) => Ok(0), // TODO: implement IoctlArg::TIOCGWINSZ(ws) => { - ws.write_at_offset( + ws.write_at_offset::( 0, litebox_common_linux::Winsize { row: 20, @@ -1817,11 +1817,7 @@ impl Task { } /// Handle syscall `ioctl` - pub fn sys_ioctl( - &self, - fd: i32, - arg: IoctlArg, - ) -> Result { + pub fn sys_ioctl(&self, fd: i32, arg: IoctlArg) -> Result { let Ok(desc) = u32::try_from(fd).and_then(usize::try_from) else { return Err(Errno::EBADF); }; @@ -1829,7 +1825,7 @@ impl Task { let files = self.files.borrow(); match arg { IoctlArg::FIONBIO(arg) => { - let val = arg.read_at_offset(0).ok_or(Errno::EFAULT)?; + let val = arg.read_at_offset::(0).ok_or(Errno::EFAULT)?; self.files .borrow() .run_on_raw_fd( @@ -2018,7 +2014,7 @@ impl Task { epfd: i32, op: litebox_common_linux::EpollOp, fd: i32, - event: ConstPtr, + event: UserPtr, ) -> Result<(), Errno> { let Ok(epfd) = u32::try_from(epfd) else { return Err(Errno::EBADF); @@ -2042,7 +2038,7 @@ impl Task { let event = if op == litebox_common_linux::EpollOp::EpollCtlDel { None } else { - Some(event.read_at_offset(0).ok_or(Errno::EFAULT)?) + Some(event.read_at_offset::(0).ok_or(Errno::EFAULT)?) }; let handle = self .global @@ -2057,10 +2053,10 @@ impl Task { pub fn sys_epoll_pwait( &self, epfd: i32, - events: MutPtr, + events: UserPtrMut, maxevents: u32, timeout: i32, - sigmask: Option>, + sigmask: Option>, _sigsetsize: usize, ) -> Result { if sigmask.is_some() { @@ -2109,7 +2105,7 @@ impl Task { Ok(epoll_events) => { if !epoll_events.is_empty() { events - .copy_from_slice(0, &epoll_events) + .copy_from_slice::(0, &epoll_events) .ok_or(Errno::EFAULT)?; } Ok(epoll_events.len()) @@ -2123,10 +2119,10 @@ impl Task { /// Handle syscall `ppoll`. pub fn sys_ppoll( &self, - fds: MutPtr, + fds: UserPtrMut, nfds: usize, - timeout: TimeParam, - sigmask: Option>, + timeout: TimeParam, + sigmask: Option>, sigsetsize: usize, ) -> Result { if sigmask.is_some() { @@ -2136,12 +2132,12 @@ impl Task { } unimplemented!("no sigmask support yet"); } - let timeout = timeout.read()?; + let timeout = timeout.read::()?; let nfds_signed = isize::try_from(nfds).map_err(|_| Errno::EINVAL)?; let mut set = super::epoll::PollSet::with_capacity(nfds); for i in 0..nfds_signed { - let fd = fds.read_at_offset(i).ok_or(Errno::EFAULT)?; + let fd = fds.read_at_offset::(i).ok_or(Errno::EFAULT)?; let events = litebox::event::Events::from_bits_truncate( fd.events.reinterpret_as_unsigned().into(), @@ -2170,14 +2166,14 @@ impl Task { let mut ready_count = 0; for (i, revents) in set.revents().enumerate() { // TODO: This is not great from a provenance perspective. Consider - // adding cast+add methods to ConstPtr/MutPtr. + // adding cast+add methods to UserPtr/UserPtrMut. let fd_addr = fds_base_addr + i * core::mem::size_of::(); - let revents_ptr = crate::MutPtr::::from_usize( + let revents_ptr = UserPtrMut::::from_usize( fd_addr + core::mem::offset_of!(litebox_common_linux::Pollfd, revents), ); let revents: u16 = revents.bits().trunc(); revents_ptr - .write_at_offset(0, revents.reinterpret_as_signed()) + .write_at_offset::(0, revents.reinterpret_as_signed()) .ok_or(Errno::EFAULT)?; if revents != 0 { ready_count += 1; @@ -2263,22 +2259,29 @@ impl Task { pub(crate) fn sys_pselect( &self, nfds: u32, - readfds: Option>, - writefds: Option>, - exceptfds: Option>, - timeout: TimeParam, - sigsetpack: Option>>, + readfds: Option>, + writefds: Option>, + exceptfds: Option>, + timeout: TimeParam, + sigsetpack: Option>, ) -> Result { let sigmask = if let Some(sigsetpack) = sigsetpack { - let sigsetpack = sigsetpack.read_at_offset(0).ok_or(Errno::EFAULT)?; + let sigsetpack = sigsetpack + .read_at_offset::(0) + .ok_or(Errno::EFAULT)?; if sigsetpack.size != core::mem::size_of::() { return Err(Errno::EINVAL); } - Some(sigsetpack.sigset.read_at_offset(0).ok_or(Errno::EFAULT)?) + Some( + sigsetpack + .sigset + .read_at_offset::(0) + .ok_or(Errno::EFAULT)?, + ) } else { None }; - let timeout = timeout.read()?; + let timeout = timeout.read::()?; if nfds >= i32::MAX as u32 || nfds as usize > self @@ -2290,15 +2293,15 @@ impl Task { } let len = (nfds as usize).div_ceil(core::mem::size_of::() * 8); let mut kreadfds = readfds - .map(|fds| fds.to_owned_slice(len).ok_or(Errno::EFAULT)) + .map(|fds| fds.to_owned_slice::(len).ok_or(Errno::EFAULT)) .transpose()? .map(|fds| bitvec::vec::BitVec::from_vec(fds.into_vec())); let mut kwritefds = writefds - .map(|fds| fds.to_owned_slice(len).ok_or(Errno::EFAULT)) + .map(|fds| fds.to_owned_slice::(len).ok_or(Errno::EFAULT)) .transpose()? .map(|fds| bitvec::vec::BitVec::from_vec(fds.into_vec())); let mut kexceptfds = exceptfds - .map(|fds| fds.to_owned_slice(len).ok_or(Errno::EFAULT)) + .map(|fds| fds.to_owned_slice::(len).ok_or(Errno::EFAULT)) .transpose()? .map(|fds| bitvec::vec::BitVec::from_vec(fds.into_vec())); @@ -2320,19 +2323,19 @@ impl Task { if let Some(fds) = kreadfds { readfds .unwrap() - .write_slice_at_offset(0, fds.as_raw_slice()) + .write_slice_at_offset::(0, fds.as_raw_slice()) .ok_or(Errno::EFAULT)?; } if let Some(fds) = kwritefds { writefds .unwrap() - .write_slice_at_offset(0, fds.as_raw_slice()) + .write_slice_at_offset::(0, fds.as_raw_slice()) .ok_or(Errno::EFAULT)?; } if let Some(fds) = kexceptfds { exceptfds .unwrap() - .write_slice_at_offset(0, fds.as_raw_slice()) + .write_slice_at_offset::(0, fds.as_raw_slice()) .ok_or(Errno::EFAULT)?; } @@ -2500,7 +2503,7 @@ impl Task { pub(crate) fn sys_getdirent64( &self, fd: i32, - dirp: MutPtr, + dirp: UserPtrMut, count: usize, ) -> Result { let Ok(fd) = u32::try_from(fd).and_then(usize::try_from) else { @@ -2541,18 +2544,20 @@ impl Task { typ: litebox_common_linux::DirentType::from(entry.file_type.clone()) as u8, __name: [0; 0], }; - let hdr_ptr = crate::MutPtr::from_usize(dirp.as_usize() + nbytes); - hdr_ptr.write_at_offset(0, dirent64).ok_or(Errno::EFAULT)?; - let name_ptr = crate::MutPtr::from_usize( + let hdr_ptr = UserPtrMut::from_usize(dirp.as_usize() + nbytes); + hdr_ptr + .write_at_offset::(0, dirent64) + .ok_or(Errno::EFAULT)?; + let name_ptr = UserPtrMut::from_usize( hdr_ptr.as_usize() + DIRENT_STRUCT_BYTES_WITHOUT_NAME, ); name_ptr - .write_slice_at_offset(0, entry.name.as_bytes()) + .write_slice_at_offset::(0, entry.name.as_bytes()) .ok_or(Errno::EFAULT)?; // set the null terminator and padding let zeros_len = len - (DIRENT_STRUCT_BYTES_WITHOUT_NAME + entry.name.len()); name_ptr - .write_slice_at_offset( + .write_slice_at_offset::( isize::try_from(entry.name.len()).unwrap(), &vec![0; zeros_len], ) @@ -2591,11 +2596,11 @@ mod tests { let second = b"second"; let iovs = [ IoWriteVec { - iov_base: ConstPtr::from_usize(first.as_ptr().expose_provenance()), + iov_base: UserPtr::from_usize(first.as_ptr().expose_provenance()), iov_len: first.len(), }, IoWriteVec { - iov_base: ConstPtr::from_usize(second.as_ptr().expose_provenance()), + iov_base: UserPtr::from_usize(second.as_ptr().expose_provenance()), iov_len: second.len(), }, ]; @@ -2625,11 +2630,11 @@ mod tests { let mut second = [0u8; 4]; let iovs = [ IoReadVec { - iov_base: MutPtr::from_usize(first.as_mut_ptr().expose_provenance()), + iov_base: UserPtrMut::from_usize(first.as_mut_ptr().expose_provenance()), iov_len: first.len(), }, IoReadVec { - iov_base: MutPtr::from_usize(second.as_mut_ptr().expose_provenance()), + iov_base: UserPtrMut::from_usize(second.as_mut_ptr().expose_provenance()), iov_len: second.len(), }, ]; @@ -2659,7 +2664,7 @@ mod tests { fn read_from_iovec_chunks_iov_larger_than_kernel_buffer() { let mut dest = [0u8; 12]; let iovs = [IoReadVec { - iov_base: MutPtr::from_usize(dest.as_mut_ptr().expose_provenance()), + iov_base: UserPtrMut::from_usize(dest.as_mut_ptr().expose_provenance()), iov_len: dest.len(), }]; let mut kernel_buffer = [0u8; 4]; @@ -2685,11 +2690,11 @@ mod tests { let mut second = [0u8; 4]; let iovs = [ IoReadVec { - iov_base: MutPtr::from_usize(first.as_mut_ptr().expose_provenance()), + iov_base: UserPtrMut::from_usize(first.as_mut_ptr().expose_provenance()), iov_len: first.len(), }, IoReadVec { - iov_base: MutPtr::from_usize(second.as_mut_ptr().expose_provenance()), + iov_base: UserPtrMut::from_usize(second.as_mut_ptr().expose_provenance()), iov_len: second.len(), }, ]; diff --git a/litebox_shim_linux/src/syscalls/misc.rs b/litebox_shim_linux/src/syscalls/misc.rs index 27975bdf5..2f8bc8f09 100644 --- a/litebox_shim_linux/src/syscalls/misc.rs +++ b/litebox_shim_linux/src/syscalls/misc.rs @@ -7,16 +7,18 @@ use crate::{ShimFS, Task}; use litebox::{ - platform::{Instant as _, RawConstPointer as _, RawMutPointer as _, TimeProvider as _}, + platform::{Instant as _, TimeProvider as _}, utils::TruncateExt as _, }; use litebox_common_linux::errno::Errno; +use litebox_common_linux::user_pointers::UserPtrMut; +use litebox_platform_multiplex::Platform; impl Task { /// Handle syscall `getrandom`. pub(crate) fn sys_getrandom( &self, - buf: crate::MutPtr, + buf: UserPtrMut, count: usize, _flags: litebox_common_linux::RngFlags, ) -> Result { @@ -29,7 +31,8 @@ impl Task { let len = (count - offset).min(kbuf.len()); let kbuf = &mut kbuf[..len]; <_ as litebox::platform::CrngProvider>::fill_bytes_crng(self.global.platform, kbuf); - buf.copy_from_slice(offset, kbuf).ok_or(Errno::EFAULT)?; + buf.copy_from_slice::(offset, kbuf) + .ok_or(Errno::EFAULT)?; offset += len; // TODO: check for interrupt here and break out. } @@ -69,9 +72,10 @@ impl Task { /// Handle syscall `uname`. pub(crate) fn sys_uname( &self, - buf: crate::MutPtr, + buf: UserPtrMut, ) -> Result<(), Errno> { - buf.write_at_offset(0, SYS_INFO).ok_or(Errno::EFAULT) + buf.write_at_offset::(0, SYS_INFO) + .ok_or(Errno::EFAULT) } /// Handle syscall `sysinfo`. @@ -107,10 +111,10 @@ impl Task { /// Note we don't support capabilities in LiteBox, so this returns empty capabilities. pub(crate) fn sys_capget( &self, - header: crate::MutPtr, - data: Option>, + header: UserPtrMut, + data: Option>, ) -> Result<(), Errno> { - let hdr = header.read_at_offset(0).ok_or(Errno::EFAULT)?; + let hdr = header.read_at_offset::(0).ok_or(Errno::EFAULT)?; match hdr.version { _LINUX_CAPABILITY_VERSION_1 => { if let Some(data_ptr) = data { @@ -119,7 +123,9 @@ impl Task { permitted: 0, inheritable: 0, }; - data_ptr.write_at_offset(0, cap).ok_or(Errno::EFAULT)?; + data_ptr + .write_at_offset::(0, cap) + .ok_or(Errno::EFAULT)?; } Ok(()) } @@ -131,15 +137,17 @@ impl Task { inheritable: 0, }; data_ptr - .write_at_offset(0, cap.clone()) + .write_at_offset::(0, cap.clone()) + .ok_or(Errno::EFAULT)?; + data_ptr + .write_at_offset::(1, cap) .ok_or(Errno::EFAULT)?; - data_ptr.write_at_offset(1, cap).ok_or(Errno::EFAULT)?; } Ok(()) } _ => { header - .write_at_offset( + .write_at_offset::( 0, litebox_common_linux::CapHeader { version: _LINUX_CAPABILITY_VERSION_3, @@ -160,6 +168,7 @@ impl Task { #[cfg(test)] mod tests { use crate::syscalls::tests::init_platform; + use litebox_common_linux::user_pointers::UserPtrMut; use zerocopy::FromZeros as _; #[test] @@ -169,7 +178,7 @@ mod tests { let task = init_platform(None); let mut buf = [0u8; 16]; - let ptr = crate::MutPtr::from_ptr(buf.as_mut_ptr()); + let ptr = UserPtrMut::from_ptr(buf.as_mut_ptr()); let count = task .sys_getrandom(ptr, buf.len() - 1, RngFlags::empty()) .expect("getrandom failed"); @@ -186,7 +195,7 @@ mod tests { let task = init_platform(None); let mut utsname = litebox_common_linux::Utsname::new_zeroed(); - let ptr = crate::MutPtr::from_ptr(&raw mut utsname); + let ptr = UserPtrMut::from_ptr(&raw mut utsname); task.sys_uname(ptr).expect("uname failed"); assert_eq!(utsname.sysname, super::SYS_INFO.sysname); diff --git a/litebox_shim_linux/src/syscalls/mm.rs b/litebox_shim_linux/src/syscalls/mm.rs index c5f67791e..d1cb13ace 100644 --- a/litebox_shim_linux/src/syscalls/mm.rs +++ b/litebox_shim_linux/src/syscalls/mm.rs @@ -8,16 +8,17 @@ use alloc::collections::{BTreeMap, BTreeSet}; use litebox::{ mm::linux::{MappingError, PAGE_SIZE, PageRange}, platform::{ - PageManagementProvider, RawConstPointer, RawMutPointer, SystemInfoProvider, + PageManagementProvider, RawConstPointer, SystemInfoProvider, page_mgmt::{FixedAddressBehavior, MemoryRegionPermissions}, }, }; use litebox_common_linux::{MRemapFlags, MapFlags, ProtFlags, errno::Errno}; -use crate::MutPtr; use crate::ShimFS; use crate::Task; +use crate::UserPtrMut; use litebox::utils::TruncateExt as _; +use litebox_platform_multiplex::Platform; use object::elf::{ET_DYN, FileHeader64, PT_LOAD, ProgramHeader64}; use object::endian::LittleEndian; @@ -82,8 +83,8 @@ impl Task { prot: ProtFlags, flags: MapFlags, ensure_space_after: bool, - op: impl FnOnce(MutPtr) -> Result, - ) -> Result, MappingError> { + op: impl FnOnce(UserPtrMut) -> Result, + ) -> Result, MappingError> { litebox_common_linux::mm::do_mmap( &self.global.pm, suggested_addr, @@ -102,7 +103,7 @@ impl Task { len: usize, prot: ProtFlags, flags: MapFlags, - ) -> Result, MappingError> { + ) -> Result, MappingError> { let op = |_| Ok(0); self.do_mmap(suggested_addr, len, prot, flags, false, op) } @@ -115,7 +116,7 @@ impl Task { flags: MapFlags, fd: i32, offset: usize, - ) -> Result, MappingError> { + ) -> Result, MappingError> { let is_exec = prot.contains(ProtFlags::PROT_EXEC); // Perform the normal mmap first (CoW or memcpy fallback). @@ -172,7 +173,7 @@ impl Task { flags: &MapFlags, fd: i32, offset: usize, - ) -> Option, MappingError>> { + ) -> Option, MappingError>> { if !len.is_multiple_of(PAGE_SIZE) { return None; } @@ -259,7 +260,7 @@ impl Task { ) } .unwrap(); - Some(Ok(ptr)) + Some(Ok(UserPtrMut::from_platform_ptr::(ptr))) } Err(_cow_not_supported) => None, } @@ -275,8 +276,8 @@ impl Task { flags: MapFlags, fd: i32, offset: usize, - ) -> Result, MappingError> { - let op = |ptr: MutPtr| -> Result { + ) -> Result, MappingError> { + let op = |ptr: UserPtrMut| -> Result { // Note a malicious user may unmap ptr while we are reading. // `sys_read` does not handle page faults, so we need to use a // temporary buffer to read the data from fs (without worrying page @@ -297,7 +298,8 @@ impl Task { break; } // ptr is a valid pointer returned by do_mmap. - ptr.copy_from_slice(copied, &buffer[..size]).unwrap(); + ptr.copy_from_slice::(copied, &buffer[..size]) + .unwrap(); copied += size; file_offset += size; } @@ -325,7 +327,7 @@ impl Task { flags: MapFlags, fd: i32, offset: usize, - ) -> Result, Errno> { + ) -> Result, Errno> { // check alignment if !offset.is_multiple_of(PAGE_SIZE) || !addr.is_multiple_of(PAGE_SIZE) || len == 0 { return Err(Errno::EINVAL); @@ -377,7 +379,7 @@ impl Task { /// Handle syscall `munmap` #[inline] - pub(crate) fn sys_munmap(&self, addr: crate::MutPtr, len: usize) -> Result<(), Errno> { + pub(crate) fn sys_munmap(&self, addr: UserPtrMut, len: usize) -> Result<(), Errno> { let result = self.sys_munmap_raw(addr, len); if result.is_ok() { self.clear_file_mappings_for_range(addr.as_usize(), len); @@ -388,7 +390,7 @@ impl Task { /// Raw munmap without clearing file_mappings — used internally by the /// patching logic to avoid deadlocks (the patch path holds elf_patch_cache). #[inline] - fn sys_munmap_raw(&self, addr: crate::MutPtr, len: usize) -> Result<(), Errno> { + fn sys_munmap_raw(&self, addr: UserPtrMut, len: usize) -> Result<(), Errno> { litebox_common_linux::mm::sys_munmap(&self.global.pm, addr, len) } @@ -414,7 +416,7 @@ impl Task { #[inline] pub(crate) fn sys_mprotect( &self, - addr: crate::MutPtr, + addr: UserPtrMut, len: usize, prot: ProtFlags, ) -> Result<(), Errno> { @@ -433,7 +435,7 @@ impl Task { #[inline] fn sys_mprotect_raw( &self, - addr: crate::MutPtr, + addr: UserPtrMut, len: usize, prot: ProtFlags, ) -> Result<(), Errno> { @@ -443,12 +445,12 @@ impl Task { #[inline] pub(crate) fn sys_mremap( &self, - old_addr: crate::MutPtr, + old_addr: UserPtrMut, old_size: usize, new_size: usize, flags: MRemapFlags, new_addr: usize, - ) -> Result, Errno> { + ) -> Result, Errno> { litebox_common_linux::mm::sys_mremap( &self.global.pm, old_addr, @@ -461,7 +463,7 @@ impl Task { /// Handle syscall `brk` #[inline] - pub(crate) fn sys_brk(&self, addr: MutPtr) -> Result { + pub(crate) fn sys_brk(&self, addr: UserPtrMut) -> Result { litebox_common_linux::mm::sys_brk(&self.global.pm, addr) } @@ -469,7 +471,7 @@ impl Task { #[inline] pub(crate) fn sys_madvise( &self, - addr: MutPtr, + addr: UserPtrMut, len: usize, advice: litebox_common_linux::MadviseBehavior, ) -> Result<(), Errno> { @@ -481,12 +483,7 @@ impl Task { /// Check all tracked file mappings for unpatched regions that overlap the /// mprotect range. If found, run the runtime rewriter before the region /// becomes executable. - fn maybe_patch_on_mprotect_exec( - &self, - addr: crate::MutPtr, - len: usize, - syscall_entry: usize, - ) { + fn maybe_patch_on_mprotect_exec(&self, addr: UserPtrMut, len: usize, syscall_entry: usize) { let mprotect_start = addr.as_usize(); let mprotect_end = mprotect_start.saturating_add(len); @@ -535,7 +532,7 @@ impl Task { if patch_len == 0 { continue; } - let mapped_addr = MutPtr::::from_usize(patch_start); + let mapped_addr = UserPtrMut::::from_usize(patch_start); self.maybe_patch_exec_segment(mapped_addr, patch_len, fd, syscall_entry, None); } } @@ -716,7 +713,7 @@ impl Task { /// and the initial mprotect RW is skipped. /// /// Panics on infrastructure failures (mprotect/read/write/disassembly). - fn apply_trap_fallback(&self, mapped_addr: crate::MutPtr, len: usize, already_rw: bool) { + fn apply_trap_fallback(&self, mapped_addr: UserPtrMut, len: usize, already_rw: bool) { if !already_rw { self.sys_mprotect_raw( mapped_addr, @@ -727,7 +724,7 @@ impl Task { } // Read, patch using the rewriter (proper disassembly), write back. - let Some(code_owned) = mapped_addr.to_owned_slice(len) else { + let Some(code_owned) = mapped_addr.to_owned_slice::(len) else { panic!("fatal: failed to read code segment for trap fallback"); }; let mut code_buf = code_owned.into_vec(); @@ -743,7 +740,9 @@ impl Task { ); } assert!( - mapped_addr.copy_from_slice(0, &code_buf).is_some(), + mapped_addr + .copy_from_slice::(0, &code_buf) + .is_some(), "fatal: failed to write trap bytes back to code segment" ); @@ -769,7 +768,7 @@ impl Task { /// trampoline address. fn maybe_patch_exec_segment( &self, - mapped_addr: MutPtr, + mapped_addr: UserPtrMut, len: usize, fd: i32, syscall_entry: usize, @@ -812,14 +811,15 @@ impl Task { }; let actual_addr = alloc_ptr.as_usize(); if actual_addr != tramp_addr { - let _ = self.sys_munmap_raw(MutPtr::::from_usize(actual_addr), tramp_len); + let _ = + self.sys_munmap_raw(UserPtrMut::::from_usize(actual_addr), tramp_len); return false; } // Read trampoline data from the file. let mut tramp_data = alloc::vec![0u8; state.trampoline_file_size]; let file_off = state.trampoline_file_offset.trunc(); - let tramp_ptr = MutPtr::::from_usize(tramp_addr); + let tramp_ptr = UserPtrMut::::from_usize(tramp_addr); match self.sys_read(fd, &mut tramp_data, Some(file_off)) { Ok(n) if n == tramp_data.len() => {} _ => { @@ -834,7 +834,10 @@ impl Task { } // Write to the mapped region. - if tramp_ptr.copy_from_slice(0, &tramp_data).is_none() { + if tramp_ptr + .copy_from_slice::(0, &tramp_data) + .is_none() + { let _ = self.sys_munmap_raw(tramp_ptr, tramp_len); return false; } @@ -902,7 +905,7 @@ impl Task { distance:? = distance; "trampoline too far from code segment, skipping patching" ); - let _ = self.sys_munmap_raw(MutPtr::::from_usize(actual_addr), PAGE_SIZE); + let _ = self.sys_munmap_raw(UserPtrMut::::from_usize(actual_addr), PAGE_SIZE); self.apply_trap_fallback(mapped_addr, len, false); return true; } @@ -910,13 +913,13 @@ impl Task { state.trampoline_addr = actual_addr; // Write the 8-byte syscall entry point at the start. - let entry_ptr = MutPtr::::from_usize(actual_addr); + let entry_ptr = UserPtrMut::::from_usize(actual_addr); if entry_ptr - .copy_from_slice(0, &syscall_entry.to_le_bytes()) + .copy_from_slice::(0, &syscall_entry.to_le_bytes()) .is_none() { litebox_util_log::warn!("failed to write syscall entry point to trampoline"); - let _ = self.sys_munmap_raw(MutPtr::::from_usize(actual_addr), PAGE_SIZE); + let _ = self.sys_munmap_raw(UserPtrMut::::from_usize(actual_addr), PAGE_SIZE); self.apply_trap_fallback(mapped_addr, len, false); return true; } @@ -935,7 +938,7 @@ impl Task { let restore_trampoline_rx = |task: &Self, state: &ElfPatchState| { if state.trampoline_mapped_len > 0 { let _ = task.sys_mprotect_raw( - MutPtr::::from_usize(state.trampoline_addr), + UserPtrMut::::from_usize(state.trampoline_addr), state.trampoline_mapped_len, ProtFlags::PROT_READ | ProtFlags::PROT_EXEC, ); @@ -946,7 +949,7 @@ impl Task { if state.trampoline_mapped_len > 0 && self .sys_mprotect_raw( - MutPtr::::from_usize(state.trampoline_addr), + UserPtrMut::::from_usize(state.trampoline_addr), state.trampoline_mapped_len, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, ) @@ -967,7 +970,7 @@ impl Task { } // Read the mapped code into a buffer, patch it, write back. - let Some(code_owned) = mapped_addr.to_owned_slice(len) else { + let Some(code_owned) = mapped_addr.to_owned_slice::(len) else { let _ = self.sys_mprotect_raw( mapped_addr, len, @@ -1035,8 +1038,11 @@ impl Task { // Write stubs before patching the code so rewritten jumps // never target an uninitialized trampoline. let tramp_write_ptr = - MutPtr::::from_usize(state.trampoline_addr + state.trampoline_cursor); - if tramp_write_ptr.copy_from_slice(0, &stubs).is_none() { + UserPtrMut::::from_usize(state.trampoline_addr + state.trampoline_cursor); + if tramp_write_ptr + .copy_from_slice::(0, &stubs) + .is_none() + { let _ = self.sys_mprotect_raw( mapped_addr, len, @@ -1047,8 +1053,11 @@ impl Task { } // Write patched code back to the mapped region. - if mapped_addr.copy_from_slice(0, &code_buf).is_none() { - let _ = mapped_addr.copy_from_slice(0, &original_code); + if mapped_addr + .copy_from_slice::(0, &code_buf) + .is_none() + { + let _ = mapped_addr.copy_from_slice::(0, &original_code); let _ = self.sys_mprotect_raw( mapped_addr, len, @@ -1064,9 +1073,12 @@ impl Task { // No trampoline stubs were generated, but the rewriter may // have replaced unpatchable syscalls with trap instructions. // Write back the modified code if it changed. - if code_buf != original_code && mapped_addr.copy_from_slice(0, &code_buf).is_none() + if code_buf != original_code + && mapped_addr + .copy_from_slice::(0, &code_buf) + .is_none() { - let _ = mapped_addr.copy_from_slice(0, &original_code); + let _ = mapped_addr.copy_from_slice::(0, &original_code); panic!("fatal: failed to write trap bytes back to code segment"); } // Fall through to restore RX protections below. @@ -1102,7 +1114,10 @@ impl Task { { let tramp_len = state.trampoline_mapped_len; if tramp_len > 0 { - let _ = self.sys_munmap(MutPtr::::from_usize(state.trampoline_addr), tramp_len); + let _ = self.sys_munmap( + UserPtrMut::::from_usize(state.trampoline_addr), + tramp_len, + ); } } } @@ -1112,11 +1127,12 @@ impl Task { mod tests { use litebox::{ fs::{Mode, OFlags}, - platform::{PageManagementProvider, RawConstPointer, RawMutPointer}, + platform::PageManagementProvider, }; use litebox_common_linux::{MRemapFlags, MapFlags, ProtFlags, errno::Errno}; + use litebox_platform_multiplex::Platform; - use crate::syscalls::tests::init_platform; + use crate::{UserPtrMut, syscalls::tests::init_platform}; #[test] fn test_anonymous_mmap() { @@ -1132,8 +1148,9 @@ mod tests { 0, ) .unwrap(); - addr.write_slice_at_offset(0, &[0xff; 0x2000]).unwrap(); - assert_eq!(addr.read_at_offset(0x1000).unwrap(), 0xff,); + addr.write_slice_at_offset::(0, &[0xff; 0x2000]) + .unwrap(); + assert_eq!(addr.read_at_offset::(0x1000).unwrap(), 0xff,); task.sys_munmap(addr, 0x2000).unwrap(); } @@ -1158,7 +1175,9 @@ mod tests { ) .unwrap(); assert_eq!( - addr.to_owned_slice(content.len()).unwrap().as_ref(), + addr.to_owned_slice::(content.len()) + .unwrap() + .as_ref(), content.as_slice(), ); task.sys_munmap(addr, 0x1000).unwrap(); @@ -1397,7 +1416,7 @@ mod tests { // grow the mapping without MREMAP_MAYMOVE should fail as the new region collides with the global allocator let err = task .sys_mremap( - crate::MutPtr::from_usize(addr - 0x1000), + UserPtrMut::from_usize(addr - 0x1000), 0x1000, 0x2000, MRemapFlags::empty(), @@ -1424,13 +1443,14 @@ mod tests { .unwrap(); // Reading should work - let _val: u8 = addr.read_at_offset(0).unwrap(); + let _val: u8 = addr.read_at_offset::(0).unwrap(); // Anonymous shared mappings allow permission changes including write task.sys_mprotect(addr, 0x2000, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE) .unwrap(); - addr.write_slice_at_offset(0, &[0xab; 0x10]).unwrap(); - assert_eq!(addr.read_at_offset(0).unwrap(), 0xab_u8); + addr.write_slice_at_offset::(0, &[0xab; 0x10]) + .unwrap(); + assert_eq!(addr.read_at_offset::(0).unwrap(), 0xab_u8); // mprotect to read-only or read-exec should also succeed task.sys_mprotect(addr, 0x2000, ProtFlags::PROT_READ) @@ -1457,8 +1477,9 @@ mod tests { ) .unwrap(); - addr.write_slice_at_offset(0, &[0xcd; 0x10]).unwrap(); - assert_eq!(addr.read_at_offset(0).unwrap(), 0xcd_u8); + addr.write_slice_at_offset::(0, &[0xcd; 0x10]) + .unwrap(); + assert_eq!(addr.read_at_offset::(0).unwrap(), 0xcd_u8); task.sys_munmap(addr, 0x1000).unwrap(); } @@ -1481,7 +1502,9 @@ mod tests { // Data should match assert_eq!( - addr.to_owned_slice(content.len()).unwrap().as_ref(), + addr.to_owned_slice::(content.len()) + .unwrap() + .as_ref(), content.as_slice(), ); @@ -1510,7 +1533,8 @@ mod tests { ) .unwrap(); - addr.write_slice_at_offset(0, &[0xff; 0x10]).unwrap(); + addr.write_slice_at_offset::(0, &[0xff; 0x10]) + .unwrap(); // Test MADV_NORMAL assert!( @@ -1528,9 +1552,12 @@ mod tests { .is_ok() ); - addr.to_owned_slice(0x10).unwrap().iter().for_each(|&x| { - assert_eq!(x, 0); // Should be zeroed after MADV_DONTNEED - }); + addr.to_owned_slice::(0x10) + .unwrap() + .iter() + .for_each(|&x| { + assert_eq!(x, 0); // Should be zeroed after MADV_DONTNEED + }); task.sys_munmap(addr, 0x2000).unwrap(); } @@ -1541,8 +1568,8 @@ mod tests { fn test_fallible_read() { let _ = init_platform(None); - let ptr = crate::MutPtr::::from_usize(0xdeadbeef); - let result = ptr.read_at_offset(0); + let ptr = UserPtrMut::::from_usize(0xdeadbeef); + let result = ptr.read_at_offset::(0); assert!(result.is_none()); } } diff --git a/litebox_shim_linux/src/syscalls/mod.rs b/litebox_shim_linux/src/syscalls/mod.rs index b5fa1a82f..b79de8814 100644 --- a/litebox_shim_linux/src/syscalls/mod.rs +++ b/litebox_shim_linux/src/syscalls/mod.rs @@ -39,6 +39,7 @@ macro_rules! common_functions_for_file_status { }; } +use crate::{UserPtr, UserPtrMut}; pub(crate) use common_functions_for_file_status; use zerocopy::{FromBytes, Immutable, IntoBytes}; @@ -46,29 +47,29 @@ use zerocopy::{FromBytes, Immutable, IntoBytes}; /// If the buffer size (i.e., provided `len`) is smaller than `size_of::()`, only write up to `len` bytes. fn write_to_user( val: T, - optval: crate::MutPtr, + optval: UserPtrMut, len: u32, ) -> Result { - use litebox::platform::RawMutPointer as _; + use litebox_platform_multiplex::Platform; let length = core::mem::size_of::().min(len as usize); let data = &val.as_bytes()[..length]; optval - .write_slice_at_offset(0, data) + .write_slice_at_offset::(0, data) .ok_or(litebox_common_linux::errno::Errno::EFAULT)?; Ok(length) } /// Helper function to read a value of type T from user memory. /// If the buffer size (i.e., provided `optlen`) is smaller than `size_of::()`, return EINVAL. fn read_from_user( - optval: crate::ConstPtr, + optval: UserPtr, optlen: usize, ) -> Result { - use litebox::platform::RawConstPointer as _; + use litebox_platform_multiplex::Platform; if optlen < size_of::() { return Err(litebox_common_linux::errno::Errno::EINVAL); } - let optval: crate::ConstPtr = crate::ConstPtr::from_usize(optval.as_usize()); + let optval: UserPtr = UserPtr::from_usize(optval.as_usize()); optval - .read_at_offset(0) + .read_at_offset::(0) .ok_or(litebox_common_linux::errno::Errno::EFAULT) } diff --git a/litebox_shim_linux/src/syscalls/net.rs b/litebox_shim_linux/src/syscalls/net.rs index 997ccb632..cc6eca4e6 100644 --- a/litebox_shim_linux/src/syscalls/net.rs +++ b/litebox_shim_linux/src/syscalls/net.rs @@ -23,7 +23,7 @@ use litebox::{ errors::AcceptError, socket_channel::{ChannelReadError, ChannelWriteError, NetworkProxy, SocketState}, }, - platform::{Instant as _, RawConstPointer as _, RawMutPointer as _, TimeProvider as _}, + platform::{Instant as _, TimeProvider as _}, utils::TruncateExt as _, }; use litebox_common_linux::{ @@ -33,12 +33,12 @@ use litebox_common_linux::{ }; use zerocopy::{FromBytes, Immutable, IntoBytes}; -use crate::{ConstPtr, MutPtr, syscalls::signal}; use crate::{GlobalState, ShimFS, Task}; use crate::{ Platform, syscalls::unix::{CSockUnixAddr, UnixSocket, UnixSocketAddr}, }; +use crate::{UserPtr, UserPtrMut, syscalls::signal}; /// Linux's hard cap on the number of iovecs per `*msg`-style call, and on the /// number of entries per `sendmmsg`. See `UIO_MAXIOV` in ``. @@ -275,7 +275,7 @@ impl GlobalState { pub(super) fn setsockopt_common( &self, optname: SocketOptionName, - optval: ConstPtr, + optval: UserPtr, optlen: usize, set_option: F, ) -> Result<(), Errno> @@ -318,7 +318,7 @@ impl GlobalState { &self, fd: &SocketFd, optname: SocketOptionName, - optval: ConstPtr, + optval: UserPtr, optlen: usize, ) -> Result<(), Errno> { match self.setsockopt_common(optname, optval, optlen, |so, value| { @@ -406,7 +406,7 @@ impl GlobalState { TcpOption::CONGESTION => { const TCP_CONGESTION_NAME_MAX: usize = 16; let data = optval - .to_owned_slice(TCP_CONGESTION_NAME_MAX.min(optlen)) + .to_owned_slice::(TCP_CONGESTION_NAME_MAX.min(optlen)) .ok_or(Errno::EFAULT)?; let name = core::str::from_utf8(&data).map_err(|_| Errno::EINVAL)?; self.net.lock().set_tcp_option( @@ -484,7 +484,7 @@ impl GlobalState { pub(super) fn getsockopt_common( &self, optname: SocketOptionName, - optval: MutPtr, + optval: UserPtrMut, len: u32, get_option: F, ) -> Result @@ -518,7 +518,7 @@ impl GlobalState { &self, fd: &SocketFd, optname: SocketOptionName, - optval: MutPtr, + optval: UserPtrMut, len: u32, ) -> Result { match self.getsockopt_common(optname, optval, len, |sopt| { @@ -585,7 +585,7 @@ impl GlobalState { }; let len = name.len().min(len as usize); optval - .write_slice_at_offset(0, &name.as_bytes()[..len]) + .write_slice_at_offset::(0, &name.as_bytes()[..len]) .ok_or(Errno::EFAULT)?; return Ok(len); } @@ -1004,7 +1004,7 @@ impl Task { domain: u32, type_and_flags: u32, protocol: u8, - sockvec: MutPtr, + sockvec: UserPtrMut, ) -> Result<(), Errno> { let (ty, flags) = parse_type_and_flags(type_and_flags)?; let domain = AddressFamily::try_from(domain).map_err(|_| { @@ -1012,8 +1012,12 @@ impl Task { Errno::EINVAL })?; let (sock1, sock2) = self.do_socketpair(domain, ty, flags, protocol)?; - sockvec.write_at_offset(0, sock1).ok_or(Errno::EFAULT)?; - sockvec.write_at_offset(1, sock2).ok_or(Errno::EFAULT)?; + sockvec + .write_at_offset::(0, sock1) + .ok_or(Errno::EFAULT)?; + sockvec + .write_at_offset::(1, sock2) + .ok_or(Errno::EFAULT)?; Ok(()) } fn do_socketpair( @@ -1062,31 +1066,33 @@ impl Task { } } pub(crate) fn read_sockaddr_from_user( - sockaddr: ConstPtr, + sockaddr: UserPtr, addrlen: usize, ) -> Result { if addrlen < 2 { return Err(Errno::EINVAL); } - let ptr: ConstPtr = ConstPtr::from_usize(sockaddr.as_usize()); - let family = ptr.read_at_offset(0).ok_or(Errno::EFAULT)?; + let ptr: UserPtr = UserPtr::from_usize(sockaddr.as_usize()); + let family = ptr.read_at_offset::(0).ok_or(Errno::EFAULT)?; let family = AddressFamily::try_from(u32::from(family)).map_err(|_| Errno::EAFNOSUPPORT)?; match family { AddressFamily::INET => { if addrlen < size_of::() { return Err(Errno::EINVAL); } - let ptr: ConstPtr = ConstPtr::from_usize(sockaddr.as_usize()); + let ptr: UserPtr = UserPtr::from_usize(sockaddr.as_usize()); // Note it reads the first 2 bytes (i.e., sa_family) again, but it is not used. // SocketAddrV4 only needs the port and addr. - let inet_addr = ptr.read_at_offset(0).ok_or(Errno::EFAULT)?; + let inet_addr = ptr.read_at_offset::(0).ok_or(Errno::EFAULT)?; Ok(SocketAddress::Inet(SocketAddr::V4(SocketAddrV4::from( inet_addr, )))) } AddressFamily::UNIX => { - let path = sockaddr.to_owned_slice(addrlen).ok_or(Errno::EFAULT)?; + let path = sockaddr + .to_owned_slice::(addrlen) + .ok_or(Errno::EFAULT)?; // skip the first two bytes (sa_family) let path = &path[offset_of!(CSockUnixAddr, path)..]; if path.is_empty() { @@ -1108,10 +1114,10 @@ pub(crate) fn read_sockaddr_from_user( pub(crate) fn write_sockaddr_to_user( sock_addr: SocketAddress, - addr: crate::MutPtr, - addrlen: crate::MutPtr, + addr: UserPtrMut, + addrlen: UserPtrMut, ) -> Result<(), Errno> { - let addrlen_val = addrlen.read_at_offset(0).ok_or(Errno::EFAULT)?; + let addrlen_val = addrlen.read_at_offset::(0).ok_or(Errno::EFAULT)?; if addrlen_val >= i32::MAX as u32 { return Err(Errno::EINVAL); } @@ -1120,14 +1126,14 @@ pub(crate) fn write_sockaddr_to_user( let addrlen_val = size_of::().min(addrlen_val as usize); let c_addr: CSockInetAddr = v4_addr.into(); let bytes: &[u8] = c_addr.as_bytes(); - addr.write_slice_at_offset(0, &bytes[..addrlen_val]) + addr.write_slice_at_offset::(0, &bytes[..addrlen_val]) .ok_or(Errno::EFAULT)?; size_of::() } SocketAddress::Unix(v) => { - let family_ptr = MutPtr::::from_usize(addr.as_usize()); + let family_ptr = UserPtrMut::::from_usize(addr.as_usize()); family_ptr - .write_at_offset(0, AddressFamily::UNIX as u16) + .write_at_offset::(0, AddressFamily::UNIX as u16) .ok_or(Errno::EFAULT)?; match v { UnixSocketAddr::Unnamed => { @@ -1137,10 +1143,10 @@ pub(crate) fn write_sockaddr_to_user( UnixSocketAddr::Abstract(name) => { let offset = offset_of!(CSockUnixAddr, path); if addrlen_val as usize > offset { - addr.write_at_offset(isize::try_from(offset).unwrap(), 0) + addr.write_at_offset::(isize::try_from(offset).unwrap(), 0) .ok_or(Errno::EFAULT)?; let max_len = addrlen_val as usize - offset - 1; - addr.write_slice_at_offset( + addr.write_slice_at_offset::( isize::try_from(offset + 1).unwrap(), &name[..name.len().min(max_len)], ) @@ -1152,12 +1158,12 @@ pub(crate) fn write_sockaddr_to_user( let offset = offset_of!(CSockUnixAddr, path); let max_len = addrlen_val as usize - offset; let name = &path.as_bytes()[..path.len().min(max_len)]; - addr.write_slice_at_offset(isize::try_from(offset).unwrap(), name) + addr.write_slice_at_offset::(isize::try_from(offset).unwrap(), name) .ok_or(Errno::EFAULT)?; let null_offset = offset + name.len(); // write null terminator if there is space if addrlen_val as usize > null_offset { - addr.write_at_offset(isize::try_from(null_offset).unwrap(), 0) + addr.write_at_offset::(isize::try_from(null_offset).unwrap(), 0) .ok_or(Errno::EFAULT)?; } offset + path.len() + 1 @@ -1167,15 +1173,12 @@ pub(crate) fn write_sockaddr_to_user( SocketAddress::Inet(SocketAddr::V6(_)) => todo!("copy_sockaddr_to_user for IPv6"), } .trunc(); - addrlen.write_at_offset(0, len).ok_or(Errno::EFAULT) + addrlen + .write_at_offset::(0, len) + .ok_or(Errno::EFAULT) } -fn copy_iovs_to_vec

( - iovs: &[litebox_common_linux::IoVec

], -) -> Result, Errno> -where - P: litebox::platform::RawMutPointer, -{ +fn copy_iovs_to_vec(iovs: &[litebox_common_linux::IoVec]) -> Result, Errno> { let total_len = iovs.iter().try_fold(0usize, |total_len, iov| { total_len.checked_add(iov.iov_len).ok_or(Errno::EINVAL) })?; @@ -1192,7 +1195,7 @@ where for (byte_offset, byte) in (0_isize..).zip(data[offset..end].iter_mut()) { *byte = iov .iov_base - .read_at_offset(byte_offset) + .read_at_offset::(byte_offset) .ok_or(Errno::EFAULT)?; } offset = end; @@ -1205,8 +1208,8 @@ impl Task { pub(crate) fn sys_accept( &self, sockfd: i32, - addr: Option>, - addrlen: Option>, + addr: Option>, + addrlen: Option>, flags: SockFlags, ) -> Result { let Ok(sockfd) = u32::try_from(sockfd) else { @@ -1285,7 +1288,7 @@ impl Task { pub(crate) fn sys_connect( &self, fd: i32, - sockaddr: ConstPtr, + sockaddr: UserPtr, addrlen: usize, ) -> Result<(), Errno> { let Ok(fd) = u32::try_from(fd) else { @@ -1313,7 +1316,7 @@ impl Task { pub(crate) fn sys_bind( &self, sockfd: i32, - sockaddr: ConstPtr, + sockaddr: UserPtr, addrlen: usize, ) -> Result<(), Errno> { let Ok(sockfd) = u32::try_from(sockfd) else { @@ -1357,10 +1360,10 @@ impl Task { pub(crate) fn sys_sendto( &self, fd: i32, - buf: ConstPtr, + buf: UserPtr, len: usize, flags: SendFlags, - addr: Option>, + addr: Option>, addrlen: u32, ) -> Result { let Ok(fd) = u32::try_from(fd) else { @@ -1369,7 +1372,7 @@ impl Task { let sockaddr = addr .map(|addr| read_sockaddr_from_user(addr, addrlen as usize)) .transpose()?; - let buf = buf.to_owned_slice(len).ok_or(Errno::EFAULT)?; + let buf = buf.to_owned_slice::(len).ok_or(Errno::EFAULT)?; self.do_sendto(fd, &buf, flags, sockaddr) } fn do_sendto( @@ -1410,25 +1413,25 @@ impl Task { pub(crate) fn sys_sendmsg( &self, fd: i32, - msg: ConstPtr>, + msg: UserPtr, flags: SendFlags, ) -> Result { let Ok(fd) = u32::try_from(fd) else { return Err(Errno::EBADF); }; - let msg = msg.read_at_offset(0).ok_or(Errno::EFAULT)?; + let msg = msg.read_at_offset::(0).ok_or(Errno::EFAULT)?; self.do_sendmsg(fd, &msg, flags) } fn do_sendmsg( &self, sockfd: u32, - msg: &litebox_common_linux::UserMsgHdr, + msg: &litebox_common_linux::UserMsgHdr, flags: SendFlags, ) -> Result { let msg_name = msg.msg_name; let sock_addr = if msg_name.as_usize() != 0 { Some(read_sockaddr_from_user( - ConstPtr::from_usize(msg_name.as_usize()), + UserPtr::from_usize(msg_name.as_usize()), msg.msg_namelen as usize, )?) } else { @@ -1446,7 +1449,7 @@ impl Task { } else { Some( msg.msg_iov - .to_owned_slice(msg.msg_iovlen) + .to_owned_slice::(msg.msg_iovlen) .ok_or(Errno::EFAULT)?, ) }; @@ -1483,7 +1486,7 @@ impl Task { pub(crate) fn sys_sendmmsg( &self, fd: i32, - msgvec: MutPtr>, + msgvec: UserPtrMut, vlen: u32, flags: SendFlags, ) -> Result { @@ -1506,14 +1509,13 @@ impl Task { return Ok(0); } - let stride = core::mem::size_of::>(); - let msg_len_off = - core::mem::offset_of!(litebox_common_linux::UserMmsgHdr, msg_len); + let stride = core::mem::size_of::(); + let msg_len_off = core::mem::offset_of!(litebox_common_linux::UserMmsgHdr, msg_len); let mut sent: usize = 0; for i in 0..vlen { let bail = |e: Errno| if sent > 0 { Ok(sent) } else { Err(e) }; - let Some(mmh) = msgvec.read_at_offset(isize::try_from(i).unwrap()) else { + let Some(mmh) = msgvec.read_at_offset::(isize::try_from(i).unwrap()) else { return bail(Errno::EFAULT); }; let inner = mmh.msg_hdr; @@ -1522,8 +1524,11 @@ impl Task { Err(e) => return bail(e), }; let msg_len_ptr = - MutPtr::::from_usize(msgvec.as_usize() + i * stride + msg_len_off); - if msg_len_ptr.write_at_offset(0, n.trunc()).is_none() { + UserPtrMut::::from_usize(msgvec.as_usize() + i * stride + msg_len_off); + if msg_len_ptr + .write_at_offset::(0, n.trunc()) + .is_none() + { return bail(Errno::EFAULT); } sent += 1; @@ -1535,11 +1540,11 @@ impl Task { pub(crate) fn sys_recvfrom( &self, fd: i32, - buf: MutPtr, + buf: UserPtrMut, len: usize, flags: ReceiveFlags, - addr: Option>, - addrlen: MutPtr, + addr: Option>, + addrlen: UserPtrMut, ) -> Result { const MAX_LEN: usize = 4096; let Ok(sockfd) = u32::try_from(fd) else { @@ -1559,7 +1564,7 @@ impl Task { }, )?; let capped_size = size.min(recv_buf.len()); - buf.copy_from_slice(0, &recv_buf[..capped_size]) + buf.copy_from_slice::(0, &recv_buf[..capped_size]) .ok_or(Errno::EFAULT)?; if let Some(src_addr) = source_addr && let Some(sock_ptr) = addr @@ -1634,7 +1639,7 @@ impl Task { pub(crate) fn sys_recvmsg( &self, fd: i32, - msg_ptr: MutPtr>, + msg_ptr: UserPtrMut, flags: ReceiveFlags, ) -> Result { let Ok(sockfd) = u32::try_from(fd) else { @@ -1652,10 +1657,10 @@ impl Task { fn do_recvmsg( &self, sockfd: u32, - msg_ptr: MutPtr>, + msg_ptr: UserPtrMut, flags: ReceiveFlags, ) -> Result { - let msg = msg_ptr.read_at_offset(0).ok_or(Errno::EFAULT)?; + let msg = msg_ptr.read_at_offset::(0).ok_or(Errno::EFAULT)?; // Copy fields out of the packed struct to avoid unaligned references. let msg_name = msg.msg_name; @@ -1670,7 +1675,9 @@ impl Task { return Err(Errno::EMSGSIZE); } - let iovs = msg_iov.to_owned_slice(msg_iovlen).ok_or(Errno::EFAULT)?; + let iovs = msg_iov + .to_owned_slice::(msg_iovlen) + .ok_or(Errno::EFAULT)?; let total_iov_capacity = iovs.iter().try_fold(0usize, |capacity, iov| { capacity.checked_add(iov.iov_len).ok_or(Errno::EINVAL) @@ -1715,7 +1722,7 @@ impl Task { } let chunk = (data_to_copy - offset).min(iov.iov_len); iov.iov_base - .copy_from_slice(0, &recv_buf[offset..offset + chunk]) + .copy_from_slice::(0, &recv_buf[offset..offset + chunk]) .ok_or(Errno::EFAULT)?; offset += chunk; } @@ -1730,33 +1737,34 @@ impl Task { // Write back source address if requested. if want_source { - let addrlen_ptr = MutPtr::::from_usize( + let addrlen_ptr = UserPtrMut::::from_usize( msg_ptr.as_usize() - + core::mem::offset_of!( - litebox_common_linux::UserMsgHdr, - msg_namelen - ), + + core::mem::offset_of!(litebox_common_linux::UserMsgHdr, msg_namelen), ); if let Some(src_addr) = source_addr { write_sockaddr_to_user(src_addr, msg_name, addrlen_ptr)?; } else { // No source address (e.g. connected stream socket) — zero out msg_namelen. - addrlen_ptr.write_at_offset(0, 0u32).ok_or(Errno::EFAULT)?; + addrlen_ptr + .write_at_offset::(0, 0u32) + .ok_or(Errno::EFAULT)?; } } // Ancillary data is not supported, so report that no control bytes were delivered. let controllen_offset = - core::mem::offset_of!(litebox_common_linux::UserMsgHdr, msg_controllen); - let controllen_ptr = MutPtr::::from_usize(msg_ptr.as_usize() + controllen_offset); - controllen_ptr.write_at_offset(0, 0).ok_or(Errno::EFAULT)?; + core::mem::offset_of!(litebox_common_linux::UserMsgHdr, msg_controllen); + let controllen_ptr = + UserPtrMut::::from_usize(msg_ptr.as_usize() + controllen_offset); + controllen_ptr + .write_at_offset::(0, 0) + .ok_or(Errno::EFAULT)?; // Write back msg_flags with any status flags (e.g. MSG_TRUNC). - let flags_offset = - core::mem::offset_of!(litebox_common_linux::UserMsgHdr, msg_flags); - let flags_ptr = MutPtr::::from_usize(msg_ptr.as_usize() + flags_offset); + let flags_offset = core::mem::offset_of!(litebox_common_linux::UserMsgHdr, msg_flags); + let flags_ptr = UserPtrMut::::from_usize(msg_ptr.as_usize() + flags_offset); flags_ptr - .write_at_offset(0, ret_flags) + .write_at_offset::(0, ret_flags) .ok_or(Errno::EFAULT)?; Ok(total_received) @@ -1766,10 +1774,10 @@ impl Task { pub(crate) fn sys_recvmmsg( &self, fd: i32, - msgvec: MutPtr>, + msgvec: UserPtrMut, vlen: u32, flags: ReceiveFlags, - timeout: litebox_common_linux::TimeParam, + timeout: litebox_common_linux::TimeParam, ) -> Result { let supported_flags = ReceiveFlags::DONTWAIT | ReceiveFlags::TRUNC | ReceiveFlags::WAITFORONE; @@ -1780,7 +1788,7 @@ impl Task { // Linux's `do_recvmmsg` validates the timespec before looking up the fd, // so a bad timeout takes precedence over EBADF. - let timeout_duration = timeout.read()?; + let timeout_duration = timeout.read::()?; let Ok(sockfd) = u32::try_from(fd) else { return Err(Errno::EBADF); @@ -1805,8 +1813,8 @@ impl Task { // — both are treated as "no deadline". let deadline = timeout_duration.and_then(|d| self.global.platform.now().checked_add(d)); - let stride = size_of::>(); - let msg_len_off = offset_of!(UserMmsgHdr, msg_len); + let stride = size_of::(); + let msg_len_off = offset_of!(UserMmsgHdr, msg_len); let msgvec_base = msgvec.as_usize(); let msgvec_len = vlen.checked_mul(stride).ok_or(Errno::EFAULT)?; if msgvec_base.checked_add(msgvec_len).is_none() { @@ -1821,7 +1829,7 @@ impl Task { let mut async_error_to_restore = None; for i in 0..vlen { let base = msgvec_base + i * stride; - let inner_ptr = MutPtr::>::from_usize(base); + let inner_ptr = UserPtrMut::::from_usize(base); let n = match self.do_recvmsg(sockfd, inner_ptr, iter_flags) { Ok(n) => n, Err(e) => { @@ -1832,8 +1840,11 @@ impl Task { break; } }; - let msg_len_ptr = MutPtr::::from_usize(base + msg_len_off); - if msg_len_ptr.write_at_offset(0, n.trunc()).is_none() { + let msg_len_ptr = UserPtrMut::::from_usize(base + msg_len_off); + if msg_len_ptr + .write_at_offset::(0, n.trunc()) + .is_none() + { last_err = Some(Errno::EFAULT); break; } @@ -1868,7 +1879,7 @@ impl Task { let remaining = deadline .and_then(|d| d.checked_duration_since(&self.global.platform.now())) .unwrap_or(core::time::Duration::ZERO); - timeout.write(remaining)?; + timeout.write::(remaining)?; Ok(received) } @@ -1878,7 +1889,7 @@ impl Task { sockfd: i32, level: u32, optname: u32, - optval: ConstPtr, + optval: UserPtr, optlen: usize, ) -> Result<(), Errno> { let Ok(sockfd) = u32::try_from(sockfd) else { @@ -1894,7 +1905,7 @@ impl Task { &self, sockfd: u32, optname: SocketOptionName, - optval: ConstPtr, + optval: UserPtr, optlen: usize, ) -> Result<(), Errno> { self.files.borrow().with_socket( @@ -1911,8 +1922,8 @@ impl Task { sockfd: i32, level: u32, optname: u32, - optval: MutPtr, - optlen: MutPtr, + optval: UserPtrMut, + optlen: UserPtrMut, ) -> Result<(), Errno> { let Ok(sockfd) = u32::try_from(sockfd) else { return Err(Errno::EBADF); @@ -1921,13 +1932,13 @@ impl Task { log_unsupported!("setsockopt(level = {level}, optname = {optname})"); Errno::EINVAL })?; - let len = optlen.read_at_offset(0).ok_or(Errno::EFAULT)?; + let len = optlen.read_at_offset::(0).ok_or(Errno::EFAULT)?; if len > i32::MAX as u32 { return Err(Errno::EINVAL); } let new_len = self.do_getsockopt(sockfd, optname, optval, len)?; optlen - .write_at_offset(0, new_len.trunc()) + .write_at_offset::(0, new_len.trunc()) .ok_or(Errno::EFAULT)?; Ok(()) } @@ -1938,7 +1949,7 @@ impl Task { &self, sockfd: u32, optname: SocketOptionName, - optval: MutPtr, + optval: UserPtrMut, len: u32, ) -> Result { self.files.borrow().with_socket( @@ -1953,8 +1964,8 @@ impl Task { pub(crate) fn sys_getsockname( &self, sockfd: i32, - addr: MutPtr, - addrlen: MutPtr, + addr: UserPtrMut, + addrlen: UserPtrMut, ) -> Result<(), Errno> { let Ok(sockfd) = u32::try_from(sockfd) else { return Err(Errno::EBADF); @@ -1982,8 +1993,8 @@ impl Task { pub(crate) fn sys_getpeername( &self, sockfd: i32, - addr: MutPtr, - addrlen: MutPtr, + addr: UserPtrMut, + addrlen: UserPtrMut, ) -> Result<(), Errno> { let Ok(sockfd) = u32::try_from(sockfd) else { return Err(Errno::EBADF); @@ -2045,7 +2056,6 @@ mod tests { use core::net::SocketAddr; use alloc::string::ToString as _; - use litebox::platform::RawConstPointer as _; use litebox::utils::TruncateExt as _; use litebox_common_linux::{ AddressFamily, ReceiveFlags, SendFlags, SockFlags, SockType, SocketOption, @@ -2055,7 +2065,7 @@ mod tests { use super::SocketAddress; use crate::{ - ConstPtr, MutPtr, + UserPtr, UserPtrMut, syscalls::{ net::{CSockInetAddr, read_sockaddr_from_user}, tests::init_platform, @@ -2067,7 +2077,7 @@ mod tests { // Compile-time layout check: UserMsgHdr must match Linux's struct user_msghdr. const _USER_MSG_HDR_SIZE: () = assert!( - core::mem::size_of::>() + core::mem::size_of::() == core::mem::size_of::() ); @@ -2090,7 +2100,7 @@ mod tests { .do_getsockopt( sockfd, SocketOptionName::Socket(SocketOption::ERROR), - MutPtr::from_usize((&raw mut optval).cast::() as usize), + UserPtrMut::from_usize((&raw mut optval).cast::() as usize), core::mem::size_of::().trunc(), ) .expect("getsockopt SO_ERROR failed"); @@ -2109,7 +2119,7 @@ mod tests { data: u64::from(target_fd), }; let ev_ptr = (&raw const ev).cast::(); - let ev_const = crate::ConstPtr::from_usize(ev_ptr as usize); + let ev_const = UserPtr::from_usize(ev_ptr as usize); task.sys_epoll_ctl( epfd, litebox_common_linux::EpollOp::EpollCtlAdd, @@ -2124,7 +2134,7 @@ mod tests { epfd: i32, events: &mut [litebox_common_linux::EpollEvent], ) -> usize { - let events_ptr = crate::MutPtr::from_usize(events.as_mut_ptr() as usize); + let events_ptr = UserPtrMut::from_usize(events.as_mut_ptr() as usize); task.sys_epoll_pwait(epfd, events_ptr, events.len().trunc(), -1, None, 0) .expect("epoll_wait failed") } @@ -2239,17 +2249,17 @@ mod tests { let buf2 = " world!\n"; let iovec = [ litebox_common_linux::IoVec { - iov_base: MutPtr::from_usize(buf1.as_ptr().expose_provenance()), + iov_base: UserPtrMut::from_usize(buf1.as_ptr().expose_provenance()), iov_len: buf1.len(), }, litebox_common_linux::IoVec { - iov_base: MutPtr::from_usize(buf2.as_ptr().expose_provenance()), + iov_base: UserPtrMut::from_usize(buf2.as_ptr().expose_provenance()), iov_len: buf2.len(), }, ]; let hdr = { - let mut h = litebox_common_linux::UserMsgHdr::::new_zeroed(); - h.msg_iov = ConstPtr::from_usize(iovec.as_ptr() as usize); + let mut h = litebox_common_linux::UserMsgHdr::new_zeroed(); + h.msg_iov = UserPtr::from_usize(iovec.as_ptr() as usize); h.msg_iovlen = iovec.len(); h }; @@ -2288,14 +2298,15 @@ mod tests { .expect("Failed to receive data"), "recvmsg" => { let iovec = [litebox_common_linux::IoVec { - iov_base: MutPtr::from_usize(recv_buf.as_mut_ptr().expose_provenance()), + iov_base: UserPtrMut::from_usize( + recv_buf.as_mut_ptr().expose_provenance(), + ), iov_len: recv_buf.len(), }]; - let mut msg_hdr = - litebox_common_linux::UserMsgHdr::::new_zeroed(); - msg_hdr.msg_iov = ConstPtr::from_usize(iovec.as_ptr() as usize); + let mut msg_hdr = litebox_common_linux::UserMsgHdr::new_zeroed(); + msg_hdr.msg_iov = UserPtr::from_usize(iovec.as_ptr() as usize); msg_hdr.msg_iovlen = iovec.len(); - let msg_ptr = MutPtr::from_usize(&raw mut msg_hdr as usize); + let msg_ptr = UserPtrMut::from_usize(&raw mut msg_hdr as usize); task.sys_recvmsg(i32::try_from(client_fd).unwrap(), msg_ptr, flags) .expect("failed to recvmsg") } @@ -2454,7 +2465,7 @@ mod tests { onoff: 1, // enable linger linger: 60, // timeout in seconds }; - let optval = ConstPtr::from_usize((&raw const linger).cast::() as usize); + let optval = UserPtr::from_usize((&raw const linger).cast::() as usize); task.do_setsockopt( client_fd, SocketOptionName::Socket(SocketOption::LINGER), @@ -2563,25 +2574,25 @@ mod tests { let mut addrlen = core::mem::size_of::(); task.sys_recvfrom( i32::try_from(server_fd).unwrap(), - MutPtr::from_usize(recv_buf.as_mut_ptr() as usize), + UserPtrMut::from_usize(recv_buf.as_mut_ptr() as usize), recv_len, recv_flags, - Some(MutPtr::from_usize(source_addr.as_ptr() as usize)), - MutPtr::from_usize(&raw mut addrlen as usize), + Some(UserPtrMut::from_usize(source_addr.as_ptr() as usize)), + UserPtrMut::from_usize(&raw mut addrlen as usize), ) .expect("recvfrom failed") } "recvmsg" => { let iovec = [litebox_common_linux::IoVec { - iov_base: MutPtr::from_usize(recv_buf.as_mut_ptr() as usize), + iov_base: UserPtrMut::from_usize(recv_buf.as_mut_ptr() as usize), iov_len: recv_len, }]; - let mut msg_hdr = litebox_common_linux::UserMsgHdr::::new_zeroed(); - msg_hdr.msg_iov = ConstPtr::from_usize(iovec.as_ptr() as usize); + let mut msg_hdr = litebox_common_linux::UserMsgHdr::new_zeroed(); + msg_hdr.msg_iov = UserPtr::from_usize(iovec.as_ptr() as usize); msg_hdr.msg_iovlen = iovec.len(); - msg_hdr.msg_name = MutPtr::from_usize(source_addr.as_ptr() as usize); + msg_hdr.msg_name = UserPtrMut::from_usize(source_addr.as_ptr() as usize); msg_hdr.msg_namelen = source_addr.len().trunc(); - let msg_ptr = MutPtr::from_usize(&raw mut msg_hdr as usize); + let msg_ptr = UserPtrMut::from_usize(&raw mut msg_hdr as usize); let n = task .sys_recvmsg(i32::try_from(server_fd).unwrap(), msg_ptr, recv_flags) .expect("recvmsg failed"); @@ -2594,7 +2605,7 @@ mod tests { _ => panic!("Unknown operation"), }; let sender_addr = read_sockaddr_from_user( - ConstPtr::from_usize(source_addr.as_ptr() as usize), + UserPtr::from_usize(source_addr.as_ptr() as usize), source_addr.len(), ) .ok(); @@ -2705,7 +2716,7 @@ mod tests { .do_getsockopt( sockfd, SocketOptionName::TCP(TcpOption::CONGESTION), - MutPtr::from_usize(congestion_name.as_mut_ptr() as usize), + UserPtrMut::from_usize(congestion_name.as_mut_ptr() as usize), congestion_name.len().trunc(), ) .expect("Failed to get TCP_CONGESTION"); @@ -2718,7 +2729,7 @@ mod tests { task.do_setsockopt( sockfd, SocketOptionName::TCP(TcpOption::CONGESTION), - ConstPtr::from_usize(congestion_name.as_ptr() as usize), + UserPtr::from_usize(congestion_name.as_ptr() as usize), optlen, ) .expect("Failed to set TCP_CONGESTION"); @@ -2728,14 +2739,14 @@ mod tests { .do_setsockopt( sockfd, SocketOptionName::TCP(TcpOption::CONGESTION), - ConstPtr::from_usize(congestion_name.as_ptr() as usize), + UserPtr::from_usize(congestion_name.as_ptr() as usize), congestion_name.len(), ) .unwrap_err(); assert_eq!(err, Errno::EINVAL); let val: u32 = 1; - let optval = ConstPtr::from_usize((&raw const val).cast::() as usize); + let optval = UserPtr::from_usize((&raw const val).cast::() as usize); task.do_setsockopt( sockfd, SocketOptionName::Socket(SocketOption::KEEPALIVE), @@ -2746,7 +2757,7 @@ mod tests { // Verify SO_KEEPALIVE is enabled let mut result: u32 = 0; - let optval_out = MutPtr::from_usize((&raw mut result).cast::() as usize); + let optval_out = UserPtrMut::from_usize((&raw mut result).cast::() as usize); let len = task .do_getsockopt( sockfd, @@ -2811,14 +2822,14 @@ mod unix_tests { use core::time::Duration; use alloc::{string::ToString, vec::Vec}; - use litebox::{event::Events, platform::RawConstPointer}; + use litebox::event::Events; use litebox_common_linux::{ AddressFamily, AtFlags, ReceiveFlags, SendFlags, SockFlags, SockType, SocketOption, SocketOptionName, TimeParam, errno::Errno, }; use crate::{ - ConstPtr, MutPtr, Task, + Task, UserPtr, UserPtrMut, syscalls::{net::SocketAddress, tests::init_platform, unix::UnixSocketAddr}, }; @@ -2857,7 +2868,7 @@ mod unix_tests { let n = task .sys_ppoll( - MutPtr::from_usize(pollfd.as_mut_ptr() as usize), + UserPtrMut::from_usize(pollfd.as_mut_ptr() as usize), 1, TimeParam::None, None, @@ -3227,7 +3238,7 @@ mod unix_tests { fn unix_socketpair_bidirectional(ty: SockType, is_nonblocking: bool) { let task = init_platform(None); let mut sv_ptr = alloc::vec![0u32; 2]; - let sv_mut_ptr = MutPtr::from_usize(sv_ptr.as_mut_ptr() as usize); + let sv_mut_ptr = UserPtrMut::from_usize(sv_ptr.as_mut_ptr() as usize); let ty_and_flags = if is_nonblocking { SockFlags::NONBLOCK.bits() @@ -3297,7 +3308,7 @@ mod unix_tests { .expect("socketpair failed"); let timeout = Duration::from_millis(200); let tv = litebox_common_linux::TimeVal::from(timeout); - let optval = ConstPtr::from_usize((&raw const tv).cast::() as usize); + let optval = UserPtr::from_usize((&raw const tv).cast::() as usize); task.do_setsockopt( sock1, SocketOptionName::Socket(SocketOption::RCVTIMEO), diff --git a/litebox_shim_linux/src/syscalls/process.rs b/litebox_shim_linux/src/syscalls/process.rs index bdcfa19b8..cb1a4b63e 100644 --- a/litebox_shim_linux/src/syscalls/process.rs +++ b/litebox_shim_linux/src/syscalls/process.rs @@ -3,7 +3,7 @@ //! Process/thread related syscalls. -use crate::{ConstPtr, MutPtr, ShimFS, Task}; +use crate::{ShimFS, Task, UserPtr, UserPtrMut}; use alloc::boxed::Box; use alloc::collections::btree_map::BTreeMap; use alloc::sync::Arc; @@ -16,11 +16,9 @@ use core::time::Duration; use litebox::event::wait::WaitError; use litebox::mm::linux::VmFlags; use litebox::platform::ThreadProvider; -use litebox::platform::{ - ArchSpecificProvider as _, ArchSpecificRegister, RawConstPointer as _, RawMutex as _, -}; +use litebox::platform::{ArchSpecificProvider as _, ArchSpecificRegister, RawMutex as _}; use litebox::platform::{Instant as _, SystemTime as _, TimeProvider}; -use litebox::platform::{RawMutPointer as _, TimerHandle, TimerProvider}; +use litebox::platform::{TimerHandle, TimerProvider}; use litebox::sync::Mutex; use litebox::utils::TruncateExt as _; use litebox_common_linux::{ @@ -43,12 +41,12 @@ pub(crate) struct ThreadState { /// /// This operation wakes a single thread waiting on the specified memory location via futex. /// Any errors from the futex wake operation are ignored. - clear_child_tid: Cell>>, + clear_child_tid: Cell>>, /// The purpose of the robust futex list is to ensure that if a thread accidentally fails to unlock a futex before /// terminating or calling execve(2), another thread that is waiting on that futex is notified that the former owner /// of the futex has died. This notification consists of two pieces: the FUTEX_OWNER_DIED bit is set in the futex word, /// and the kernel performs a futex(2) FUTEX_WAKE operation on one of the threads waiting on the futex. - robust_list: Cell>>, + robust_list: Cell>>, } // TODO: remove once we figure out how to handle Send/Sync for raw pointers. @@ -334,7 +332,7 @@ enum ThreadInitState { NewThread { stack: Option, tls: Option, - set_child_tid: Option>, + set_child_tid: Option>, }, } @@ -361,13 +359,10 @@ impl Task { } /// Handle syscall `prctl`. - pub(crate) fn sys_prctl( - &self, - arg: PrctlArg, - ) -> Result { + pub(crate) fn sys_prctl(&self, arg: PrctlArg) -> Result { match arg { PrctlArg::GetName(name) => name - .write_slice_at_offset(0, &self.comm.get()) + .write_slice_at_offset::(0, &self.comm.get()) .ok_or(Errno::EFAULT) .map(|()| 0), PrctlArg::SetName(name) => { @@ -375,7 +370,7 @@ impl Task { // strncpy for (i, byte) in name_buf.iter_mut().enumerate() { let b = name - .read_at_offset(isize::try_from(i).unwrap()) + .read_at_offset::(isize::try_from(i).unwrap()) .ok_or(Errno::EFAULT)?; if b == 0 { break; @@ -403,10 +398,7 @@ impl Task { } /// Handle syscall `arch_prctl`. - pub(crate) fn sys_arch_prctl( - &self, - arg: ArchPrctlArg, - ) -> Result<(), Errno> { + pub(crate) fn sys_arch_prctl(&self, arg: ArchPrctlArg) -> Result<(), Errno> { match arg { #[cfg(target_arch = "x86_64")] ArchPrctlArg::SetFs(addr) => self @@ -420,7 +412,8 @@ impl Task { .global .platform .get_arch_specific_register(&ArchSpecificRegister::FsBase)?; - addr.write_at_offset(0, fsbase).ok_or(Errno::EFAULT)?; + addr.write_at_offset::(0, fsbase) + .ok_or(Errno::EFAULT)?; Ok(()) } ArchPrctlArg::CETStatus | ArchPrctlArg::CETDisable | ArchPrctlArg::CETLock => { @@ -437,12 +430,8 @@ const ROBUST_LIST_LIMIT: isize = 2048; * Process a futex-list entry, check whether it's owned by the * dying task, and do notification if so: */ -fn handle_futex_death( - futex_addr: crate::ConstPtr, - _pi: bool, - _pending_op: bool, -) -> Result<(), Errno> { - if futex_addr.as_usize() % 4 != 0 { +fn handle_futex_death(futex_addr: UserPtr, _pi: bool, _pending_op: bool) -> Result<(), Errno> { + if !futex_addr.as_usize().is_multiple_of(4) { return Err(Errno::EINVAL); } @@ -450,29 +439,27 @@ fn handle_futex_death( } fn fetch_robust_entry( - head: crate::ConstPtr, -) -> (crate::ConstPtr, bool) { + head: UserPtr, +) -> (UserPtr, bool) { let next = head.as_usize(); - (crate::ConstPtr::from_usize(next & !1), next & 1 != 0) + (UserPtr::from_usize(next & !1), next & 1 != 0) } -fn wake_robust_list( - head: crate::ConstPtr, -) -> Result<(), Errno> { +fn wake_robust_list(head: UserPtr) -> Result<(), Errno> { let mut limit = ROBUST_LIST_LIMIT; let head_ptr = head.as_usize(); - let head = head.read_at_offset(0).ok_or(Errno::EFAULT)?; - let (mut entry, mut pi) = fetch_robust_entry(crate::ConstPtr::from_usize(head.list.next)); - let (pending, ppi) = fetch_robust_entry(crate::ConstPtr::from_usize(head.list_op_pending)); + let head = head.read_at_offset::(0).ok_or(Errno::EFAULT)?; + let (mut entry, mut pi) = fetch_robust_entry(UserPtr::from_usize(head.list.next)); + let (pending, ppi) = fetch_robust_entry(UserPtr::from_usize(head.list_op_pending)); let futex_offset = head.futex_offset; let entry_head = head_ptr + offset_of!(litebox_common_linux::RobustListHead, list); while entry.as_usize() != entry_head && limit > 0 { let nxt = entry - .read_at_offset(0) - .map(|e| fetch_robust_entry(crate::ConstPtr::from_usize(e.next))); + .read_at_offset::(0) + .map(|e| fetch_robust_entry(UserPtr::from_usize(e.next))); if entry.as_usize() != pending.as_usize() { handle_futex_death( - crate::ConstPtr::from_usize(entry.as_usize() + futex_offset), + UserPtr::from_usize(entry.as_usize() + futex_offset), pi, false, )?; @@ -488,7 +475,7 @@ fn wake_robust_list( if pending.as_usize() != 0 { let _ = handle_futex_death( - crate::ConstPtr::from_usize(pending.as_usize() + futex_offset), + UserPtr::from_usize(pending.as_usize() + futex_offset), ppi, true, ); @@ -504,9 +491,9 @@ impl Task { if let Some(clear_child_tid) = self.thread.clear_child_tid.take() { // Clear the child TID if requested // TODO: if we are the last thread, we don't need to clear it - let _ = clear_child_tid.write_at_offset(0, 0); + let _ = clear_child_tid.write_at_offset::(0, 0); // Cast from *i32 to *u32 - let clear_child_tid = crate::MutPtr::from_usize(clear_child_tid.as_usize()); + let clear_child_tid = UserPtrMut::from_usize(clear_child_tid.as_usize()); let _ = self.sys_futex(litebox_common_linux::FutexArgs::Wake { addr: clear_child_tid, flags: litebox_common_linux::FutexFlags::PRIVATE, @@ -535,7 +522,7 @@ impl Task { /// On `x86_64`, this is represented as a `*mut u8`. The TLS pointer can point to /// an arbitrary-sized memory region. #[cfg(target_arch = "x86_64")] -type ThreadLocalDescriptor = MutPtr; +type ThreadLocalDescriptor = UserPtrMut; struct NewThreadArgs { /// Task struct that maintains all per-thread data @@ -570,9 +557,9 @@ impl Task { pub(crate) fn sys_clone3( &self, ctx: &litebox_common_linux::PtRegs, - args: ConstPtr, + args: UserPtr, ) -> Result { - let args = args.read_at_offset(0).ok_or(Errno::EFAULT)?; + let args = args.read_at_offset::(0).ok_or(Errno::EFAULT)?; self.do_clone(ctx, &args, true) } @@ -663,7 +650,7 @@ impl Task { } } #[cfg(target_arch = "x86_64")] - let desc = MutPtr::from_usize(addr); + let desc = UserPtrMut::from_usize(addr); Some(desc) } else { None @@ -672,7 +659,7 @@ impl Task { let child_tid = if child_tid == 0 { None } else { - Some(MutPtr::from_usize(child_tid.trunc())) + Some(UserPtrMut::from_usize(child_tid.trunc())) }; let set_child_tid = if flags.contains(CloneFlags::CHILD_SETTID) { child_tid @@ -685,7 +672,7 @@ impl Task { None }; let set_parent_tid = if flags.contains(CloneFlags::PARENT_SETTID) && parent_tid != 0 { - Some(MutPtr::from_usize(parent_tid.trunc())) + Some(UserPtrMut::from_usize(parent_tid.trunc())) } else { None }; @@ -698,7 +685,7 @@ impl Task { let child_tid = self.global.next_thread_id.fetch_add(1, Ordering::Relaxed); if let Some(parent_tid_ptr) = set_parent_tid { - let _ = parent_tid_ptr.write_at_offset(0, child_tid); + let _ = parent_tid_ptr.write_at_offset::(0, child_tid); } if (stack == 0 && stack_size != 0) || (stack != 0 && clone3 && stack_size == 0) { @@ -751,7 +738,7 @@ impl Task { } /// Handle syscall `set_tid_address`. - pub(crate) fn sys_set_tid_address(&self, tidptr: crate::MutPtr) -> i32 { + pub(crate) fn sys_set_tid_address(&self, tidptr: UserPtrMut) -> i32 { self.thread.clear_child_tid.set(Some(tidptr)); self.tid } @@ -882,15 +869,15 @@ impl Task { &self, pid: i32, resource: litebox_common_linux::RlimitResource, - new_rlim: Option>, - old_rlim: Option>, + new_rlim: Option>, + old_rlim: Option>, ) -> Result<(), Errno> { if pid != 0 { unimplemented!("prlimit for a specific PID is not supported yet"); } let new_limit = match new_rlim { Some(rlim) => { - let rlim = rlim.read_at_offset(0).ok_or(Errno::EINVAL)?; + let rlim = rlim.read_at_offset::(0).ok_or(Errno::EINVAL)?; Some(litebox_common_linux::rlimit64_to_rlimit(rlim)) } None => None, @@ -899,7 +886,7 @@ impl Task { litebox_common_linux::rlimit_to_rlimit64(self.do_prlimit(resource, new_limit)?); if let Some(old_rlim) = old_rlim { old_rlim - .write_at_offset(0, old_limit) + .write_at_offset::(0, old_limit) .ok_or(Errno::EINVAL)?; } Ok(()) @@ -909,26 +896,27 @@ impl Task { pub(crate) fn sys_getrlimit( &self, resource: litebox_common_linux::RlimitResource, - rlim: crate::MutPtr, + rlim: UserPtrMut, ) -> Result<(), Errno> { let old_limit = self.do_prlimit(resource, None)?; - rlim.write_at_offset(0, old_limit).ok_or(Errno::EINVAL) + rlim.write_at_offset::(0, old_limit) + .ok_or(Errno::EINVAL) } /// Handle syscall `setrlimit`. pub(crate) fn sys_setrlimit( &self, resource: litebox_common_linux::RlimitResource, - rlim: crate::ConstPtr, + rlim: UserPtr, ) -> Result<(), Errno> { - let new_limit = rlim.read_at_offset(0).ok_or(Errno::EFAULT)?; + let new_limit = rlim.read_at_offset::(0).ok_or(Errno::EFAULT)?; let _ = self.do_prlimit(resource, Some(new_limit))?; Ok(()) } /// Handle syscall `set_robust_list`. pub(crate) fn sys_set_robust_list(&self, head: usize) { - let head = crate::ConstPtr::from_usize(head); + let head = UserPtr::from_usize(head); self.thread.robust_list.set(Some(head)); } @@ -936,7 +924,7 @@ impl Task { pub(crate) fn sys_get_robust_list( &self, pid: Option, - head_ptr: crate::MutPtr, + head_ptr: UserPtrMut, ) -> Result<(), Errno> { if pid.is_some() { unimplemented!("Getting robust list for a specific PID is not supported yet"); @@ -946,7 +934,9 @@ impl Task { .robust_list .get() .map_or(0, |ptr| ptr.as_usize()); - head_ptr.write_at_offset(0, head).ok_or(Errno::EFAULT) + head_ptr + .write_at_offset::(0, head) + .ok_or(Errno::EFAULT) } fn real_time_as_duration_since_epoch(&self) -> core::time::Duration { @@ -961,10 +951,10 @@ impl Task { pub(crate) fn sys_clock_gettime( &self, clockid: litebox_common_linux::ClockId, - tp: TimeParam, + tp: TimeParam, ) -> Result<(), Errno> { let duration = self.gettime_as_duration(clockid)?; - tp.write(duration) + tp.write::(duration) } fn gettime_as_duration( @@ -1035,7 +1025,7 @@ impl Task { pub(crate) fn sys_clock_getres( &self, clockid: litebox_common_linux::ClockId, - res: TimeParam, + res: TimeParam, ) -> Result<(), Errno> { // Return the resolution of the clock let resolution = match clockid { @@ -1051,7 +1041,7 @@ impl Task { _ => unimplemented!(), }; - res.write(resolution) + res.write::(resolution) } /// Handle syscall `clock_nanosleep`. @@ -1059,10 +1049,10 @@ impl Task { &self, clockid: litebox_common_linux::ClockId, flags: litebox_common_linux::TimerFlags, - request: TimeParam, - remain: TimeParam, + request: TimeParam, + remain: TimeParam, ) -> Result<(), Errno> { - let request = request.read()?.ok_or(Errno::EFAULT)?; + let request = request.read::()?.ok_or(Errno::EFAULT)?; if flags.intersects(litebox_common_linux::TimerFlags::ABSTIME.complement()) { return Err(Errno::EINVAL); } @@ -1084,7 +1074,7 @@ impl Task { return Err(Errno::EINTR); } if let Some(remaining_timeout) = wait_cx.remaining_timeout() { - remain.write(remaining_timeout)?; + remain.write::(remaining_timeout)?; return Err(Errno::EINTR); } // Whoops, time ran out after getting interrupted. Treat this as a timeout. @@ -1097,18 +1087,19 @@ impl Task { /// Handle syscall `gettimeofday`. pub(crate) fn sys_gettimeofday( &self, - tv: Option>, - tz: Option>, + tv: Option>, + tz: Option>, ) -> Result<(), Errno> { if let Some(tz) = tz { // `man 2 gettimeofday`: The use of the timezone structure is obsolete; the tz argument // should normally be specified as NULL. Linux still accepts a non-NULL tz and fills it // in (typically with zeros for UTC systems) rather than returning an error. let utc_tz = litebox_common_linux::TimeZone::new(0, 0); - tz.write_at_offset(0, utc_tz).ok_or(Errno::EFAULT)?; + tz.write_at_offset::(0, utc_tz) + .ok_or(Errno::EFAULT)?; } if let Some(tv) = tv { - tv.write_at_offset(0, self.real_time_as_duration_since_epoch().into()) + tv.write_at_offset::(0, self.real_time_as_duration_since_epoch().into()) .ok_or(Errno::EFAULT)?; } Ok(()) @@ -1117,13 +1108,14 @@ impl Task { /// Handle syscall `time`. pub(crate) fn sys_time( &self, - tloc: Option>, + tloc: Option>, ) -> Result { let time = self.real_time_as_duration_since_epoch(); let seconds: u64 = time.as_secs(); let seconds: litebox_common_linux::time_t = seconds.try_into().or(Err(Errno::EOVERFLOW))?; if let Some(tloc) = tloc { - tloc.write_at_offset(0, seconds).ok_or(Errno::EFAULT)?; + tloc.write_at_offset::(0, seconds) + .ok_or(Errno::EFAULT)?; } Ok(seconds) } @@ -1181,11 +1173,11 @@ impl Task { pub(crate) fn sys_setitimer( &self, which: IntervalTimer, - new_value: Option>, - old_value: Option>, + new_value: Option>, + old_value: Option>, ) -> Result<(), Errno> { let new = match new_value { - Some(ptr) => ptr.read_at_offset(0).ok_or(Errno::EFAULT)?, + Some(ptr) => ptr.read_at_offset::(0).ok_or(Errno::EFAULT)?, // Linux supports NULL `new_value` but says it would be removed in the future. None => ItimerVal::default(), }; @@ -1212,7 +1204,8 @@ impl Task { }; if let Some(out) = old_value { - out.write_at_offset(0, prev).ok_or(Errno::EFAULT)?; + out.write_at_offset::(0, prev) + .ok_or(Errno::EFAULT)?; } Ok(()) } @@ -1221,7 +1214,7 @@ impl Task { pub(crate) fn sys_getitimer( &self, which: IntervalTimer, - curr_value: MutPtr, + curr_value: UserPtrMut, ) -> Result<(), Errno> { let value = match which { IntervalTimer::Real => { @@ -1235,7 +1228,7 @@ impl Task { } }; curr_value - .write_at_offset(0, ItimerVal::single_shot(value)) + .write_at_offset::(0, ItimerVal::single_shot(value)) .ok_or(Errno::EFAULT) } @@ -1306,10 +1299,7 @@ impl Task { impl Task { /// Handle syscall `futex` - pub(crate) fn sys_futex( - &self, - arg: litebox_common_linux::FutexArgs, - ) -> Result { + pub(crate) fn sys_futex(&self, arg: litebox_common_linux::FutexArgs) -> Result { /// Note our mutex implementation assumes futexes are private as we don't support shared memory yet. /// It should be fine to treat shared futexes as private for now. macro_rules! warn_shared_futex { @@ -1326,7 +1316,9 @@ impl Task { let Some(count) = core::num::NonZeroU32::new(count) else { return Ok(0); }; - self.global.futex_manager.wake(addr, count, None)? as usize + self.global + .futex_manager + .wake(addr.to_platform_ptr::(), count, None)? as usize } FutexArgs::Wait { addr, @@ -1335,10 +1327,10 @@ impl Task { timeout, } => { warn_shared_futex!(flags); - let timeout = timeout.read()?; + let timeout = timeout.read::()?; self.global.futex_manager.wait( &self.wait_cx().with_timeout(timeout), - addr, + addr.to_platform_ptr::(), val, None, )?; @@ -1352,7 +1344,7 @@ impl Task { bitmask, } => { warn_shared_futex!(flags); - let deadline = if let Some(timeout) = timeout.read()? { + let deadline = if let Some(timeout) = timeout.read::()? { let clock_id = if flags.contains(litebox_common_linux::FutexFlags::CLOCK_REALTIME) { litebox_common_linux::ClockId::RealTime @@ -1365,7 +1357,7 @@ impl Task { }; self.global.futex_manager.wait( &self.wait_cx().with_deadline(deadline), - addr, + addr.to_platform_ptr::(), val, core::num::NonZeroU32::new(bitmask), )?; @@ -1464,21 +1456,21 @@ impl Task { /// Handle syscall `execve`. pub(crate) fn sys_execve( &self, - pathname: crate::ConstPtr, - argv: crate::ConstPtr>, - envp: crate::ConstPtr>, + pathname: UserPtr, + argv: UserPtr>, + envp: UserPtr>, ctx: &mut litebox_common_linux::PtRegs, ) -> Result { fn copy_vector( - mut base: crate::ConstPtr>, + mut base: UserPtr>, _which: &str, ) -> Result, Errno> { let mut out = alloc::vec::Vec::new(); let mut total = 0usize; for _ in 0..MAX_VEC { - let p: crate::ConstPtr = { + let p: UserPtr = { // read pointer-sized entries - match base.read_at_offset(0) { + match base.read_at_offset::(0) { Some(ptr) => ptr, None => return Err(Errno::EFAULT), } @@ -1486,7 +1478,7 @@ impl Task { if p.as_usize() == 0 { break; } - let Some(cs) = p.to_cstring() else { + let Some(cs) = p.to_cstring::() else { return Err(Errno::EFAULT); }; total += cs.as_bytes().len() + 1; @@ -1495,13 +1487,13 @@ impl Task { } out.push(cs); // advance to next pointer - base = crate::ConstPtr::from_usize(base.as_usize() + core::mem::size_of::()); + base = UserPtr::from_usize(base.as_usize() + core::mem::size_of::()); } Ok(out) } // Copy pathname - let Some(path_cstr) = pathname.to_cstring() else { + let Some(path_cstr) = pathname.to_cstring::() else { return Err(Errno::EFAULT); }; let path = path_cstr.to_str().map_err(|_| Errno::ENOENT)?; @@ -1638,7 +1630,6 @@ impl Task { if let Some(tls) = tls { #[cfg(target_arch = "x86_64")] { - use litebox::platform::RawConstPointer as _; self.sys_arch_prctl(ArchPrctlArg::SetFs(tls.as_usize())) .unwrap(); } @@ -1646,7 +1637,7 @@ impl Task { if let Some(child_tid_ptr) = set_child_tid { // Set the child TID if requested. - let _ = child_tid_ptr.write_at_offset(0, self.tid); + let _ = child_tid_ptr.write_at_offset::(0, self.tid); } } } @@ -1655,38 +1646,39 @@ impl Task { #[cfg(test)] mod tests { + use crate::{UserPtr, UserPtrMut}; + extern crate std; #[cfg(target_arch = "x86_64")] #[test] fn test_arch_prctl() { - use crate::{MutPtr, syscalls::tests::init_platform}; - use litebox::platform::RawConstPointer; + use crate::syscalls::tests::init_platform; use litebox_common_linux::ArchPrctlArg; let task = init_platform(None); // Save old FS base let mut old_fs_base: usize = 0; - let ptr = MutPtr::from_ptr(&raw mut old_fs_base); + let ptr = UserPtrMut::from_ptr(&raw mut old_fs_base); task.sys_arch_prctl(ArchPrctlArg::GetFs(ptr)) .expect("Failed to get FS base"); // Set new FS base let mut new_fs_base: [u8; 16] = [0; 16]; - let ptr = MutPtr::from_ptr(new_fs_base.as_mut_ptr()); + let ptr = UserPtrMut::from_ptr(new_fs_base.as_mut_ptr()); task.sys_arch_prctl(ArchPrctlArg::SetFs(ptr.as_usize())) .expect("Failed to set FS base"); // Verify new FS base let mut current_fs_base: usize = 0; - let ptr = MutPtr::from_ptr(&raw mut current_fs_base); + let ptr = UserPtrMut::from_ptr(&raw mut current_fs_base); task.sys_arch_prctl(ArchPrctlArg::GetFs(ptr)) .expect("Failed to get FS base"); assert_eq!(current_fs_base, new_fs_base.as_ptr() as usize); // Restore old FS base - let ptr: crate::MutPtr = crate::MutPtr::from_usize(old_fs_base); + let ptr: UserPtrMut = UserPtrMut::from_usize(old_fs_base); task.sys_arch_prctl(ArchPrctlArg::SetFs(ptr.as_usize())) .expect("Failed to restore FS base"); } @@ -1714,13 +1706,13 @@ mod tests { let name: &[u8] = b"litebox-test\0"; // Call prctl(PR_SET_NAME, set_buf) - let set_ptr = crate::ConstPtr::from_ptr(name.as_ptr()); + let set_ptr = UserPtr::from_ptr(name.as_ptr()); task.sys_prctl(litebox_common_linux::PrctlArg::SetName(set_ptr)) .expect("sys_prctl SetName failed"); // Prepare buffer for prctl(PR_GET_NAME, get_buf) let mut get_buf = [0u8; litebox_common_linux::TASK_COMM_LEN]; - let get_ptr = crate::MutPtr::from_ptr(get_buf.as_mut_ptr()); + let get_ptr = UserPtrMut::from_ptr(get_buf.as_mut_ptr()); task.sys_prctl(litebox_common_linux::PrctlArg::GetName(get_ptr)) .expect("sys_prctl GetName failed"); @@ -1732,13 +1724,13 @@ mod tests { // Test too long name let long_name = [b'a'; litebox_common_linux::TASK_COMM_LEN + 10]; - let long_name_ptr = crate::ConstPtr::from_ptr(long_name.as_ptr()); + let long_name_ptr = UserPtr::from_ptr(long_name.as_ptr()); task.sys_prctl(litebox_common_linux::PrctlArg::SetName(long_name_ptr)) .expect("sys_prctl SetName failed"); // Get the name again let mut get_buf = [0u8; litebox_common_linux::TASK_COMM_LEN]; - let get_ptr = crate::MutPtr::from_ptr(get_buf.as_mut_ptr()); + let get_ptr = UserPtrMut::from_ptr(get_buf.as_mut_ptr()); task.sys_prctl(litebox_common_linux::PrctlArg::GetName(get_ptr)) .expect("sys_prctl GetName failed"); assert_eq!( @@ -1774,7 +1766,7 @@ mod tests { restorer: 0, mask: SigSet::empty(), }; - let act_ptr = crate::ConstPtr::from_ptr(&raw const act); + let act_ptr = UserPtr::from_ptr(&raw const act); task.sys_rt_sigaction( Signal::SIGINT, Some(act_ptr), @@ -1801,7 +1793,7 @@ mod tests { let result = task.sys_clock_nanosleep( ClockId::Monotonic, TimerFlags::empty(), - litebox_common_linux::TimeParam::Timespec64(crate::MutPtr::from_ptr( + litebox_common_linux::TimeParam::Timespec64(UserPtrMut::from_ptr( &raw mut request, )), litebox_common_linux::TimeParam::None, @@ -1854,8 +1846,8 @@ mod tests { let result = task.sys_clock_nanosleep( ClockId::Monotonic, TimerFlags::empty(), - litebox_common_linux::TimeParam::Timespec64(crate::MutPtr::from_ptr(&raw mut request)), - litebox_common_linux::TimeParam::Timespec64(crate::MutPtr::from_ptr(&raw mut remain)), + litebox_common_linux::TimeParam::Timespec64(UserPtrMut::from_ptr(&raw mut request)), + litebox_common_linux::TimeParam::Timespec64(UserPtrMut::from_ptr(&raw mut remain)), ); let elapsed = platform.now().duration_since(&start); @@ -1908,7 +1900,7 @@ mod tests { let result = task.sys_clock_nanosleep( ClockId::Monotonic, TimerFlags::empty(), - litebox_common_linux::TimeParam::Timespec64(crate::MutPtr::from_ptr(&raw mut request)), + litebox_common_linux::TimeParam::Timespec64(UserPtrMut::from_ptr(&raw mut request)), litebox_common_linux::TimeParam::None, ); assert_eq!(result, Ok(()), "nanosleep should not have been interrupted"); @@ -1933,7 +1925,7 @@ mod tests { let block_set = SigSet::empty().with(Signal::SIGUSR1); task.sys_rt_sigprocmask( SigmaskHow::SIG_BLOCK, - Some(crate::ConstPtr::from_ptr(&raw const block_set)), + Some(UserPtr::from_ptr(&raw const block_set)), None, core::mem::size_of::(), ) @@ -1950,7 +1942,7 @@ mod tests { task.sys_rt_sigprocmask( SigmaskHow::SIG_UNBLOCK, - Some(crate::ConstPtr::from_ptr(&raw const block_set)), + Some(UserPtr::from_ptr(&raw const block_set)), None, core::mem::size_of::(), ) @@ -1986,7 +1978,7 @@ mod tests { restorer: 0, mask: SigSet::empty(), }; - let act_ptr = crate::ConstPtr::from_ptr(&raw const act); + let act_ptr = UserPtr::from_ptr(&raw const act); task.sys_rt_sigaction( Signal::SIGALRM, Some(act_ptr), @@ -2004,7 +1996,7 @@ mod tests { let result = task.sys_clock_nanosleep( ClockId::Monotonic, TimerFlags::empty(), - litebox_common_linux::TimeParam::Timespec64(crate::MutPtr::from_ptr(&raw mut request)), + litebox_common_linux::TimeParam::Timespec64(UserPtrMut::from_ptr(&raw mut request)), litebox_common_linux::TimeParam::None, ); @@ -2049,7 +2041,7 @@ mod tests { let result = task.sys_clock_nanosleep( ClockId::Monotonic, TimerFlags::empty(), - litebox_common_linux::TimeParam::Timespec64(crate::MutPtr::from_ptr( + litebox_common_linux::TimeParam::Timespec64(UserPtrMut::from_ptr( &raw mut request, )), litebox_common_linux::TimeParam::None, diff --git a/litebox_shim_linux/src/syscalls/signal/mod.rs b/litebox_shim_linux/src/syscalls/signal/mod.rs index 86e6436ac..8ff55d00c 100644 --- a/litebox_shim_linux/src/syscalls/signal/mod.rs +++ b/litebox_shim_linux/src/syscalls/signal/mod.rs @@ -12,16 +12,11 @@ use x86_64 as arch; use zerocopy::FromZeros; use crate::syscalls::process::ExitStatus; -use crate::{ConstPtr, MutPtr, ShimFS, Task}; +use crate::{ShimFS, Task, UserPtr, UserPtrMut}; use alloc::collections::vec_deque::VecDeque; use alloc::sync::Arc; use core::cell::{Cell, RefCell}; -use litebox::{ - platform::{RawConstPointer as _, RawMutPointer as _}, - shim::Exception, - sync::Mutex, - utils::ReinterpretUnsignedExt as _, -}; +use litebox::{shim::Exception, sync::Mutex, utils::ReinterpretUnsignedExt as _}; use litebox_common_linux::signal::{ MINSIGSTKSZ, NSIG, SI_KERNEL, SI_USER, SIG_DFL, SIG_IGN, SaFlags, SigAction, SigAltStack, SigSet, Siginfo, SiginfoData, SigmaskHow, Signal, SsFlags, Ucontext, @@ -392,22 +387,24 @@ impl Task { pub(crate) fn sys_rt_sigprocmask( &self, how: SigmaskHow, - set_ptr: Option>, - oldset_ptr: Option>, + set_ptr: Option>, + oldset_ptr: Option>, sigsetsize: usize, ) -> Result { if sigsetsize != core::mem::size_of::() { return Err(Errno::EINVAL); } let set = if let Some(set_ptr) = set_ptr { - Some(set_ptr.read_at_offset(0).ok_or(Errno::EFAULT)?) + Some(set_ptr.read_at_offset::(0).ok_or(Errno::EFAULT)?) } else { None }; if let Some(oldset_ptr) = oldset_ptr { let oldset = self.signals.blocked.get(); - oldset_ptr.write_at_offset(0, oldset).ok_or(Errno::EFAULT)?; + oldset_ptr + .write_at_offset::(0, oldset) + .ok_or(Errno::EFAULT)?; } if let Some(set) = set { @@ -431,8 +428,8 @@ impl Task { pub(crate) fn sys_sigaltstack( &self, - ss_ptr: Option>, - old_ss_ptr: Option>, + ss_ptr: Option>, + old_ss_ptr: Option>, ctx: &PtRegs, ) -> Result { let mut old_ss = self.signals.altstack.get(); @@ -441,13 +438,15 @@ impl Task { if is_on_stack { old_ss.flags |= SsFlags::ONSTACK; } - old_ss_ptr.write_at_offset(0, old_ss).ok_or(Errno::EFAULT)?; + old_ss_ptr + .write_at_offset::(0, old_ss) + .ok_or(Errno::EFAULT)?; } if let Some(ss_ptr) = ss_ptr { if is_on_stack { return Err(Errno::EPERM); } - let ss = ss_ptr.read_at_offset(0).ok_or(Errno::EFAULT)?; + let ss = ss_ptr.read_at_offset::(0).ok_or(Errno::EFAULT)?; self.signals.set_sigaltstack(ss)?; } Ok(0) @@ -455,8 +454,8 @@ impl Task { pub(crate) fn sys_rt_sigreturn(&self, ctx: &mut PtRegs) -> Result { let uctx_addr = arch::uctx_addr(ctx); - let uctx_ptr = ConstPtr::::from_usize(uctx_addr); - let Some(uctx) = uctx_ptr.read_at_offset(0) else { + let uctx_ptr = UserPtr::::from_usize(uctx_addr); + let Some(uctx) = uctx_ptr.read_at_offset::(0) else { self.force_signal(Signal::SIGSEGV, false); return Err(Errno::EFAULT); }; @@ -472,8 +471,8 @@ impl Task { pub(crate) fn sys_rt_sigaction( &self, signal: Signal, - act_ptr: Option>, - oldact_ptr: Option>, + act_ptr: Option>, + oldact_ptr: Option>, sigsetsize: usize, ) -> Result { if signal == Signal::SIGKILL || signal == Signal::SIGSTOP { @@ -483,7 +482,7 @@ impl Task { return Err(Errno::EINVAL); } let act = if let Some(act_ptr) = act_ptr { - Some(act_ptr.read_at_offset(0).ok_or(Errno::EFAULT)?) + Some(act_ptr.read_at_offset::(0).ok_or(Errno::EFAULT)?) } else { None }; @@ -504,7 +503,7 @@ impl Task { if let Some(oldact_ptr) = oldact_ptr { oldact_ptr - .write_at_offset(0, old_act) + .write_at_offset::(0, old_act) .ok_or(Errno::EFAULT)?; } diff --git a/litebox_shim_linux/src/syscalls/signal/x86_64.rs b/litebox_shim_linux/src/syscalls/signal/x86_64.rs index 2177dd174..a505cba59 100644 --- a/litebox_shim_linux/src/syscalls/signal/x86_64.rs +++ b/litebox_shim_linux/src/syscalls/signal/x86_64.rs @@ -1,15 +1,15 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -use crate::MutPtr; +use crate::UserPtrMut; use crate::syscalls::signal::{DeliverFault, SignalState}; use core::mem::offset_of; -use litebox::platform::{RawConstPointer as _, RawMutPointer as _}; use litebox::utils::{ReinterpretUnsignedExt as _, TruncateExt as _}; use litebox_common_linux::{ PtRegs, signal::{SaFlags, SigAction, Siginfo, Ucontext, x86_64::Sigcontext}, }; +use litebox_platform_multiplex::Platform; use zerocopy::{FromBytes, IntoBytes}; #[repr(C)] @@ -98,8 +98,10 @@ impl SignalState { siginfo: siginfo.clone(), }; - let frame_ptr = MutPtr::from_usize(frame_addr); - frame_ptr.write_at_offset(0, frame).ok_or(DeliverFault)?; + let frame_ptr = UserPtrMut::from_usize(frame_addr); + frame_ptr + .write_at_offset::(0, frame) + .ok_or(DeliverFault)?; ctx.rsp = frame_addr; ctx.rip = action.sigaction; diff --git a/litebox_shim_linux/src/syscalls/tests.rs b/litebox_shim_linux/src/syscalls/tests.rs index c65ce13a7..3113199b2 100644 --- a/litebox_shim_linux/src/syscalls/tests.rs +++ b/litebox_shim_linux/src/syscalls/tests.rs @@ -2,12 +2,11 @@ // Licensed under the MIT license. use litebox::fs::{FileSystem as _, Mode, OFlags}; -use litebox::platform::RawConstPointer as _; use litebox_common_linux::{AtFlags, EfdFlags, FcntlArg, FileDescriptorFlags, errno::Errno}; use litebox_platform_multiplex::{Platform, set_platform}; use zerocopy::FromBytes as _; -use crate::MutPtr; +use crate::UserPtrMut; extern crate std; @@ -184,7 +183,7 @@ fn test_getdent64() { let bytes_read = task .sys_getdirent64( dir_fd, - MutPtr::from_usize(buffer.as_mut_ptr() as usize), + UserPtrMut::from_usize(buffer.as_mut_ptr() as usize), buffer.len(), ) .expect("Failed to read directory entries"); @@ -266,7 +265,7 @@ fn test_getdent64() { assert_eq!( task.sys_getdirent64( dir_fd, - MutPtr::from_usize(buffer.as_mut_ptr() as usize), + UserPtrMut::from_usize(buffer.as_mut_ptr() as usize), buffer.len() ) .expect("Failed to read directory entries"), @@ -284,7 +283,7 @@ fn test_getdent64() { let bytes = task .sys_getdirent64( dir_fd, - MutPtr::from_usize(small_buffer.as_mut_ptr() as usize), + UserPtrMut::from_usize(small_buffer.as_mut_ptr() as usize), small_buffer.len(), ) .expect("Failed to read directory entries"); @@ -305,7 +304,7 @@ fn test_getdent64() { // Test 3: Invalid file descriptor let result = task.sys_getdirent64( -1, - MutPtr::from_usize(buffer.as_mut_ptr() as usize), + UserPtrMut::from_usize(buffer.as_mut_ptr() as usize), buffer.len(), ); assert_eq!( @@ -322,7 +321,7 @@ fn test_getdent64() { let result = task.sys_getdirent64( file1_fd, - MutPtr::from_usize(buffer.as_mut_ptr() as usize), + UserPtrMut::from_usize(buffer.as_mut_ptr() as usize), buffer.len(), ); assert_eq!( @@ -333,7 +332,11 @@ fn test_getdent64() { task.sys_close(file1_fd).expect("Failed to close file"); // Test 5: Zero-length buffer - let result = task.sys_getdirent64(dir_fd, MutPtr::from_usize(buffer.as_mut_ptr() as usize), 0); + let result = task.sys_getdirent64( + dir_fd, + UserPtrMut::from_usize(buffer.as_mut_ptr() as usize), + 0, + ); assert_eq!( result, Err(Errno::EINVAL), @@ -357,7 +360,7 @@ fn test_getdent64() { let bytes_read = task .sys_getdirent64( dir_fd2, - MutPtr::from_usize(chunk_buffer.as_mut_ptr() as usize), + UserPtrMut::from_usize(chunk_buffer.as_mut_ptr() as usize), chunk_buffer.len(), ) .expect("Failed to read directory chunk"); diff --git a/litebox_shim_linux/src/syscalls/unix.rs b/litebox_shim_linux/src/syscalls/unix.rs index 5ae3222bb..9abfca993 100644 --- a/litebox_shim_linux/src/syscalls/unix.rs +++ b/litebox_shim_linux/src/syscalls/unix.rs @@ -31,7 +31,7 @@ use litebox_common_linux::{ }; use crate::{ - ConstPtr, FileFd, GlobalState, MutPtr, ShimFS, Task, + FileFd, GlobalState, ShimFS, Task, UserPtr, UserPtrMut, channel::{Channel, ReadEnd, WriteEnd}, syscalls::net::{SocketOptionValue, SocketOptions}, }; @@ -1464,7 +1464,7 @@ impl UnixSocket { &self, global: &GlobalState, optname: SocketOptionName, - optval: ConstPtr, + optval: UserPtr, optlen: usize, ) -> Result<(), Errno> { match global.setsockopt_common(optname, optval, optlen, |so, value| { @@ -1523,7 +1523,7 @@ impl UnixSocket { &self, global: &GlobalState, optname: SocketOptionName, - optval: MutPtr, + optval: UserPtrMut, len: u32, ) -> Result { match global.getsockopt_common(optname, optval, len, |sopt| match sopt { diff --git a/litebox_shim_optee/src/syscalls/mm.rs b/litebox_shim_optee/src/syscalls/mm.rs index 116421b8f..2263e68c6 100644 --- a/litebox_shim_optee/src/syscalls/mm.rs +++ b/litebox_shim_optee/src/syscalls/mm.rs @@ -4,9 +4,9 @@ //! Implementation of memory management related syscalls, eg., `mmap`, `munmap`, etc. use litebox::mm::linux::{MappingError, PAGE_SIZE}; -use litebox_common_linux::{MapFlags, ProtFlags, errno::Errno}; +use litebox_common_linux::{MapFlags, ProtFlags, errno::Errno, user_pointers::UserPtrMut}; -use crate::{Task, UserMutPtr}; +use crate::{Platform, Task, UserMutPtr}; #[inline] fn align_up(addr: usize, align: usize) -> Option { @@ -33,6 +33,7 @@ impl Task { false, op, ) + .map(UserPtrMut::to_platform_ptr::) } /// Handle syscall `mmap` @@ -92,7 +93,11 @@ impl Task { /// Handle syscall `munmap` pub(crate) fn sys_munmap(&self, addr: UserMutPtr, len: usize) -> Result<(), Errno> { let pm = &self.global.pm; - litebox_common_linux::mm::sys_munmap(pm, addr, len) + litebox_common_linux::mm::sys_munmap( + pm, + UserPtrMut::from_platform_ptr::(addr), + len, + ) } /// Handle syscall `mprotect` @@ -104,6 +109,11 @@ impl Task { prot: ProtFlags, ) -> Result<(), Errno> { let pm = &self.global.pm; - litebox_common_linux::mm::sys_mprotect(pm, addr, len, prot) + litebox_common_linux::mm::sys_mprotect( + pm, + UserPtrMut::from_platform_ptr::(addr), + len, + prot, + ) } }