Implement bidirectional SYS_CALL support
This commit is contained in:
committed by
Jeremy Soller
parent
8f24d894eb
commit
4607576006
Generated
+2
-2
@@ -234,8 +234,8 @@ checksum = "64072665120942deff5fd5425d6c1811b854f4939e7f1c01ce755f64432bbea7"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.8"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/syscall.git?branch=master#ee30da97005bf4675f5ede8baa3a440abf773883"
|
||||
version = "0.5.9"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/syscall.git#3117ea451c6224a6eb91283d8eb7c41d05fb7d9d"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
]
|
||||
|
||||
+11
-2
@@ -13,7 +13,7 @@ use core::{hash::BuildHasherDefault, sync::atomic::AtomicUsize};
|
||||
use hashbrown::{hash_map::DefaultHashBuilder, HashMap};
|
||||
use indexmap::IndexMap;
|
||||
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use syscall::{EventFlags, MunmapFlags, SendFdFlags};
|
||||
use syscall::{CallFlags, EventFlags, MunmapFlags, SendFdFlags};
|
||||
|
||||
use crate::{
|
||||
context::{
|
||||
@@ -22,7 +22,7 @@ use crate::{
|
||||
},
|
||||
syscall::{
|
||||
error::*,
|
||||
usercopy::{UserSliceRo, UserSliceWo},
|
||||
usercopy::{UserSliceRo, UserSliceRw, UserSliceWo},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -505,6 +505,15 @@ pub trait KernelScheme: Send + Sync + 'static {
|
||||
fn on_close(&self, id: usize) -> Result<()> {
|
||||
self.close(id)
|
||||
}
|
||||
fn kcall(
|
||||
&self,
|
||||
id: usize,
|
||||
payload: UserSliceRw,
|
||||
flags: CallFlags,
|
||||
metadata: &[u64],
|
||||
) -> Result<usize> {
|
||||
Err(Error::new(EOPNOTSUPP))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
+65
-42
@@ -15,8 +15,8 @@ use spin::{Mutex, RwLock};
|
||||
use spinning_top::RwSpinlock;
|
||||
use syscall::{
|
||||
schemev2::{Cqe, CqeOpcode, Opcode, Sqe, SqeFlags},
|
||||
FobtainFdFlags, MunmapFlags, SendFdFlags, F_SETFL, KSMSG_CANCEL, MAP_FIXED_NOREPLACE,
|
||||
SKMSG_FOBTAINFD, SKMSG_FRETURNFD, SKMSG_PROVIDE_MMAP,
|
||||
CallFlags, FobtainFdFlags, MunmapFlags, SendFdFlags, F_SETFL, KSMSG_CANCEL,
|
||||
MAP_FIXED_NOREPLACE, SKMSG_FOBTAINFD, SKMSG_FRETURNFD, SKMSG_PROVIDE_MMAP,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -38,9 +38,9 @@ use crate::{
|
||||
syscall::{
|
||||
data::{Map, Packet},
|
||||
error::*,
|
||||
flag::{EventFlags, MapFlags, EVENT_READ, O_NONBLOCK, PROT_READ, PROT_WRITE},
|
||||
flag::{EventFlags, MapFlags, EVENT_READ, O_NONBLOCK, PROT_READ},
|
||||
number::*,
|
||||
usercopy::{UserSlice, UserSliceRo, UserSliceWo},
|
||||
usercopy::{UserSlice, UserSliceRo, UserSliceRw, UserSliceWo},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -465,12 +465,10 @@ impl UserInner {
|
||||
context_weak: &Weak<RwSpinlock<Context>>,
|
||||
user_buf: UserSlice<READ, WRITE>,
|
||||
) -> Result<CaptureGuard<READ, WRITE>> {
|
||||
let (mode, map_flags) = match (READ, WRITE) {
|
||||
(true, false) => (Mode::Ro, PROT_READ),
|
||||
(false, true) => (Mode::Wo, PROT_WRITE),
|
||||
let mut map_flags = MapFlags::empty();
|
||||
map_flags.set(MapFlags::PROT_READ, READ);
|
||||
map_flags.set(MapFlags::PROT_WRITE, WRITE);
|
||||
|
||||
_ => unreachable!(),
|
||||
};
|
||||
if user_buf.is_empty() {
|
||||
// NOTE: Rather than returning NULL, we return a dummy dangling address, that is
|
||||
// happens to be non-canonical on x86. This relieves scheme handlers from having to
|
||||
@@ -549,22 +547,18 @@ impl UserInner {
|
||||
|
||||
let len = core::cmp::min(PAGE_SIZE - offset, user_buf.len());
|
||||
|
||||
match mode {
|
||||
Mode::Ro => {
|
||||
array.buf_mut()[..offset].fill(0_u8);
|
||||
array.buf_mut()[offset + len..].fill(0_u8);
|
||||
if READ {
|
||||
array.buf_mut()[..offset].fill(0_u8);
|
||||
array.buf_mut()[offset + len..].fill(0_u8);
|
||||
|
||||
let slice = &mut array.buf_mut()[offset..][..len];
|
||||
let head_part_of_buf =
|
||||
user_buf.limit(len).expect("always smaller than max len");
|
||||
let slice = &mut array.buf_mut()[offset..][..len];
|
||||
let head_part_of_buf = user_buf.limit(len).expect("always smaller than max len");
|
||||
|
||||
head_part_of_buf
|
||||
.reinterpret_unchecked::<true, false>()
|
||||
.copy_to_slice(slice)?;
|
||||
}
|
||||
Mode::Wo => {
|
||||
array.buf_mut().fill(0_u8);
|
||||
}
|
||||
head_part_of_buf
|
||||
.reinterpret_unchecked::<true, false>()
|
||||
.copy_to_slice(slice)?;
|
||||
} else {
|
||||
array.buf_mut().fill(0_u8);
|
||||
}
|
||||
|
||||
dst_space.mmap(
|
||||
@@ -583,7 +577,7 @@ impl UserInner {
|
||||
|
||||
let head = CopyInfo {
|
||||
src: Some(array),
|
||||
dst: (mode == Mode::Wo).then_some(head_part_of_buf.reinterpret_unchecked()),
|
||||
dst: WRITE.then_some(head_part_of_buf.reinterpret_unchecked()),
|
||||
};
|
||||
|
||||
head
|
||||
@@ -651,20 +645,17 @@ impl UserInner {
|
||||
let mut array = BorrowedHtBuf::tail()?;
|
||||
let frame = array.frame();
|
||||
|
||||
match mode {
|
||||
Mode::Ro => {
|
||||
let (to_copy, to_zero) = array.buf_mut().split_at_mut(tail_size);
|
||||
if READ {
|
||||
let (to_copy, to_zero) = array.buf_mut().split_at_mut(tail_size);
|
||||
|
||||
to_zero.fill(0_u8);
|
||||
to_zero.fill(0_u8);
|
||||
|
||||
// FIXME: remove reinterpret_unchecked
|
||||
tail_part_of_buf
|
||||
.reinterpret_unchecked::<true, false>()
|
||||
.copy_to_slice(to_copy)?;
|
||||
}
|
||||
Mode::Wo => {
|
||||
array.buf_mut().fill(0_u8);
|
||||
}
|
||||
// FIXME: remove reinterpret_unchecked
|
||||
tail_part_of_buf
|
||||
.reinterpret_unchecked::<true, false>()
|
||||
.copy_to_slice(to_copy)?;
|
||||
} else {
|
||||
array.buf_mut().fill(0_u8);
|
||||
}
|
||||
|
||||
dst_space.mmap(
|
||||
@@ -683,7 +674,7 @@ impl UserInner {
|
||||
|
||||
CopyInfo {
|
||||
src: Some(array),
|
||||
dst: (mode == Mode::Wo).then_some(tail_part_of_buf.reinterpret_unchecked()),
|
||||
dst: WRITE.then_some(tail_part_of_buf.reinterpret_unchecked()),
|
||||
}
|
||||
} else {
|
||||
CopyInfo {
|
||||
@@ -1734,12 +1725,44 @@ impl KernelScheme for UserScheme {
|
||||
Response::Fd(_) => Err(Error::new(EIO)),
|
||||
}
|
||||
}
|
||||
}
|
||||
fn kcall(
|
||||
&self,
|
||||
id: usize,
|
||||
payload: UserSliceRw,
|
||||
_flags: CallFlags,
|
||||
metadata: &[u64],
|
||||
) -> Result<usize> {
|
||||
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum Mode {
|
||||
Ro,
|
||||
Wo,
|
||||
let mut address = inner.capture_user(payload)?;
|
||||
|
||||
let mut sqe = Sqe {
|
||||
opcode: Opcode::Call as u8,
|
||||
sqe_flags: SqeFlags::empty(),
|
||||
_rsvd: 0,
|
||||
tag: inner.next_id()?,
|
||||
caller: 0, // TODO?
|
||||
args: [
|
||||
id as u64,
|
||||
address.base() as u64,
|
||||
address.len() as u64,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
};
|
||||
{
|
||||
let dst = &mut sqe.args[3..];
|
||||
let len = dst.len().min(metadata.len());
|
||||
dst[..len].copy_from_slice(&metadata[..len]);
|
||||
}
|
||||
let res = inner.call_extended_inner(None, sqe, &mut address.span())?;
|
||||
|
||||
match res {
|
||||
Response::Regular(res, _) => Error::demux(res),
|
||||
Response::Fd(_) => Err(Error::new(EIO)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Args: Copy {
|
||||
|
||||
@@ -145,6 +145,13 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
Ok(times)
|
||||
}),
|
||||
),
|
||||
SYS_CALL => format!(
|
||||
"call({b}, {c:x}+{d}, {:?}, {:0x?}",
|
||||
CallFlags::from_bits_retain(e & !0xff),
|
||||
// TODO: u64
|
||||
UserSlice::ro(f, (e & 0xff) * 8)
|
||||
.and_then(|buf| buf.usizes().collect::<Result<Vec<usize>>>()),
|
||||
),
|
||||
|
||||
SYS_CLOCK_GETTIME => format!("clock_gettime({}, {:?})", b, unsafe {
|
||||
read_struct::<TimeSpec>(c)
|
||||
|
||||
+20
-2
@@ -1,5 +1,5 @@
|
||||
//! Filesystem syscalls
|
||||
use core::num::NonZeroUsize;
|
||||
use core::{mem::size_of, num::NonZeroUsize};
|
||||
|
||||
use alloc::{sync::Arc, vec::Vec};
|
||||
use redox_path::RedoxPath;
|
||||
@@ -17,7 +17,7 @@ use crate::{
|
||||
syscall::{data::Stat, error::*, flag::*},
|
||||
};
|
||||
|
||||
use super::usercopy::{UserSlice, UserSliceRo, UserSliceWo};
|
||||
use super::usercopy::{UserSlice, UserSliceRo, UserSliceRw, UserSliceWo};
|
||||
|
||||
pub fn file_op_generic<T>(
|
||||
fd: FileHandle,
|
||||
@@ -248,6 +248,24 @@ pub fn dup2(fd: FileHandle, new_fd: FileHandle, buf: UserSliceRo) -> Result<File
|
||||
.ok_or(Error::new(EMFILE))
|
||||
}
|
||||
}
|
||||
pub fn call(
|
||||
fd: FileHandle,
|
||||
payload: UserSliceRw,
|
||||
flags: CallFlags,
|
||||
metadata: UserSliceRo,
|
||||
) -> Result<usize> {
|
||||
let mut meta = [0_u64; 3];
|
||||
|
||||
// TODO: bytemuck/plain
|
||||
let copied = metadata.copy_common_bytes_to_slice(unsafe {
|
||||
core::slice::from_raw_parts_mut(meta.as_mut_ptr().cast(), meta.len() * 8)
|
||||
})?;
|
||||
|
||||
file_op_generic(fd, |scheme, number| {
|
||||
scheme.kcall(number, payload, flags, &meta[..copied / 8])
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sendfd(socket: FileHandle, fd: FileHandle, flags_raw: usize, arg: u64) -> Result<usize> {
|
||||
let requested_flags = SendFdFlags::from_bits(flags_raw).ok_or(Error::new(EINVAL))?;
|
||||
|
||||
|
||||
+7
-1
@@ -6,7 +6,7 @@ extern crate syscall;
|
||||
|
||||
use core::mem::size_of;
|
||||
|
||||
use syscall::{dirent::DirentHeader, RtSigInfo, RwFlags, EINVAL, SIGKILL};
|
||||
use syscall::{dirent::DirentHeader, CallFlags, RtSigInfo, RwFlags, EINVAL, SIGKILL};
|
||||
|
||||
pub use self::syscall::{
|
||||
data, error, flag, io, number, ptrace_event, EnvRegisters, FloatRegisters, IntRegisters,
|
||||
@@ -174,6 +174,12 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> us
|
||||
}
|
||||
|
||||
SYS_CLOSE => close(fd).map(|()| 0),
|
||||
SYS_CALL => call(
|
||||
fd,
|
||||
UserSlice::rw(c, d)?,
|
||||
CallFlags::from_bits(e & !0xff).ok_or(Error::new(EINVAL))?,
|
||||
UserSlice::ro(f, (e & 0xff) * 8)?,
|
||||
),
|
||||
|
||||
SYS_OPEN => open(UserSlice::ro(b, c)?, d).map(FileHandle::into),
|
||||
SYS_RMDIR => rmdir(UserSlice::ro(b, c)?).map(|()| 0),
|
||||
|
||||
@@ -17,6 +17,7 @@ pub struct UserSlice<const READ: bool, const WRITE: bool> {
|
||||
}
|
||||
pub type UserSliceRo = UserSlice<true, false>;
|
||||
pub type UserSliceWo = UserSlice<false, true>;
|
||||
pub type UserSliceRw = UserSlice<true, true>;
|
||||
|
||||
impl<const READ: bool, const WRITE: bool> UserSlice<READ, WRITE> {
|
||||
pub fn empty() -> Self {
|
||||
@@ -207,6 +208,11 @@ impl UserSliceWo {
|
||||
Self::new(base, size)
|
||||
}
|
||||
}
|
||||
impl UserSliceRw {
|
||||
pub fn rw(base: usize, size: usize) -> Result<Self> {
|
||||
Self::new(base, size)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_kernel_mem(slice: &[u8]) -> bool {
|
||||
(slice.as_ptr() as usize) >= crate::USER_END_OFFSET
|
||||
|
||||
Reference in New Issue
Block a user