// SPDX-License-Identifier: MPL-2.0 use crate::{ fs::file_table::{FdFlags, FileDesc, get_file_fast}, prelude::*, process::{PidFile, credentials::capabilities::CapSet, posix_thread::AsPosixThread}, syscall::SyscallReturn, }; pub fn sys_pidfd_getfd( pidfd: FileDesc, targetfd: FileDesc, flags: u32, ctx: &Context, ) -> Result { // The `flags` argument is reserved for future use. Currently, it must be specified as 0. if flags != 0 { return_errno_with_message!(Errno::EINVAL, "invalid flags"); } debug!( "pidfd_getfd: pidfd={}, targetfd={}, flags={}", pidfd, targetfd, flags ); let mut file_table = ctx.thread_local.borrow_file_table_mut(); let file = get_file_fast!(&mut file_table, pidfd); let Some(pid_file) = file.downcast_ref::() else { return_errno_with_message!(Errno::EBADF, "the file is not a PID file"); }; let process = pid_file .process_opt() .ok_or_else(|| Error::with_message(Errno::ESRCH, "the target process has been reaped"))?; // The calling process should have PTRACE_MODE_ATTACH_REALCREDS permissions (see ptrace(2)) // over the process referred to by `pidfd`. // Currently, this is implemented as requiring the calling process to have the // CAP_SYS_PTRACE capability, which is stricter. // TODO: Implement appropriate PTRACE_MODE_ATTACH_REALCREDS permission check. if process .user_ns() .lock() .check_cap(CapSet::SYS_PTRACE, ctx.posix_thread) .is_err() { return_errno_with_message!( Errno::EPERM, "the calling process does not have the required permissions" ); } let main_thread = process.main_thread(); // Get the file description corresponding to to the file descriptor `targetfd` in the process // referred to by the PID file. let target_file_table = main_thread.as_posix_thread().unwrap().file_table(); let target_file = target_file_table .lock() .as_ref() .ok_or_else(|| Error::with_message(Errno::ESRCH, "the target process has exited"))? .read() .get_file(targetfd)? .clone(); // Duplicate the file descriptor into the caller's file descriptor table. let new_fd = { let mut file_table_locked = file_table.unwrap().write(); file_table_locked.insert(target_file, FdFlags::CLOEXEC) }; Ok(SyscallReturn::Return(new_fd as _)) }