Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
0a7b800
chore: add WRAP_PROGRESS.md
olukowski Apr 24, 2026
0f16b09
feat(syscalls): add access wrapper
olukowski Apr 24, 2026
93231de
feat(syscalls): add acct wrapper
olukowski Apr 24, 2026
6787b10
feat: add adjtimex wrap layer
olukowski Apr 24, 2026
8194fb6
feat(syscalls): wrap alarm syscall
olukowski Apr 24, 2026
479c49f
feat: add brk wrap-layer wrapper
olukowski Apr 24, 2026
7967d0c
refactor: centralize syscall wrapper result mapping
olukowski Apr 24, 2026
480f607
docs: standardize syscall wrapper docs
olukowski Apr 24, 2026
65defc1
feat(syscalls): add wrapped chdir
olukowski Apr 24, 2026
9351049
feat(syscalls): add wrapped chmod
olukowski Apr 24, 2026
7b0ea37
feat(syscalls): add chroot wrapper
olukowski Apr 24, 2026
a2d38bc
feat(syscalls): add close wrapper
olukowski Apr 24, 2026
e74c5d5
feat(syscalls): add wrapped creat syscall
olukowski Apr 24, 2026
a879255
feat(syscalls): wrap create_module
olukowski Apr 24, 2026
8eca0cd
fix: repair wrapper test builds
olukowski Apr 24, 2026
6590491
test: cover wrapper error mappings
olukowski Apr 24, 2026
5d1f9ce
test: cover named errno mappings
olukowski Apr 24, 2026
5afe32c
feat(syscalls): wrap delete_module
olukowski Apr 24, 2026
00e9edb
feat(syscalls): add dup wrapper
olukowski Apr 24, 2026
834868a
feat(syscalls): add dup2 wrapper
olukowski Apr 24, 2026
3b4a418
feat(syscalls): add execve wrap layer
olukowski Apr 24, 2026
40d721a
feat(syscalls): add wrapped exit wrapper
olukowski Apr 24, 2026
43ae3bc
feat(syscalls): wrap fchdir
olukowski Apr 24, 2026
663e2ca
feat(syscalls): add wrapped fchmod
olukowski Apr 24, 2026
b6520b2
feat(syscalls): wrap fchown16
olukowski Apr 24, 2026
2a7e74b
feat(syscalls): add wrapped fcntl API
olukowski Apr 24, 2026
d9c5c2e
feat(syscalls): add wrapped fork API
olukowski Apr 24, 2026
d366f67
feat(syscalls): add wrapped fstatfs
olukowski Apr 24, 2026
3769db5
feat(syscalls): add fsync wrapper
olukowski Apr 24, 2026
1677d37
feat(syscalls): wrap ftruncate
olukowski Apr 24, 2026
e221232
Wrap x86 get_kernel_syms
olukowski Apr 25, 2026
79f7dd1
Wrap getegid16 syscall
olukowski Apr 25, 2026
ccc1461
Mark geteuid16 wrap complete
olukowski Apr 25, 2026
96db3ed
Wrap getgid16 on x86
olukowski Apr 25, 2026
f4e20c8
Wrap x86 getgroups16
olukowski Apr 25, 2026
ed71149
Wrap getitimer syscall
olukowski Apr 25, 2026
94bf319
feat(syscalls): wrap getpgid
olukowski Apr 25, 2026
64cecbd
feat(syscalls): wrap getpgrp
olukowski Apr 25, 2026
34bdeac
feat(syscalls): wrap getpid
olukowski Apr 25, 2026
910bdc2
feat(syscalls): wrap getppid
olukowski Apr 25, 2026
16d8603
feat(syscalls): wrap getpriority
olukowski Apr 25, 2026
e480961
feat(syscalls): wrap getrlimit
olukowski Apr 25, 2026
fc66157
feat(syscalls): wrap getrusage
olukowski Apr 25, 2026
8e04dfb
feat(syscalls): wrap gettimeofday
olukowski Apr 25, 2026
19f46d4
feat(syscalls): wrap getuid16
olukowski Apr 25, 2026
42fe957
feat(syscalls): wrap idle
olukowski Apr 25, 2026
08b436d
feat(syscalls): wrap init_module
olukowski Apr 25, 2026
31022e7
feat(syscalls): wrap ioctl
olukowski Apr 25, 2026
f7887c2
feat(syscalls): wrap ioperm
olukowski Apr 25, 2026
829ec0b
feat(syscalls): wrap iopl
olukowski Apr 25, 2026
1ab45f1
feat(syscalls): wrap ipc
olukowski Apr 25, 2026
1c38ee8
feat(syscalls): wrap kill
olukowski Apr 25, 2026
6a547d9
feat(syscalls): wrap lchown16
olukowski Apr 25, 2026
3023591
feat(syscalls): wrap link
olukowski Apr 25, 2026
a154fc5
feat(syscalls): wrap lseek
olukowski Apr 25, 2026
c7334c4
feat(syscalls): wrap mknod
olukowski Apr 25, 2026
4ba61ff
feat(syscalls): wrap mkdir
olukowski Apr 25, 2026
fea0aa3
feat(syscalls): wrap mmap
olukowski Apr 25, 2026
a826797
feat(syscalls): wrap modify_ldt
olukowski Apr 25, 2026
160cc1e
feat(syscalls): wrap mount
olukowski Apr 25, 2026
4c428d0
feat(syscalls): wrap munmap
olukowski Apr 25, 2026
bf796a6
feat(syscalls): wrap newfstat
olukowski Apr 25, 2026
5b8a0b3
feat(syscalls): wrap newlstat
olukowski Apr 25, 2026
a2dd337
feat(syscalls): wrap newuname
olukowski Apr 25, 2026
d3cc067
feat(syscalls): wrap nice
olukowski Apr 25, 2026
3151309
feat(syscalls): wrap oldfstat
olukowski Apr 25, 2026
882fc50
feat(syscalls): wrap oldlstat
olukowski Apr 25, 2026
19d2f12
feat(syscalls): wrap oldolduname
olukowski Apr 25, 2026
9860ba2
feat(syscalls): wrap oldstat
olukowski Apr 25, 2026
a626118
feat(syscalls): wrap olduname
olukowski Apr 25, 2026
25e68a2
feat(syscalls): wrap open
olukowski Apr 25, 2026
70ffb0a
feat(syscalls): wrap pause
olukowski Apr 25, 2026
9f96dda
feat(syscalls): wrap pipe
olukowski Apr 25, 2026
3dda872
feat(syscalls): wrap ptrace
olukowski Apr 25, 2026
68fe5d1
feat(syscalls): wrap read
olukowski Apr 25, 2026
2c06d34
feat(syscalls): wrap readdir
olukowski Apr 25, 2026
840523f
feat(syscalls): wrap readlink
olukowski Apr 25, 2026
0eab2b6
feat(syscalls): wrap reboot
olukowski Apr 25, 2026
f233076
feat(syscalls): wrap rename
olukowski Apr 25, 2026
d96d428
feat(syscalls): wrap rmdir
olukowski Apr 25, 2026
ef67481
feat(syscalls): wrap select
olukowski Apr 25, 2026
0712363
feat(syscalls): wrap setdomainname
olukowski Apr 25, 2026
2678abe
feat(syscalls): wrap setgid16
olukowski Apr 25, 2026
22d7a15
feat(syscalls): wrap setgroups16
olukowski Apr 25, 2026
c195931
feat(syscalls): wrap sethostname
olukowski Apr 25, 2026
847fb57
feat(syscalls): wrap setitimer
olukowski Apr 25, 2026
c0b771a
feat(syscalls): wrap setpgid
olukowski Apr 25, 2026
1a7b69c
feat(syscalls): wrap setpriority
olukowski Apr 25, 2026
330ed90
feat(syscalls): wrap setregid16
olukowski Apr 25, 2026
1d1ab69
feat(syscalls): wrap setreuid16
olukowski Apr 25, 2026
728f6c2
feat(syscalls): wrap setrlimit
olukowski Apr 25, 2026
b0132a2
feat(syscalls): wrap setsid
olukowski Apr 25, 2026
0cfe1ad
feat(syscalls): wrap settimeofday
olukowski Apr 25, 2026
2edc50b
feat(syscalls): wrap setuid16
olukowski Apr 25, 2026
d1d00e8
feat(syscalls): wrap sgetmask
olukowski Apr 25, 2026
4f7a62b
feat(syscalls): wrap sigaction
olukowski Apr 25, 2026
c7ee6b2
feat(syscalls): wrap signal
olukowski Apr 25, 2026
6aba0ea
feat(syscalls): wrap sigpending
olukowski Apr 25, 2026
5726931
feat(syscalls): wrap sigprocmask
olukowski Apr 25, 2026
6077daf
feat(syscalls): wrap sigreturn
olukowski Apr 25, 2026
5986d0c
feat(syscalls): wrap sigsuspend
olukowski Apr 25, 2026
8cbdd7f
feat(syscalls): wrap socketcall
olukowski Apr 25, 2026
0b162b6
feat(syscalls): wrap ssetmask
olukowski Apr 25, 2026
4183b48
feat(syscalls): wrap stat
olukowski Apr 25, 2026
a1e00da
feat(syscalls): wrap statfs
olukowski Apr 25, 2026
7e374ae
feat(syscalls): wrap stime
olukowski Apr 25, 2026
e448aa3
feat(syscalls): wrap swapoff
olukowski Apr 25, 2026
1d3b9ce
feat(syscalls): wrap swapon
olukowski Apr 25, 2026
5052eac
feat(syscalls): wrap symlink
olukowski Apr 25, 2026
5eda8fe
feat(syscalls): wrap sync
olukowski Apr 25, 2026
32904b5
feat(syscalls): wrap sysinfo
olukowski Apr 25, 2026
f7160c2
feat(syscalls): wrap syslog
olukowski Apr 25, 2026
1b309ca
feat(syscalls): wrap time
olukowski Apr 25, 2026
56dcb2c
feat(syscalls): wrap times
olukowski Apr 25, 2026
5da2b01
feat(syscalls): wrap truncate
olukowski Apr 25, 2026
03a8aa4
feat(syscalls): wrap umask
olukowski Apr 25, 2026
1a12f28
feat(syscalls): wrap umount
olukowski Apr 25, 2026
a2401d7
feat(syscalls): wrap unlink
olukowski Apr 25, 2026
76cf1ac
feat(syscalls): wrap uselib
olukowski Apr 25, 2026
a5df756
feat(syscalls): wrap ustat
olukowski Apr 25, 2026
e33fed7
feat(syscalls): wrap utime
olukowski Apr 25, 2026
6a39a7c
feat(syscalls): wrap vhangup
olukowski Apr 25, 2026
a020c62
feat(syscalls): wrap vm86
olukowski Apr 25, 2026
bdf146c
feat(syscalls): wrap wait4
olukowski Apr 25, 2026
9d46557
feat(syscalls): wrap waitpid
olukowski Apr 25, 2026
349d41a
feat(syscalls): wrap write
olukowski Apr 25, 2026
8228e53
feat(syscalls): wrap linux 1.0 init_module
olukowski Apr 25, 2026
d66dc01
feat(syscalls): wrap linux 1.0 setup
olukowski Apr 25, 2026
22a69b6
feat(syscalls): export remaining wrapped syscalls
olukowski Apr 25, 2026
4671e32
docs(syscalls): complete wrap progress checklist
olukowski Apr 25, 2026
b14188b
test(syscalls): exclude unexercised historical control wrappers from …
olukowski Apr 25, 2026
ee72c34
fix(syscalls): preserve data-valued negative returns
olukowski Apr 25, 2026
02e9b52
fix(syscalls): surface ambiguous fcntl getown returns
olukowski Apr 25, 2026
c298c60
test: cover fcntl F_GETOWN nonnegative result
olukowski Apr 25, 2026
dc15a52
fix(syscalls): make EFAULT-only output wrappers infallible
olukowski Apr 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
239 changes: 239 additions & 0 deletions system/linux/syscalls/WRAP_PROGRESS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
# Wrap Progress

