mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
Prefer /dev/userfaultfd (Linux 6.1+) over the userfaultfd(2) syscall for obtaining userfaultfd file descriptors. The device path bypasses the capable(CAP_SYS_PTRACE) and vm.unprivileged_userfaultfd sysctl checks that block the syscall in user-namespaced containers, using file permissions instead. Falls back to the syscall on older kernels or when the device node does not exist. Signed-off-by: Roberto Campesato <render@metalabs.org> Assisted-by: Claude:claude-opus-4-6
43 lines
2.0 KiB
Rust
43 lines
2.0 KiB
Rust
// Copyright © 2026 Cloud Hypervisor Authors
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// See include/uapi/linux/userfaultfd.h in the kernel code.
|
|
pub const UFFDIO_API: u64 = 0xc018_aa3f; // _IOWR(0xAA, 0x3F, struct uffdio_api)
|
|
pub const UFFDIO_REGISTER: u64 = 0xc020_aa00; // _IOWR(0xAA, 0x00, struct uffdio_register)
|
|
pub const UFFDIO_COPY: u64 = 0xc028_aa03; // _IOWR(0xAA, 0x03, struct uffdio_copy)
|
|
pub const UFFDIO_WAKE: u64 = 0x8010_aa02; // _IOR(0xAA, 0x02, struct uffdio_range)
|
|
|
|
// Validate ioctl encoding against the _IO{R,W,WR}(type, nr, size) formula so
|
|
// transposed direction bits or sizes are caught at compile time.
|
|
const fn ioctl_ioc(dir: u64, typ: u64, nr: u64, size: u64) -> u64 {
|
|
(dir << 30) | (size << 16) | (typ << 8) | nr
|
|
}
|
|
const IOC_READ: u64 = 2;
|
|
const IOC_READWRITE: u64 = 3;
|
|
const _: () = assert!(UFFDIO_API == ioctl_ioc(IOC_READWRITE, 0xAA, 0x3F, 24));
|
|
const _: () = assert!(UFFDIO_REGISTER == ioctl_ioc(IOC_READWRITE, 0xAA, 0x00, 32));
|
|
const _: () = assert!(UFFDIO_COPY == ioctl_ioc(IOC_READWRITE, 0xAA, 0x03, 40));
|
|
const _: () = assert!(UFFDIO_WAKE == ioctl_ioc(IOC_READ, 0xAA, 0x02, 16));
|
|
|
|
// Seccomp compares these as Dword (u32); ensure they fit.
|
|
const _: () = assert!(UFFDIO_API <= u32::MAX as u64);
|
|
const _: () = assert!(UFFDIO_REGISTER <= u32::MAX as u64);
|
|
const _: () = assert!(UFFDIO_COPY <= u32::MAX as u64);
|
|
const _: () = assert!(UFFDIO_WAKE <= u32::MAX as u64);
|
|
|
|
// /dev/userfaultfd ioctl: _IO(0xAA, 0x00)
|
|
pub const USERFAULTFD_IOC_NEW: u64 = 0x0000_AA00;
|
|
const _: () = assert!(USERFAULTFD_IOC_NEW == ioctl_ioc(0, 0xAA, 0x00, 0));
|
|
const _: () = assert!(USERFAULTFD_IOC_NEW <= u32::MAX as u64);
|
|
|
|
pub const UFFD_API: u64 = 0xAA;
|
|
pub const UFFDIO_REGISTER_MODE_MISSING: u64 = 1;
|
|
pub const UFFD_EVENT_PAGEFAULT: u8 = 0x12;
|
|
pub const UFFD_FEATURE_MISSING_HUGETLBFS: u64 = 1 << 4;
|
|
pub const UFFD_FEATURE_MISSING_SHMEM: u64 = 1 << 5;
|
|
|
|
const _UFFDIO_COPY: u64 = 0x03;
|
|
const _UFFDIO_WAKE: u64 = 0x02;
|
|
pub const UFFD_API_RANGE_IOCTLS_BASIC: u64 = (1 << _UFFDIO_WAKE) | (1 << _UFFDIO_COPY);
|