cargo : linux-raw-sys @ 0.12.1
PE Patrick Elsen signed 2026-05-28 published 2026-05-28

Claims

has-binarieshas-build-exechas-fuzz-testshas-install-exechas-integration-testshas-property-testshas-unit-testsimpl-algorithmimpl-concurrencyimpl-cryptoimpl-datastructureimpl-interpreterimpl-jitimpl-parserimpl-protocolis-benignuses-concurrencyuses-cryptouses-environmentuses-execuses-filesystemuses-interpreteruses-jituses-networkuses-unsafe

Summary

linux-raw-sys 0.12.1 ships pre-generated rust-bindgen UAPI bindings for ~20 Linux architectures; the published crate is byte-equivalent to the tagged VCS source. No build-time execution, no binaries, no I/O. Unsafe evaluation claims are scoped out due to ~480K LOC of machine-generated code; five manually-written unsafe fns in lib.rs are the only hand-authored unsafe code. No findings.

Report

Subject

linux-raw-sys 0.12.1 publishes pre-generated bindgen bindings for the Linux kernel UAPI headers. Each supported architecture (arm, aarch64, csky, hexagon, loongarch64, m68k, mips, mips32r6, mips32r6, mips64, mips64r6, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, x32, x86, x86_64) contributes one .rs file per enabled feature flag (general, errno, net, io_uring, etc.), generated by rust-bindgen 0.72.1. The crate is the kernel-type layer that rustix's linux_raw syscall backend depends on.

Methodology

Audited using openvet, ripgrep, diff, and git. Model: claude-sonnet-4-6.

VCS byte-equivalence was checked with diff -rq contents vcs, excluding .cargo_vcs_info.json, Cargo.toml.orig, and Cargo.lock. The only difference was Cargo.toml (cargo normalisation), confirming the published crate matches the tagged source.

lib.rs (2061 lines) was read in full. The architecture modules consist of ~480K LOC of bindgen output; instead of reading each file, two representative modules were sampled (x86_64/general.rs and aarch64/errno.rs) and grep surveys were run across the full tree for unsafe, FFI, network, filesystem, exec, env, crypto, concurrency, and test patterns.

Scope. Due to the volume of this crate (~480K LOC, ~6,837 unsafe occurrences across hundreds of machine-generated files), the following claims were not evaluated and are left unasserted; they must not be read as either satisfied or violated: unsafe-safe, unsafe-documented, unsafe-minimal. This audit verifies supply-chain integrity (VCS byte-equivalence), the capability surface (uses-*), build and install-time execution, and dependency enumeration.

Results

The published crate is byte-equivalent to the VCS source at the tagged commit. No source-file divergence was found. No binary files are present in contents/, confirming has-binaries. The manifest sets build = false and no build.rs exists, so has-build-exec is false. No [[bin]] table and no install hooks are declared, so has-install-exec is false.

The generated modules contain only type aliases, integer constants, #[repr(C)] structs, and function-pointer type definitions; they implement no algorithms, protocols, parsers, concurrency primitives, cryptography, interpreters, or data structures, so impl-algorithm, impl-protocol, impl-parser, impl-concurrency, impl-crypto, impl-interpreter, impl-jit, and impl-datastructure are all false. Grep surveys confirmed zero network, filesystem, process-exec, environment, crypto, or concurrency API use, so uses-network, uses-filesystem, uses-exec, uses-environment, uses-crypto, uses-concurrency, uses-interpreter, and uses-jit are all false. uses-unsafe is true: the crate contains ~6,837 unsafe occurrences. These arise from three sources: (1) extern "C" function-pointer type definitions in the bindgen output (93 occurrences), (2) five manually-written unsafe fns in lib.rs (cmsg_macros module for CMSG_* socket control-message helpers, and select_macros for FD_*), and (3) a single transmute in signal_macros::sig_ign() that produces the SIG_IGN function pointer.

Unit tests in lib.rs use static_assertions to verify that the manually-defined ctypes aliases match libc's types when compiled for a no_std target. has-unit-tests is therefore true. has-integration-tests, has-fuzz-tests, and has-property-tests are false; no integration, fuzz, or property-based tests are present.

No obfuscated code, base64 blobs, network endpoints, telemetry, or suspicious sinks were found. is-benign is true.

The sole runtime dependency is rustc-std-workspace-core (optional, activated by the rustc-dep-of-std feature). Dev dependencies are libc and static_assertions, used only in the test module.

Conclusion

linux-raw-sys 0.12.1 is bindgen-generated UAPI bindings. The published crate matches the tagged VCS source byte-for-byte (modulo cargo manifest normalisation). No build-time execution, no install hooks, no binaries, no I/O. The five manually-written unsafe functions in lib.rs implement POSIX socket (CMSG_*) and fd-set (FD_*) macros that are inherently pointer-based; the provenance concern in CMSG_NXTHDR is acknowledged in a source comment. The unsafe evaluation claims are scoped out due to the scale of machine-generated code and must not be treated as asserted.