This checklist tracks the next layer above the raw Linux syscall wrappers.
The goal of this layer is to preserve the raw syscall shape while removing
the most mechanical Rust rough edges.

## Scope

The wrap layer should:

- convert raw syscall return values into `Result<T, E>`;
- use syscall-specific error enums, with an `Other(Errno)` escape hatch when
the syscall can delegate to file systems, drivers, protocols, security
modules, or other helpers with wider reachable errors;
- use shared slices for `*const T` plus length arguments;
- use mutable slices for `*mut T` plus length arguments when the kernel reads
and writes initialized elements;
- use `MaybeUninit` for output buffers or output slots that the kernel
initializes;
- use shared references for non-null single-item `*const T` arguments;
- use mutable references for non-null single-item `*mut T` arguments when the
pointed-to value must already be initialized;
- use `Option<&T>`, `Option<&mut T>`, or `Option<&mut MaybeUninit<T>>` when
null is a meaningful syscall input;
- use `&CStr` for NUL-terminated `*const Char` strings;
- stay safe whenever the wrapper removes all caller-visible memory-safety
preconditions;
- use strict-provenance APIs when converting pointers before passing raw
integer syscall arguments.

The wrap layer should not introduce ownership, buffering, retry policy, path
encoding policy, automatic descriptor closing, or broad semantic convenience.
Those belong in higher layers.

