wasi-common: WIP translating to use automated borrow checking

This commit is contained in:
Pat Hickey
2020-05-19 18:13:20 -07:00
parent 3643f2d164
commit 04fb4acc6a
2 changed files with 34 additions and 67 deletions

View File

@@ -3,7 +3,7 @@ use crate::handle::{Handle, HandleRights};
use crate::wasi::{types, Errno, Result}; use crate::wasi::{types, Errno, Result};
use std::path::{Component, Path}; use std::path::{Component, Path};
use std::str; use std::str;
use wiggle::{GuestBorrows, GuestPtr}; use wiggle::GuestPtr;
pub(crate) use crate::sys::path::{from_host, open_rights}; pub(crate) use crate::sys::path::{from_host, open_rights};
@@ -14,19 +14,15 @@ pub(crate) fn get(
entry: &Entry, entry: &Entry,
required_rights: &HandleRights, required_rights: &HandleRights,
dirflags: types::Lookupflags, dirflags: types::Lookupflags,
path: &GuestPtr<'_, str>, path_ptr: &GuestPtr<'_, str>,
needs_final_component: bool, needs_final_component: bool,
) -> Result<(Box<dyn Handle>, String)> { ) -> Result<(Box<dyn Handle>, String)> {
const MAX_SYMLINK_EXPANSIONS: usize = 128; const MAX_SYMLINK_EXPANSIONS: usize = 128;
// Extract path as &str from guest's memory. // Extract path as &str from guest's memory.
let path = unsafe { let path = path_ptr.as_str()?;
let mut bc = GuestBorrows::new();
let raw = path.as_raw(&mut bc)?;
&*raw
};
log::trace!(" | (path_ptr,path_len)='{}'", path); log::trace!(" | (path_ptr,path_len)='{}'", &*path);
if path.contains('\0') { if path.contains('\0') {
// if contains NUL, return Ilseq // if contains NUL, return Ilseq
@@ -51,6 +47,9 @@ pub(crate) fn get(
// any symlinks we encounter are processed by pushing them on the stack. // any symlinks we encounter are processed by pushing them on the stack.
let mut path_stack = vec![path.to_owned()]; let mut path_stack = vec![path.to_owned()];
// No longer need a borrow into the guest memory for `path`:
drop(path);
// Track the number of symlinks we've expanded, so we can return `ELOOP` after too many. // Track the number of symlinks we've expanded, so we can return `ELOOP` after too many.
let mut symlink_expansions = 0; let mut symlink_expansions = 0;

View File

@@ -8,7 +8,7 @@ use crate::{path, poll};
use log::{debug, error, trace}; use log::{debug, error, trace};
use std::convert::TryInto; use std::convert::TryInto;
use std::io::{self, SeekFrom}; use std::io::{self, SeekFrom};
use wiggle::{GuestBorrows, GuestPtr}; use wiggle::{GuestPtr, GuestSlice};
impl<'a> WasiSnapshotPreview1 for WasiCtx { impl<'a> WasiSnapshotPreview1 for WasiCtx {
fn args_get<'b>( fn args_get<'b>(
@@ -199,18 +199,11 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
iovs: &types::IovecArray<'_>, iovs: &types::IovecArray<'_>,
offset: types::Filesize, offset: types::Filesize,
) -> Result<types::Size> { ) -> Result<types::Size> {
let mut buf = Vec::new(); let mut guest_slices: Vec<GuestSlice<'_, u8>> = Vec::new();
let mut bc = GuestBorrows::new();
bc.borrow_slice(iovs)?;
for iov_ptr in iovs.iter() { for iov_ptr in iovs.iter() {
let iov_ptr = iov_ptr?; let iov_ptr = iov_ptr?;
let iov: types::Iovec = iov_ptr.read()?; let iov: types::Iovec = iov_ptr.read()?;
let slice = unsafe { guest_slices.push(iov.buf.as_array(iov.buf_len).as_slice()?);
let buf = iov.buf.as_array(iov.buf_len);
let raw = buf.as_raw(&mut bc)?;
&mut *raw
};
buf.push(io::IoSliceMut::new(slice));
} }
let required_rights = let required_rights =
@@ -219,10 +212,18 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
if offset > i64::max_value() as u64 { if offset > i64::max_value() as u64 {
return Err(Errno::Io); return Err(Errno::Io);
} }
let host_nread = entry
.as_handle(&required_rights)? let host_nread = {
.preadv(&mut buf, offset)? let mut buf = guest_slices
.try_into()?; .iter()
.map(|s| io::IoSliceMut::new(&mut *s))
.collect::<Vec<io::IoSliceMut<'_>>>();
entry
.as_handle(&required_rights)?
.preadv(&mut buf, offset)?
.try_into()?
};
drop(guest_slices);
Ok(host_nread) Ok(host_nread)
} }
@@ -276,16 +277,11 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
offset: types::Filesize, offset: types::Filesize,
) -> Result<types::Size> { ) -> Result<types::Size> {
let mut buf = Vec::new(); let mut buf = Vec::new();
let mut bc = GuestBorrows::new();
bc.borrow_slice(ciovs)?;
for ciov_ptr in ciovs.iter() { for ciov_ptr in ciovs.iter() {
let ciov_ptr = ciov_ptr?; let ciov_ptr = ciov_ptr?;
let ciov: types::Ciovec = ciov_ptr.read()?; let ciov: types::Ciovec = ciov_ptr.read()?;
let slice = unsafe { let guest_slice: GuestSlice<u8> = ciov.buf.as_array(ciov.buf_len).as_slice()?;
let buf = ciov.buf.as_array(ciov.buf_len); let slice: &[u8] = &*guest_slice;
let raw = buf.as_raw(&mut bc)?;
&*raw
};
buf.push(io::IoSlice::new(slice)); buf.push(io::IoSlice::new(slice));
} }
@@ -305,17 +301,12 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
} }
fn fd_read(&self, fd: types::Fd, iovs: &types::IovecArray<'_>) -> Result<types::Size> { fn fd_read(&self, fd: types::Fd, iovs: &types::IovecArray<'_>) -> Result<types::Size> {
let mut bc = GuestBorrows::new();
let mut slices = Vec::new(); let mut slices = Vec::new();
bc.borrow_slice(&iovs)?;
for iov_ptr in iovs.iter() { for iov_ptr in iovs.iter() {
let iov_ptr = iov_ptr?; let iov_ptr = iov_ptr?;
let iov: types::Iovec = iov_ptr.read()?; let iov: types::Iovec = iov_ptr.read()?;
let slice = unsafe { let guest_slice = iov.buf.as_array(iov.buf_len).as_slice()?;
let buf = iov.buf.as_array(iov.buf_len); let slice = &mut *guest_slice;
let raw = buf.as_raw(&mut bc)?;
&mut *raw
};
slices.push(io::IoSliceMut::new(slice)); slices.push(io::IoSliceMut::new(slice));
} }
@@ -423,18 +414,12 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
} }
fn fd_write(&self, fd: types::Fd, ciovs: &types::CiovecArray<'_>) -> Result<types::Size> { fn fd_write(&self, fd: types::Fd, ciovs: &types::CiovecArray<'_>) -> Result<types::Size> {
let mut bc = GuestBorrows::new();
let mut slices = Vec::new(); let mut slices = Vec::new();
bc.borrow_slice(&ciovs)?;
for ciov_ptr in ciovs.iter() { for ciov_ptr in ciovs.iter() {
let ciov_ptr = ciov_ptr?; let ciov_ptr = ciov_ptr?;
let ciov: types::Ciovec = ciov_ptr.read()?; let ciov: types::Ciovec = ciov_ptr.read()?;
let slice = unsafe { let slice = ciov.buf.as_array(ciov.buf_len).as_slice()?;
let buf = ciov.buf.as_array(ciov.buf_len); slices.push(io::IoSlice::new(&*slice));
let raw = buf.as_raw(&mut bc)?;
&*raw
};
slices.push(io::IoSlice::new(slice));
} }
let required_rights = HandleRights::from_base(types::Rights::FD_WRITE); let required_rights = HandleRights::from_base(types::Rights::FD_WRITE);
let entry = self.get_entry(fd)?; let entry = self.get_entry(fd)?;
@@ -596,13 +581,8 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
path, path,
false, false,
)?; )?;
let slice = unsafe { let slice = buf.as_array(buf_len).as_slice()?;
let mut bc = GuestBorrows::new(); let host_bufused = dirfd.readlink(&path, &mut *slice)?.try_into()?;
let buf = buf.as_array(buf_len);
let raw = buf.as_raw(&mut bc)?;
&mut *raw
};
let host_bufused = dirfd.readlink(&path, slice)?.try_into()?;
Ok(host_bufused) Ok(host_bufused)
} }
@@ -662,12 +642,8 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
new_path, new_path,
true, true,
)?; )?;
let old_path = unsafe { let old_path = old_path.as_str()?;
let mut bc = GuestBorrows::new(); trace!(" | old_path='{}'", &*old_path);
let raw = old_path.as_raw(&mut bc)?;
&*raw
};
trace!(" | old_path='{}'", old_path);
new_fd.symlink(&old_path, &new_path) new_fd.symlink(&old_path, &new_path)
} }
@@ -696,9 +672,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
} }
let mut subscriptions = Vec::new(); let mut subscriptions = Vec::new();
let mut bc = GuestBorrows::new();
let subs = in_.as_array(nsubscriptions); let subs = in_.as_array(nsubscriptions);
bc.borrow_slice(&subs)?;
for sub_ptr in subs.iter() { for sub_ptr in subs.iter() {
let sub_ptr = sub_ptr?; let sub_ptr = sub_ptr?;
let sub: types::Subscription = sub_ptr.read()?; let sub: types::Subscription = sub_ptr.read()?;
@@ -793,7 +767,6 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
let nevents = events.len().try_into()?; let nevents = events.len().try_into()?;
let out_events = out.as_array(nevents); let out_events = out.as_array(nevents);
bc.borrow_slice(&out_events)?;
for (event, event_ptr) in events.into_iter().zip(out_events.iter()) { for (event, event_ptr) in events.into_iter().zip(out_events.iter()) {
let event_ptr = event_ptr?; let event_ptr = event_ptr?;
event_ptr.write(event)?; event_ptr.write(event)?;
@@ -820,13 +793,8 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
} }
fn random_get(&self, buf: &GuestPtr<u8>, buf_len: types::Size) -> Result<()> { fn random_get(&self, buf: &GuestPtr<u8>, buf_len: types::Size) -> Result<()> {
let slice = unsafe { let slice = buf.as_array(buf_len).as_slice()?;
let mut bc = GuestBorrows::new(); getrandom::getrandom(&mut *slice).map_err(|err| {
let buf = buf.as_array(buf_len);
let raw = buf.as_raw(&mut bc)?;
&mut *raw
};
getrandom::getrandom(slice).map_err(|err| {
error!("getrandom failure: {:?}", err); error!("getrandom failure: {:?}", err);
Errno::Io Errno::Io
}) })