WIP: Allow listing address space grants again.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use syscall::GrantFlags;
|
||||
use core::cmp;
|
||||
use core::fmt::Debug;
|
||||
use core::num::NonZeroUsize;
|
||||
@@ -1063,6 +1064,45 @@ impl GrantInfo {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub fn grant_flags(&self) -> GrantFlags {
|
||||
let mut flags = GrantFlags::empty();
|
||||
// TODO: has_read
|
||||
flags.set(GrantFlags::GRANT_READ, true);
|
||||
|
||||
flags.set(GrantFlags::GRANT_WRITE, self.flags.has_write());
|
||||
flags.set(GrantFlags::GRANT_EXEC, self.flags.has_execute());
|
||||
|
||||
// TODO: Set GRANT_LAZY
|
||||
|
||||
match self.provider {
|
||||
Provider::External { is_pinned_userscheme_borrow, .. } => {
|
||||
flags.set(GrantFlags::GRANT_PINNED, is_pinned_userscheme_borrow);
|
||||
flags |= GrantFlags::GRANT_SHARED;
|
||||
}
|
||||
Provider::Allocated { ref cow_file_ref } => {
|
||||
// !GRANT_SHARED is equivalent to "GRANT_PRIVATE"
|
||||
flags.set(GrantFlags::GRANT_SCHEME, cow_file_ref.is_some());
|
||||
}
|
||||
Provider::PhysBorrowed { is_pinned_userscheme_borrow, .. } => {
|
||||
flags |= GrantFlags::GRANT_SHARED | GrantFlags::GRANT_PHYS;
|
||||
flags.set(GrantFlags::GRANT_PINNED, is_pinned_userscheme_borrow);
|
||||
}
|
||||
Provider::FmapBorrowed { .. } => {
|
||||
flags |= GrantFlags::GRANT_SHARED | GrantFlags::GRANT_SCHEME;
|
||||
}
|
||||
}
|
||||
|
||||
flags
|
||||
}
|
||||
pub fn file_ref(&self) -> Option<&GrantFileRef> {
|
||||
// TODO: This would be bad for PhysBorrowed head/tail buffers, but otherwise the physical
|
||||
// base address could be included in offset, for PhysBorrowed.
|
||||
if let Provider::FmapBorrowed { ref file_ref } | Provider::Allocated { cow_file_ref: Some(ref file_ref) } = self.provider {
|
||||
Some(file_ref)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for GrantInfo {
|
||||
|
||||
+51
-3
@@ -8,10 +8,10 @@ use crate::{
|
||||
FloatRegisters,
|
||||
IntRegisters,
|
||||
EnvRegisters,
|
||||
data::{Map, PtraceEvent, SigAction, Stat},
|
||||
data::{GrantDesc, Map, PtraceEvent, SigAction, Stat},
|
||||
error::*,
|
||||
flag::*,
|
||||
scheme::{calc_seek_offset_usize, Scheme},
|
||||
scheme::{CallerCtx, calc_seek_offset_usize, Scheme},
|
||||
self, usercopy::{UserSliceWo, UserSliceRo},
|
||||
},
|
||||
};
|
||||
@@ -23,7 +23,6 @@ use alloc::{
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
use ::syscall::CallerCtx;
|
||||
use core::{
|
||||
mem,
|
||||
slice,
|
||||
@@ -806,6 +805,39 @@ impl KernelScheme for ProcScheme {
|
||||
// Return read events
|
||||
Ok(read * mem::size_of::<PtraceEvent>())
|
||||
}
|
||||
Operation::AddrSpace { ref addrspace } => {
|
||||
let OperationData::Offset(orig_offset) = self.handles.read().get(&id).ok_or(Error::new(EBADF))?.data else {
|
||||
return Err(Error::new(EBADFD));
|
||||
};
|
||||
|
||||
// Output a list of grant descriptors, sufficient to allow relibc's fork()
|
||||
// implementation to fmap MAP_SHARED grants.
|
||||
let mut grants_read = 0;
|
||||
|
||||
let mut dst = [GrantDesc::default(); 16];
|
||||
|
||||
for (dst, (grant_base, grant_info)) in dst.iter_mut().zip(addrspace.read().grants.iter().skip(orig_offset)) {
|
||||
*dst = GrantDesc {
|
||||
base: grant_base.start_address().data(),
|
||||
size: grant_info.page_count() * PAGE_SIZE,
|
||||
flags: grant_info.grant_flags(),
|
||||
// The !0 is not a sentinel value; the availability of `offset` is
|
||||
// indicated by the GRANT_SCHEME flag.
|
||||
offset: grant_info.file_ref().map_or(!0, |f| f.base_offset as u64),
|
||||
};
|
||||
grants_read += 1;
|
||||
}
|
||||
for (src, chunk) in dst.iter().take(grants_read).zip(buf.in_exact_chunks(mem::size_of::<GrantDesc>())) {
|
||||
chunk.copy_exactly(src)?;
|
||||
}
|
||||
|
||||
match self.handles.write().get_mut(&id).ok_or(Error::new(EBADF))?.data {
|
||||
OperationData::Offset(ref mut offset) => *offset = dbg!(dbg!(*offset) + dbg!(grants_read)),
|
||||
_ => return Err(Error::new(EBADFD)),
|
||||
};
|
||||
|
||||
Ok(grants_read * mem::size_of::<GrantDesc>())
|
||||
}
|
||||
Operation::Name => read_from(buf, context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.read().name.as_bytes(), &mut 0),
|
||||
Operation::Sigstack => read_from(buf, &context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.read().sigstack.unwrap_or(!0).to_ne_bytes(), &mut 0),
|
||||
Operation::Attr(attr) => {
|
||||
@@ -1131,6 +1163,7 @@ impl KernelScheme for ProcScheme {
|
||||
}
|
||||
Operation::AddrSpace { ref addrspace } => {
|
||||
let addrspace_clone = Arc::clone(addrspace);
|
||||
const GRANT_FD_PREFIX: &[u8] = b"grant-fd-";
|
||||
|
||||
let operation = match buf {
|
||||
// TODO: Better way to obtain new empty address spaces, perhaps using SYS_OPEN. But
|
||||
@@ -1139,6 +1172,21 @@ impl KernelScheme for ProcScheme {
|
||||
b"exclusive" => Operation::AddrSpace { addrspace: addrspace.write().try_clone(addrspace_clone)? },
|
||||
b"mmap-min-addr" => Operation::MmapMinAddr(Arc::clone(addrspace)),
|
||||
|
||||
_ if buf.starts_with(GRANT_FD_PREFIX) => {
|
||||
let string = core::str::from_utf8(&buf[GRANT_FD_PREFIX.len()..]).map_err(|_| Error::new(EINVAL))?;
|
||||
let page_addr = usize::from_str_radix(string, 16).map_err(|_| Error::new(EINVAL))?;
|
||||
|
||||
if page_addr % PAGE_SIZE != 0 {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
|
||||
let page = Page::containing_address(VirtualAddress::new(page_addr));
|
||||
|
||||
match addrspace.read().grants.contains(page).ok_or(Error::new(EINVAL))? {
|
||||
(_, info) => return Ok(OpenResult::External(info.file_ref().map(|r| Arc::clone(&r.description)).ok_or(Error::new(EBADF))?)),
|
||||
}
|
||||
}
|
||||
|
||||
_ => return Err(Error::new(EINVAL)),
|
||||
};
|
||||
|
||||
|
||||
+1
-1
Submodule syscall updated: d587771fc3...ff149946c0
Reference in New Issue
Block a user