## Module Layout

The existing `sys` module remains the raw syscall layer. Its wrappers keep the
exact kernel-facing ABI shape: raw pointer arguments, raw integer return values,
and `unsafe` where the caller must uphold memory-safety preconditions.

The crate root exports the wrap layer. `lib.rs` should mirror the shape of
`sys.rs`: declare per-syscall wrapper modules and re-export each public wrapper
and its syscall-specific error type from the crate root. For example,
`celer_system_linux_syscalls::read` is the wrapped API, while
`celer_system_linux_syscalls::sys::read` is the raw API.

Architecture availability should mirror the raw layer. Top-level wrapped
modules and re-exports must use the same kind of `cfg` gates as the raw
syscalls so only syscalls available on the current target are exposed.

Historical Linux 1.0 ABI wrappers should be exposed from a top-level
`linux_1_0` module, mirroring `sys::linux_1_0`.

## Errno

The shared errno representation should be an enum. Common errno values should
be listed explicitly, and a raw variant should carry any errno value that the
crate does not list explicitly.

The raw variant should hold a `u16` value. When a raw syscall return is in the
kernel errno range `-4095..=-1`, the stored errno value is the negated kernel
return value.

Syscall-specific error enums should use explicit variants for source-verified
reachable errors. They should include an `Other(Errno)` variant when the syscall
can return delegated, object-specific, or otherwise open-ended errors.

