[hyper mode] Add UntrustedSlice

This commit is contained in:
LI Qing 2022-01-27 17:46:53 +08:00 committed by Zongmin.Gu
parent 0b7b384241
commit 1d1cbb0abf
5 changed files with 102 additions and 13 deletions

@ -1,6 +1,6 @@
use super::*;
use std;
use untrusted::{SliceAsMutPtrAndLen, SliceAsPtrAndLen, UntrustedSliceAlloc};
use untrusted::{SliceAsMutPtrAndLen, SliceAsPtrAndLen, UntrustedSlice, UntrustedSliceAlloc};
pub use self::io_multiplexing::{
clear_notifier_status, notify_thread, wait_for_notification, EpollEvent, IoEvent, PollEvent,

@ -45,10 +45,10 @@ impl HostSocket {
let mut remain = retval.0;
for (i, buf) in data.iter_mut().enumerate() {
if remain >= buf.len() {
buf.copy_from_slice(u_data[i]);
u_data[i].write_to_slice(buf)?;
remain -= buf.len();
} else {
buf[0..remain].copy_from_slice(&u_data[i][0..remain]);
u_data[i].write_to_slice(&mut buf[0..remain])?;
break;
}
}
@ -57,7 +57,7 @@ impl HostSocket {
fn do_recvmsg_untrusted_data(
&self,
data: &mut [&mut [u8]],
data: &mut [UntrustedSlice],
flags: RecvFlags,
mut name: Option<&mut [u8]>,
mut control: Option<&mut [u8]>,
@ -70,8 +70,10 @@ impl HostSocket {
let msg_name = msg_name as *mut c_void;
let mut msg_namelen_recvd = 0_u32;
// Iovs
let mut raw_iovs: Vec<libc::iovec> =
data.iter().map(|slice| slice.as_libc_iovec()).collect();
let mut raw_iovs: Vec<libc::iovec> = data
.iter()
.map(|slice| slice.as_ref().as_libc_iovec())
.collect();
let (msg_iov, msg_iovlen) = raw_iovs.as_mut_slice().as_mut_ptr_and_len();
// Control
let (msg_control, msg_controllen) = control.as_mut_ptr_and_len();

@ -38,7 +38,7 @@ impl HostSocket {
fn do_sendmsg_untrusted_data(
&self,
u_data: &[&[u8]],
u_data: &[UntrustedSlice],
flags: SendFlags,
name: Option<&[u8]>,
control: Option<&[u8]>,
@ -51,7 +51,10 @@ impl HostSocket {
let (msg_name, msg_namelen) = name.as_ptr_and_len();
let msg_name = msg_name as *const c_void;
// Iovs
let raw_iovs: Vec<libc::iovec> = u_data.iter().map(|slice| slice.as_libc_iovec()).collect();
let raw_iovs: Vec<libc::iovec> = u_data
.iter()
.map(|slice| slice.as_ref().as_libc_iovec())
.collect();
let (msg_iov, msg_iovlen) = raw_iovs.as_slice().as_ptr_and_len();
// Control
let (msg_control, msg_controllen) = control.as_ptr_and_len();

@ -6,5 +6,5 @@ mod slice_ext;
use super::*;
pub use self::alloc::UNTRUSTED_ALLOC;
pub use self::slice_alloc::UntrustedSliceAlloc;
pub use self::slice_alloc::{UntrustedSlice, UntrustedSliceAlloc};
pub use self::slice_ext::{SliceAsMutPtrAndLen, SliceAsPtrAndLen};

@ -1,5 +1,6 @@
use super::*;
use std::alloc::{AllocError, Allocator, Layout};
use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;
use std::sync::atomic::{AtomicUsize, Ordering};
@ -36,13 +37,13 @@ impl UntrustedSliceAlloc {
})
}
pub fn new_slice(&self, src_slice: &[u8]) -> Result<&[u8]> {
pub fn new_slice(&self, src_slice: &[u8]) -> Result<UntrustedSlice> {
let mut new_slice = self.new_slice_mut(src_slice.len())?;
new_slice.copy_from_slice(src_slice);
new_slice.read_from_slice(src_slice)?;
Ok(new_slice)
}
pub fn new_slice_mut(&self, new_slice_len: usize) -> Result<&mut [u8]> {
pub fn new_slice_mut(&self, new_slice_len: usize) -> Result<UntrustedSlice> {
let new_slice_ptr = {
// Move self.buf_pos forward if enough space _atomically_.
let old_pos = self
@ -59,7 +60,7 @@ impl UntrustedSliceAlloc {
unsafe { self.buf_ptr.add(old_pos) }
};
let new_slice = unsafe { std::slice::from_raw_parts_mut(new_slice_ptr, new_slice_len) };
Ok(new_slice)
Ok(UntrustedSlice { slice: new_slice })
}
}
@ -76,3 +77,86 @@ impl Drop for UntrustedSliceAlloc {
}
}
}
pub struct UntrustedSlice<'a> {
slice: &'a mut [u8],
}
impl UntrustedSlice<'_> {
pub fn read_from_slice(&mut self, src_slice: &[u8]) -> Result<()> {
assert!(self.len() >= src_slice.len());
#[cfg(not(feature = "hyper_mode"))]
self[..src_slice.len()].copy_from_slice(src_slice);
#[cfg(feature = "hyper_mode")]
{
let n = unsafe {
libc::ocall::write_shared_buf(
self.as_mut_ptr() as *mut _,
src_slice.as_ptr() as *const _,
src_slice.len(),
0,
)
};
match n {
n if n < 0 => return_errno!(ENOMEM, "No enough space"),
n if n as usize == src_slice.len() => {}
_ => return_errno!(ENOMEM, "failed to fill whole buffer"),
}
}
Ok(())
}
pub fn write_to_slice(&self, dest_slice: &mut [u8]) -> Result<()> {
assert!(self.len() >= dest_slice.len());
#[cfg(not(feature = "hyper_mode"))]
dest_slice.copy_from_slice(&self[..dest_slice.len()]);
#[cfg(feature = "hyper_mode")]
{
let n = unsafe {
libc::ocall::read_shared_buf(
self.as_ptr() as *const _,
dest_slice.as_mut_ptr() as *mut _,
dest_slice.len(),
0,
)
};
match n {
n if n < 0 => return_errno!(ENOMEM, "No enough space"),
n if n as usize == dest_slice.len() => {}
_ => return_errno!(ENOMEM, "failed to write whole buffer"),
}
}
Ok(())
}
}
impl AsRef<[u8]> for UntrustedSlice<'_> {
fn as_ref(&self) -> &[u8] {
&**self
}
}
impl AsMut<[u8]> for UntrustedSlice<'_> {
fn as_mut(&mut self) -> &mut [u8] {
&mut **self
}
}
impl Deref for UntrustedSlice<'_> {
type Target = [u8];
#[inline]
fn deref(&self) -> &Self::Target {
self.slice
}
}
impl DerefMut for UntrustedSlice<'_> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.slice
}
}