From 2f2e76c0cad893af36b574153c108eb491b39930 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sat, 14 Oct 2023 14:56:40 +0200 Subject: [PATCH] Inform SYS_SENDFD scheme if the fd was exclusive. --- src/scheme/mod.rs | 4 ++-- src/scheme/user.rs | 6 +++--- src/syscall/fs.rs | 51 ++++++++++++++++------------------------------ syscall | 2 +- 4 files changed, 24 insertions(+), 39 deletions(-) diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index 6d6acd68ef..e277457564 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -13,7 +13,7 @@ use alloc::{ sync::Arc, vec::Vec, }; -use syscall::{CallerCtx, MunmapFlags}; +use syscall::{CallerCtx, MunmapFlags, SendFdFlags}; use core::sync::atomic::AtomicUsize; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; @@ -342,7 +342,7 @@ pub trait KernelScheme: Scheme + Send + Sync + 'static { Err(Error::new(EBADF)) } - fn ksendfd(&self, id: usize, desc: Arc>, flags: usize, arg: u64) -> Result { + fn ksendfd(&self, id: usize, desc: Arc>, flags: SendFdFlags, arg: u64) -> Result { Err(Error::new(EOPNOTSUPP)) } diff --git a/src/scheme/user.rs b/src/scheme/user.rs index 944c7a444e..11552f7917 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -3,7 +3,7 @@ use alloc::sync::{Arc, Weak}; use alloc::boxed::Box; use alloc::collections::BTreeMap; use alloc::vec::Vec; -use syscall::{SKMSG_FRETURNFD, CallerCtx, SKMSG_PROVIDE_MMAP, MAP_FIXED_NOREPLACE, MunmapFlags, SKMSG_FOBTAINFD, FobtainFdFlags}; +use syscall::{SKMSG_FRETURNFD, CallerCtx, SKMSG_PROVIDE_MMAP, MAP_FIXED_NOREPLACE, MunmapFlags, SKMSG_FOBTAINFD, FobtainFdFlags, SendFdFlags}; use core::mem::size_of; use core::num::NonZeroUsize; use core::sync::atomic::{AtomicBool, Ordering}; @@ -968,14 +968,14 @@ impl KernelScheme for UserScheme { Response::Fd(_) => Err(Error::new(EIO)), } } - fn ksendfd(&self, number: usize, desc: Arc>, flags: usize, arg: u64) -> Result { + fn ksendfd(&self, number: usize, desc: Arc>, flags: SendFdFlags, arg: u64) -> Result { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; let res = inner.call_extended(CallerCtx { pid: context::context_id().into(), uid: arg as u32, gid: (arg >> 32) as u32, - }, Some(desc), [SYS_SENDFD, number, flags, 0])?; + }, Some(desc), [SYS_SENDFD, number, flags.bits(), 0])?; match res { Response::Regular(res) => Ok(res), diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs index 80c0fef8ef..0403f41269 100644 --- a/src/syscall/fs.rs +++ b/src/syscall/fs.rs @@ -15,37 +15,6 @@ use crate::syscall::scheme::CallerCtx; use super::usercopy::{UserSlice, UserSliceWo, UserSliceRo}; -/*pub fn file_op(a: usize, fd: FileHandle, c: usize, d: usize) -> Result { - let (file, pid, uid, gid) = { - let contexts = context::contexts(); - let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; - let context = context_lock.read(); - let file = context.get_file(fd).ok_or(Error::new(EBADF))?; - (file, context.id, context.euid, context.egid) - }; - - let scheme = { - let schemes = scheme::schemes(); - let scheme = schemes.get(file.description.read().scheme).ok_or(Error::new(EBADF))?; - Arc::clone(scheme) - }; - - let mut packet = Packet { - id: 0, - pid: pid.into(), - uid, - gid, - a, - b: file.description.read().number, - c, - d - }; - - scheme.handle(&mut packet); - - Error::demux(packet.a) -}*/ - pub fn file_op_generic(fd: FileHandle, op: impl FnOnce(&dyn KernelScheme, &CallerCtx, usize) -> Result) -> Result { file_op_generic_ext(fd, |s, _, ctx, no| op(s, ctx, no)) } @@ -235,7 +204,9 @@ pub fn dup2(fd: FileHandle, new_fd: FileHandle, buf: UserSliceRo) -> Result Result { +pub fn sendfd(socket: FileHandle, fd: FileHandle, flags_raw: usize, arg: u64) -> Result { + let requested_flags = SendFdFlags::from_bits(flags_raw).ok_or(Error::new(EINVAL))?; + let (scheme, number, desc_to_send) = { let current_lock = context::current()?; let current = current_lock.read(); @@ -249,7 +220,21 @@ pub fn sendfd(socket: FileHandle, fd: FileHandle, flags: usize, arg: u64) -> Res (scheme, number, current.remove_file(fd).ok_or(Error::new(EBADF))?.description) }; - scheme.ksendfd(number, desc_to_send, flags, arg) + + // Inform the scheme whether there are still references to the file description to be sent, + // either in the current file table or in other file tables, regardless of whether EXCLUSIVE is + // requested. + + let flags_to_scheme = if Arc::strong_count(&desc_to_send) == 1 { + SendFdFlags::EXCLUSIVE + } else { + if requested_flags.contains(SendFdFlags::EXCLUSIVE) { + return Err(Error::new(EBUSY)); + } + SendFdFlags::empty() + }; + + scheme.ksendfd(number, desc_to_send, flags_to_scheme, arg) } /// File descriptor controls diff --git a/syscall b/syscall index 0200e818a4..bbbf2a97c5 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit 0200e818a4ba752c1869be9718eb7f090c19d65c +Subproject commit bbbf2a97c55ea9d4a5b5d0c465f1871df745eb82