## Done Criteria

A checked syscall means:

- the wrapper exists and is public from the wrap layer;
- each pointer argument has been classified as input, output, in/out, nullable,
or NUL-terminated string from kernel source;
- each safe/unsafe choice follows the repository unsafe rule;
- the success return type is semantic for this syscall;
- reachable direct errors are represented in a syscall-specific error type;
- delegated or object-specific errors use `Other(Errno)` unless the reachable
set is source-verified to be closed;
- tests cover success and at least one practical error path when feasible.

## Documentation

Wrapped syscall docs should document wrapper semantics, not kernel behavior.
Kernel support, historical notes, required privileges, detailed behavior,
reachable error analysis, and source references belong in `sys::*`.

Each wrapped syscall should document:

- the Rust argument conversions it provides;
- the `Ok(...)` value when it is not obvious;
- the syscall-specific error variants;
- any remaining caller-visible safety precondition;
- a link to the raw `sys::*` wrapper for kernel behavior, reachable errors,
and source references.

## Helpers

Shared conversion helpers should live in a private `helpers` module.

## Checklist

- [x] `access` - x86, x86_64
- [x] `acct`
- [x] `adjtimex`
- [x] `alarm` - x86, x86_64
- [x] `brk`
- [x] `chdir`
- [x] `chmod` - x86, x86_64
- [x] `chroot`
- [x] `close`
- [x] `creat` - x86, x86_64
- [x] `create_module` - x86
- [x] `delete_module`
- [x] `dup`
- [x] `dup2` - x86, x86_64
- [x] `execve`
- [x] `exit`
- [x] `fchdir`
- [x] `fchmod`
- [x] `fchown16` - x86
- [x] `fcntl`
- [x] `fork` - x86
- [x] `fstatfs`
- [x] `fsync`
- [x] `ftruncate`
- [x] `get_kernel_syms` - x86
- [x] `getegid16` - x86
- [x] `geteuid16` - x86
- [x] `getgid16` - x86
- [x] `getgroups16` - x86
- [x] `getitimer`
- [x] `getpgid`
- [x] `getpgrp` - x86, x86_64
- [x] `getpid`
- [x] `getppid`
- [x] `getpriority`
- [x] `getrlimit`
- [x] `getrusage`
- [x] `gettimeofday`
- [x] `getuid16` - x86
- [x] `idle` - x86
- [x] `init_module`
- [x] `ioctl`
- [x] `ioperm` - x86
- [x] `iopl` - x86
- [x] `ipc` - x86
- [x] `kill`
- [x] `lchown16` - x86
- [x] `link` - x86, x86_64
- [x] `lseek`
- [x] `mknod` - x86, x86_64
- [x] `mkdir` - x86, x86_64
- [x] `mmap`
- [x] `modify_ldt` - x86
- [x] `mount`
- [x] `munmap`
- [x] `newfstat`
- [x] `newlstat` - x86, x86_64
- [x] `newuname`
- [x] `nice` - x86
- [x] `oldfstat` - x86
- [x] `oldlstat` - x86
- [x] `oldolduname` - x86
- [x] `oldstat` - x86
- [x] `olduname` - x86
- [x] `open` - x86, x86_64
- [x] `pause` - x86, x86_64
- [x] `pipe` - x86, x86_64
- [x] `ptrace`
- [x] `read`
- [x] `readdir` - x86
- [x] `readlink` - x86, x86_64
- [x] `reboot`
- [x] `rename` - x86, x86_64
- [x] `rmdir` - x86, x86_64
- [x] `select` - x86, x86_64
- [x] `setdomainname`
- [x] `setgid16` - x86
- [x] `setgroups16` - x86
- [x] `sethostname`
- [x] `setitimer`
- [x] `setpgid`
- [x] `setpriority`
- [x] `setregid16` - x86
- [x] `setreuid16` - x86
- [x] `setrlimit`
- [x] `setsid`
- [x] `settimeofday`
- [x] `setuid16` - x86
- [x] `sgetmask` - x86
- [x] `sigaction` - x86
- [x] `signal` - x86
- [x] `sigpending` - x86
- [x] `sigprocmask` - x86
- [x] `sigreturn` - x86
- [x] `sigsuspend` - x86
- [x] `socketcall` - x86
- [x] `ssetmask` - x86
- [x] `stat` - x86, x86_64
- [x] `statfs`
- [x] `stime` - x86
- [x] `swapoff`
- [x] `swapon`
- [x] `symlink` - x86, x86_64
- [x] `sync`
- [x] `sysinfo`
- [x] `syslog`
- [x] `time` - x86, x86_64
- [x] `times`
- [x] `truncate`
- [x] `umask`
- [x] `umount`
- [x] `unlink` - x86, x86_64
- [x] `uselib` - x86
- [x] `ustat` - x86, x86_64
- [x] `utime` - x86, x86_64
- [x] `vhangup`
- [x] `vm86` - x86
- [x] `wait4`
- [x] `waitpid` - x86
- [x] `write`

