blob: 36e01338beeffd991e7149d8e8f7461b6e7c88da [file] [edit]
// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use starnix_core::security;
use starnix_core::task::CurrentTask;
use starnix_core::vfs::{FdFlags, FdNumber};
use starnix_logging::track_stub;
use starnix_sync::{Locked, Unlocked};
use starnix_uapi::auth::CAP_SYS_PTRACE;
use starnix_uapi::errors::Errno;
use starnix_uapi::open_flags::OpenFlags;
use starnix_uapi::{O_CLOEXEC, O_NONBLOCK, UFFD_USER_MODE_ONLY, error};
use crate::userfault_file::UserFaultFile;
pub fn sys_userfaultfd(
locked: &mut Locked<Unlocked>,
current_task: &CurrentTask,
raw_flags: u32,
) -> Result<FdNumber, Errno> {
let unknown_flags = raw_flags & !(O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY);
if unknown_flags != 0 {
return error!(EINVAL, format!("unknown flags provided: {unknown_flags:x?}"));
}
let mut open_flags = OpenFlags::empty();
if raw_flags & O_NONBLOCK != 0 {
open_flags |= OpenFlags::NONBLOCK;
}
if raw_flags & O_CLOEXEC != 0 {
open_flags |= OpenFlags::CLOEXEC;
}
let fd_flags = if raw_flags & O_CLOEXEC != 0 {
FdFlags::CLOEXEC
} else {
track_stub!(TODO("https://fxbug.dev/297375964"), "userfaultfds that survive exec()");
return error!(ENOSYS);
};
let user_mode_only = raw_flags & UFFD_USER_MODE_ONLY != 0;
if !user_mode_only {
security::check_task_capable(current_task, CAP_SYS_PTRACE)?;
}
let uff_handle = UserFaultFile::new(locked, current_task, open_flags, user_mode_only)?;
current_task.add_file(locked, uff_handle, fd_flags)
}
pub use sys_userfaultfd as sys_arch32_userfaultfd;