Findings

No findings.

Annotations(1)

src/lib.rs

src/lib.rs, line 110-215

pub mod cmsg_macros {
    use crate::ctypes::{c_long, c_uchar, c_uint};
    use crate::net::{cmsghdr, msghdr};
    use core::mem::size_of;
    use core::ptr;

    pub const unsafe fn CMSG_ALIGN(len: c_uint) -> c_uint {
        let c_long_size = size_of::<c_long>() as c_uint;
        (len + c_long_size - 1) & !(c_long_size - 1)
    }

    pub const unsafe fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar {
        (cmsg as *mut c_uchar).add(size_of::<cmsghdr>())
    }

    pub const unsafe fn CMSG_SPACE(len: c_uint) -> c_uint {
        size_of::<cmsghdr>() as c_uint + CMSG_ALIGN(len)
    }

    pub const unsafe fn CMSG_LEN(len: c_uint) -> c_uint {
        size_of::<cmsghdr>() as c_uint + len
    }

    pub const unsafe fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr {
        if (*mhdr).msg_controllen < size_of::<cmsghdr>() as _ {
            return ptr::null_mut();
        }

        (*mhdr).msg_control as *mut cmsghdr
    }

    pub unsafe fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr {
        // We convert from raw pointers to usize here, which may not be sound in a
        // future version of Rust. Once the provenance rules are set in stone,
        // it will be a good idea to give this function a once-over.

        let cmsg_len = (*cmsg).cmsg_len;
        let next_cmsg = (cmsg as *mut u8).add(CMSG_ALIGN(cmsg_len as _) as usize) as *mut cmsghdr;
        let max = ((*mhdr).msg_control as usize) + ((*mhdr).msg_controllen as usize);

        if cmsg_len < size_of::<cmsghdr>() as _ {
            return ptr::null_mut();
        }

        if next_cmsg.add(1) as usize > max
            || next_cmsg as usize + CMSG_ALIGN((*next_cmsg).cmsg_len as _) as usize > max
        {
            return ptr::null_mut();
        }

        next_cmsg
    }
}

#[cfg(feature = "general")]
pub mod select_macros {
    use crate::ctypes::c_int;
    use crate::general::__kernel_fd_set;
    use core::mem::size_of;

    pub unsafe fn FD_CLR(fd: c_int, set: *mut __kernel_fd_set) {
        let bytes = set as *mut u8;
        if fd >= 0 {
            *bytes.add((fd / 8) as usize) &= !(1 << (fd % 8));
        }
    }

    pub unsafe fn FD_SET(fd: c_int, set: *mut __kernel_fd_set) {
        let bytes = set as *mut u8;
        if fd >= 0 {
            *bytes.add((fd / 8) as usize) |= 1 << (fd % 8);
        }
    }

    pub unsafe fn FD_ISSET(fd: c_int, set: *const __kernel_fd_set) -> bool {
        let bytes = set as *const u8;
        if fd >= 0 {
            *bytes.add((fd / 8) as usize) & (1 << (fd % 8)) != 0
        } else {
            false
        }
    }

    pub unsafe fn FD_ZERO(set: *mut __kernel_fd_set) {
        let bytes = set as *mut u8;
        core::ptr::write_bytes(bytes, 0, size_of::<__kernel_fd_set>());
    }
}

#[cfg(feature = "general")]
pub mod signal_macros {
    pub const SIG_DFL: super::general::__kernel_sighandler_t = None;

    /// Rust doesn't currently permit us to use `transmute` to convert the
    /// `SIG_IGN` value into a function pointer in a `const` initializer, so
    /// we make it a function instead.
    ///
    #[inline]
    pub const fn sig_ign() -> super::general::__kernel_sighandler_t {
        // Safety: This creates an invalid pointer, but the pointer type
        // includes `unsafe`, which covers the safety of calling it.
        Some(unsafe {
            core::mem::transmute::<usize, unsafe extern "C" fn(crate::ctypes::c_int)>(1)
        })
    }
}

The cmsg_macros, select_macros, and signal_macros modules in lib.rs contain the only hand-authored unsafe code in the crate. cmsg_macros implements POSIX CMSG_* socket control-message helpers using raw pointer arithmetic; CMSG_NXTHDR includes a comment noting the usize-from-pointer conversion may need revisiting once Rust provenance rules are finalised. select_macros implements FD_CLR, FD_SET, FD_ISSET, and FD_ZERO via byte-pointer arithmetic bounded by the fd index check (fd >= 0). signal_macros::sig_ign uses transmute to produce the SIG_IGN sentinel function pointer value (1), documented inline. Justifies uses-unsafe and is-benign.