Support getting intra-page off and mapping sig [tp]ctl.

This commit is contained in:
4lDO2
2025-03-31 18:32:02 +02:00
parent e002d0be33
commit 2f977bbc52
+53 -3
View File
@@ -4,10 +4,10 @@ use crate::{
self,
context::{HardBlockedReason, SignalState},
file::{FileDescriptor, InternalFlags},
memory::{handle_notify_files, AddrSpaceWrapper, Grant, PageSpan},
memory::{handle_notify_files, AddrSpace, AddrSpaceWrapper, Grant, PageSpan},
Context, Status,
},
memory::PAGE_SIZE,
memory::{get_page_info, AddRefError, RefKind, PAGE_SIZE},
ptrace,
scheme::{self, FileHandle, KernelScheme},
syscall::{
@@ -415,7 +415,7 @@ impl KernelScheme for ProcScheme {
consume: bool,
) -> Result<usize> {
let handle = HANDLES.read().get(&id).ok_or(Error::new(EBADF))?.clone();
let Handle { kind, .. } = handle;
let Handle { kind, ref context } = handle;
match kind {
ContextHandle::AddrSpace { ref addrspace } => {
@@ -479,6 +479,44 @@ impl KernelScheme for ProcScheme {
Ok(result_base.start_address().data())
}
ContextHandle::Sighandler => {
let context = context.read();
let sig = context.sig.as_ref().ok_or(Error::new(EBADF))?;
let frame = match map.offset {
// tctl
0 => &sig.thread_control,
// pctl
PAGE_SIZE => &sig.proc_control,
_ => return Err(Error::new(EINVAL)),
};
let info = get_page_info(frame.get()).ok_or(Error::new(EBADFD))?;
match info.add_ref(RefKind::Shared) {
Ok(()) => (),
Err(AddRefError::RcOverflow) => return Err(Error::new(ENOMEM)),
Err(AddRefError::CowToShared) => unreachable!("cannot be CoW since it's a kernel RaiiFrame that at some point was made Shared"),
Err(AddRefError::SharedToCow) => unreachable!("wasn't requested"),
}
// TODO: Allocated or AllocatedShared?
let addrsp = AddrSpace::current()?;
let page = addrsp.acquire_write().mmap(
&addrsp,
None,
NonZeroUsize::new(1).unwrap(),
MapFlags::PROT_READ | MapFlags::PROT_WRITE,
&mut Vec::new(),
|page, flags, mapper, flusher| {
Grant::allocated_shared_one_page(
frame.get(),
page,
flags,
mapper,
flusher,
false,
)
},
)?;
Ok(page.start_address().data())
}
_ => Err(Error::new(EBADF)),
}
}
@@ -1198,6 +1236,18 @@ impl ContextHandle {
ens,
})
}
ContextHandle::Sighandler => {
let data = match context.read().sig {
Some(ref sig) => SetSighandlerData {
excp_handler: sig.excp_handler.map_or(0, NonZeroUsize::get),
user_handler: sig.user_handler.get(),
proc_control_addr: sig.procctl_off.into(),
thread_control_addr: sig.threadctl_off.into(),
},
None => SetSighandlerData::default(),
};
buf.copy_common_bytes_from_slice(&data)
}
// TODO: Find a better way to switch address spaces, since they also require switching
// the instruction and stack pointer. Maybe remove `<pid>/regs` altogether and replace it