## Linux 1.0 Historical Variants

These raw wrappers are currently exposed under `sys::linux_1_0` on x86. Decide
whether the wrap layer mirrors them before checking them off.

- [x] `linux_1_0::fstatfs`
- [x] `linux_1_0::ftruncate`
- [x] `linux_1_0::init_module`
- [x] `linux_1_0::newfstat`
- [x] `linux_1_0::newlstat`
- [x] `linux_1_0::setrlimit`
- [x] `linux_1_0::setup`
- [x] `linux_1_0::stat`
- [x] `linux_1_0::statfs`
- [x] `linux_1_0::sysinfo`
- [x] `linux_1_0::truncate`
102 changes: 102 additions & 0 deletions system/linux/syscalls/src/access.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use core::ffi::CStr;

use celer_system_linux_ctypes::Int;

use crate::errno::Errno;
use crate::helpers::unit_from_ret;
use crate::sys;

/// Errors returned by [`access`].
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum AccessError {
/// `EINVAL`.
Einval,
/// `ENOMEM`.
Enomem,
/// Another errno returned by delegated pathname, permission, or filesystem
/// work.
Other(Errno),
}

impl AccessError {
fn from_errno(errno: Errno) -> Self {
match errno {
Errno::Einval => Self::Einval,
Errno::Enomem => Self::Enomem,
errno => Self::Other(errno),
}
}
}

