Skip to content

rawsys_linux is a minimal library providing raw-level system call interfaces for Linux. It offers direct access to Linux syscalls using inline assembly, with per-ISA customization and support for multiple kernel versions.

License

Notifications You must be signed in to change notification settings

sonjaehyuk/rawsys-linux

 
 

Repository files navigation

rawsys-linux

Crates.io docs.rs Rust 2024 License

README.ko.md

Call the Linux kernel directly without libc.

This is a low-level library to enumerate and invoke raw Linux system calls. Key changes are summarized in CHANGELOG.md. Highlights in v1.0.0:

  • Raw call number types are now fixed-width to the architecture (u32/u64) and exposed via the SyscallWord alias.
  • Migrated to Rust 2024 edition and reduced compiler warnings.
  • Kernel version tables can be selected at build time via features.

Introduction

rawsys-linux exposes:

  • A Sysno enum per architecture with syscall IDs and names.
  • Inlinable raw syscall functions for several architectures.
  • Errno, SysnoSet, and SysnoMap utilities for ergonomic and fast lookup.

Installation

Using a Git dependency:

[dependencies]
rawsys-linux = { git = "https://github.com/sonjaehyuk/rawsys-linux" }

In code, rawsys-linux is imported as rawsys_linux (hyphen → underscore):

use rawsys_linux::{syscall, Sysno, SyscallWord};

Quick Start

Unsafe by nature: invoking syscalls bypasses libc. Use with care.

use rawsys_linux::{syscall, Sysno, SyscallWord};

fn main() {
  unsafe {
    // openat(AT_FDCWD, "/dev/null", O_RDONLY, 0)
    let fd = syscall(Sysno::openat, &rawsys_linux::SyscallArgs::from(&[
      (-100isize) as SyscallWord,
      "/dev/null\0".as_ptr() as SyscallWord,
      0,
      0,
    ]))?;

    // close(fd)
    let _ = syscall(Sysno::close, &rawsys_linux::SyscallArgs::from(&[fd]))?;
  }
}

Macro form is also available:

use rawsys_linux::syscall;

fn main() {
  unsafe {
    let tid = syscall!(Sysno::gettid)?;
    let _ = tid;
  } 
}

Features & Configuration

Default features: std, serde.

Additional features:

  • full: Enables all optional features.
  • all: Exposes syscall tables for all architectures.
  • Per-architecture: aarch64, arm, loongarch64, mips, mips64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, x86, x86_64.
  • Kernel versions: default_kernel_5_4, default_kernel_5_10, default_kernel_5_15, default_kernel_6_1, default_kernel_6_6, default_kernel_6_10, default_kernel_6_12.

kernel versions selects the kernel version exposed by default, not the available kernels. All versions are available via modules.

no_std

Disable default features and choose exactly one kernel version:

[dependencies]
rawsys-linux = { git = "https://github.com/sonjaehyuk/rawsys-linux", default-features = false, features = ["default_kernel_6_12", "serde"] }

Notes:

  • Syscall invocation works without std. Error handling (Errno) and internals are no_std-friendly.
  • Some architectures require nightly due to inline assembly constraints (see Architecture Support).

Kernel Version Selection (mutually exclusive)

Pick exactly one kernel version to lock syscall tables. If none is chosen, the latest (default_kernel_6_12) is used by default.

cargo build --features "default_kernel_5_10"
cargo build --features "default_kernel_6_6 aarch64"

Enabling multiple default_kernel_* features simultaneously will cause duplicate symbol errors. Choose exactly one.

Serde

Sysno, SysnoSet, and related types implement Serde. To disable Serde, turn off default features and opt-in only what you need.

[dependencies]
rawsys-linux = { git = "https://github.com/sonjaehyuk/rawsys-linux", default-features = false, features = ["default_kernel_6_12"] }

Build Examples

# x86-64 target with kernel 6.1 tables
cargo build --features "default_kernel_6_1"

# Cross-compile: expose aarch64 tables + kernel 5.15
cargo build --features "aarch64 default_kernel_5_15"

# All architectures + kernel 6.12
cargo build --features "all default_kernel_6_12"

Architecture Support

The Enum column means that a Sysno enum is implemented for this architecture.

The Invoke column means that syscalls can be invoked for this architecture.

The Stable Rust? column means that syscall invocation only requires stable Rust. Some architectures require nightly Rust because inline assembly is not yet stabilized for all architectures.

Arch Enum Invoke Stable Rust?
arm* Yes ✅
aarch64 Yes ✅
mips No ❌
mips64 No ❌
powerpc No ❌
powerpc64 No ❌
riscv32 ❌† No ❌
riscv64 Yes ✅
s390x No ❌
sparc N/A
sparc64 N/A
x86 Yes ✅
x86_64 Yes ✅

* Includes ARM thumb mode support.

† Rust does not support riscv32 Linux targets, but syscall functions are implemented if you're feeling adventurous.

Updating the syscall list

Updates are pulled from the Linux source tree (tables or unistd headers).

  • Generate syscalls for a specific version:
    • cd syscalls-gen && cargo run -- --version v6.10
  • Generate multiple versions and/or specific archs:
    • cd syscalls-gen && cargo run -- --versions v6.8,v6.10 --archs x86_64,aarch64

This will add files under src/arch/<arch>/vX_Y.rs (e.g., src/arch/x86_64/v6_10.rs). When adding a new version, declare the module in each architecture’s mod.rs and update the selection logic as needed.

About contributing

Check out CONTRIBUTING.md

License & Acknowledgements

  • License: BSD-2-Clause
  • Acknowledgements: Thanks to Jason White’s original syscalls project.

About

rawsys_linux is a minimal library providing raw-level system call interfaces for Linux. It offers direct access to Linux syscalls using inline assembly, with per-ISA customization and support for multiple kernel versions.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Rust 100.0%