/// Check whether the calling process can access a file by pathname.
///
/// This safe wrapper takes a NUL-terminated [`CStr`] pathname and maps the raw
/// syscall return value into `Result<(), AccessError>`.
///
/// On success, returns `Ok(())` when the requested access is permitted.
///
/// See [`sys::access`] for kernel behavior, reachable errors, and source
/// references.
///
/// # Errors
/// - [`AccessError::Einval`]: `mode` contains unsupported bits.
/// - [`AccessError::Enomem`]: temporary credential allocation failed.
/// - [`AccessError::Other`]: delegated pathname, permission, or filesystem
/// error.
pub fn access(pathname: &CStr, mode: Int) -> Result<(), AccessError> {
// SAFETY: the `CStr` argument guarantees a valid, NUL-terminated
// pathname pointer for the duration of the call.
let ret = unsafe { sys::access(pathname.as_ptr(), mode) };

unit_from_ret(ret as isize, AccessError::from_errno)
}

#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use std::ffi::CString;
use std::fs::{self, File};
use std::time::{SystemTime, UNIX_EPOCH};

use crate::Errno;

use super::{AccessError, access};

fn temp_path() -> std::path::PathBuf {
let mut path = std::env::temp_dir();
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos();
path.push(format!("celer_wrap_access_{now}"));
path
}

#[test]
fn test_access_ok() {
let path = temp_path();
File::create(&path).unwrap();
let path_c = CString::new(path.as_os_str().as_encoded_bytes()).unwrap();

assert_eq!(access(path_c.as_c_str(), 0), Ok(()));

fs::remove_file(&path).unwrap();
}

#[test]
fn test_access_einval() {
let path = CString::new("/tmp").unwrap();

assert_eq!(access(path.as_c_str(), 0x8000), Err(AccessError::Einval));
}

#[test]
fn test_access_error_mapping() {
assert_eq!(AccessError::from_errno(Errno::Einval), AccessError::Einval);
assert_eq!(AccessError::from_errno(Errno::Enomem), AccessError::Enomem);
assert_eq!(
AccessError::from_errno(Errno::Enoent),
AccessError::Other(Errno::Enoent)
);
}
}
Loading