wasi-common: move GuestPtr deref out of path::get

This commit is contained in:
Pat Hickey
2020-08-24 12:26:02 -07:00
parent 20ccc11564
commit 87222d6db0
2 changed files with 103 additions and 73 deletions

View File

@@ -4,7 +4,6 @@ use crate::wasi::types;
use crate::{Error, Result}; use crate::{Error, Result};
use std::path::{Component, Path}; use std::path::{Component, Path};
use std::str; use std::str;
use wiggle::GuestPtr;
pub(crate) use crate::sys::path::{from_host, open_rights}; pub(crate) use crate::sys::path::{from_host, open_rights};
@@ -15,15 +14,12 @@ pub(crate) fn get(
entry: &Entry, entry: &Entry,
required_rights: &HandleRights, required_rights: &HandleRights,
dirflags: types::Lookupflags, dirflags: types::Lookupflags,
path_ptr: &GuestPtr<'_, str>, path: &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. tracing::trace!(path = path);
let path = path_ptr.as_str()?;
tracing::trace!(path = &*path);
if path.contains('\0') { if path.contains('\0') {
// if contains NUL, return Ilseq // if contains NUL, return Ilseq

View File

@@ -6,6 +6,7 @@ use crate::wasi::{types, AsBytes};
use crate::{path, poll, Error, Result, WasiCtx}; use crate::{path, poll, Error, Result, WasiCtx};
use std::convert::TryInto; use std::convert::TryInto;
use std::io::{self, SeekFrom}; use std::io::{self, SeekFrom};
use std::ops::Deref;
use tracing::{debug, trace}; use tracing::{debug, trace};
use wiggle::{GuestPtr, GuestSlice}; use wiggle::{GuestPtr, GuestSlice};
@@ -438,11 +439,12 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
types::Rights::PATH_OPEN | types::Rights::PATH_CREATE_DIRECTORY, types::Rights::PATH_OPEN | types::Rights::PATH_CREATE_DIRECTORY,
); );
let entry = self.get_entry(dirfd)?; let entry = self.get_entry(dirfd)?;
let path = path.as_str()?;
let (dirfd, path) = path::get( let (dirfd, path) = path::get(
&entry, &entry,
&required_rights, &required_rights,
types::Lookupflags::empty(), types::Lookupflags::empty(),
path, path.deref(),
false, false,
)?; )?;
dirfd.create_directory(&path) dirfd.create_directory(&path)
@@ -456,7 +458,8 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
) -> Result<types::Filestat> { ) -> Result<types::Filestat> {
let required_rights = HandleRights::from_base(types::Rights::PATH_FILESTAT_GET); let required_rights = HandleRights::from_base(types::Rights::PATH_FILESTAT_GET);
let entry = self.get_entry(dirfd)?; let entry = self.get_entry(dirfd)?;
let (dirfd, path) = path::get(&entry, &required_rights, flags, path, false)?; let path = path.as_str()?;
let (dirfd, path) = path::get(&entry, &required_rights, flags, path.deref(), false)?;
let host_filestat = let host_filestat =
dirfd.filestat_get_at(&path, flags.contains(&types::Lookupflags::SYMLINK_FOLLOW))?; dirfd.filestat_get_at(&path, flags.contains(&types::Lookupflags::SYMLINK_FOLLOW))?;
Ok(host_filestat) Ok(host_filestat)
@@ -473,7 +476,8 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
) -> Result<()> { ) -> Result<()> {
let required_rights = HandleRights::from_base(types::Rights::PATH_FILESTAT_SET_TIMES); let required_rights = HandleRights::from_base(types::Rights::PATH_FILESTAT_SET_TIMES);
let entry = self.get_entry(dirfd)?; let entry = self.get_entry(dirfd)?;
let (dirfd, path) = path::get(&entry, &required_rights, flags, path, false)?; let path = path.as_str()?;
let (dirfd, path) = path::get(&entry, &required_rights, flags, path.deref(), false)?;
dirfd.filestat_set_times_at( dirfd.filestat_set_times_at(
&path, &path,
atim, atim,
@@ -494,22 +498,30 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
) -> Result<()> { ) -> Result<()> {
let required_rights = HandleRights::from_base(types::Rights::PATH_LINK_SOURCE); let required_rights = HandleRights::from_base(types::Rights::PATH_LINK_SOURCE);
let old_entry = self.get_entry(old_fd)?; let old_entry = self.get_entry(old_fd)?;
let (old_dirfd, old_path) = path::get( let (old_dirfd, old_path) = {
// Borrow old_path for just this scope
let old_path = old_path.as_str()?;
path::get(
&old_entry, &old_entry,
&required_rights, &required_rights,
types::Lookupflags::empty(), types::Lookupflags::empty(),
old_path, old_path.deref(),
false, false,
)?; )?
};
let required_rights = HandleRights::from_base(types::Rights::PATH_LINK_TARGET); let required_rights = HandleRights::from_base(types::Rights::PATH_LINK_TARGET);
let new_entry = self.get_entry(new_fd)?; let new_entry = self.get_entry(new_fd)?;
let (new_dirfd, new_path) = path::get( let (new_dirfd, new_path) = {
// Borrow new_path for just this scope
let new_path = new_path.as_str()?;
path::get(
&new_entry, &new_entry,
&required_rights, &required_rights,
types::Lookupflags::empty(), types::Lookupflags::empty(),
new_path, new_path.deref(),
false, false,
)?; )?
};
old_dirfd.link( old_dirfd.link(
&old_path, &old_path,
new_dirfd, new_dirfd,
@@ -535,13 +547,16 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
); );
trace!(" | needed_rights={}", needed_rights); trace!(" | needed_rights={}", needed_rights);
let entry = self.get_entry(dirfd)?; let entry = self.get_entry(dirfd)?;
let (dirfd, path) = path::get( let (dirfd, path) = {
let path = path.as_str()?;
path::get(
&entry, &entry,
&needed_rights, &needed_rights,
dirflags, dirflags,
path, path.deref(),
oflags & types::Oflags::CREAT != types::Oflags::empty(), oflags & types::Oflags::CREAT != types::Oflags::empty(),
)?; )?
};
// which open mode do we need? // which open mode do we need?
let read = fs_rights_base & (types::Rights::FD_READ | types::Rights::FD_READDIR) let read = fs_rights_base & (types::Rights::FD_READ | types::Rights::FD_READDIR)
!= types::Rights::empty(); != types::Rights::empty();
@@ -577,13 +592,17 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
) -> Result<types::Size> { ) -> Result<types::Size> {
let required_rights = HandleRights::from_base(types::Rights::PATH_READLINK); let required_rights = HandleRights::from_base(types::Rights::PATH_READLINK);
let entry = self.get_entry(dirfd)?; let entry = self.get_entry(dirfd)?;
let (dirfd, path) = path::get( let (dirfd, path) = {
// borrow path for just this scope
let path = path.as_str()?;
path::get(
&entry, &entry,
&required_rights, &required_rights,
types::Lookupflags::empty(), types::Lookupflags::empty(),
path, path.deref(),
false, false,
)?; )?
};
let mut slice = buf.as_array(buf_len).as_slice()?; let mut slice = buf.as_array(buf_len).as_slice()?;
let host_bufused = dirfd.readlink(&path, &mut *slice)?.try_into()?; let host_bufused = dirfd.readlink(&path, &mut *slice)?.try_into()?;
Ok(host_bufused) Ok(host_bufused)
@@ -592,13 +611,16 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
fn path_remove_directory(&self, dirfd: types::Fd, path: &GuestPtr<'_, str>) -> Result<()> { fn path_remove_directory(&self, dirfd: types::Fd, path: &GuestPtr<'_, str>) -> Result<()> {
let required_rights = HandleRights::from_base(types::Rights::PATH_REMOVE_DIRECTORY); let required_rights = HandleRights::from_base(types::Rights::PATH_REMOVE_DIRECTORY);
let entry = self.get_entry(dirfd)?; let entry = self.get_entry(dirfd)?;
let (dirfd, path) = path::get( let (dirfd, path) = {
let path = path.as_str()?;
path::get(
&entry, &entry,
&required_rights, &required_rights,
types::Lookupflags::empty(), types::Lookupflags::empty(),
path, path.deref(),
true, true,
)?; )?
};
dirfd.remove_directory(&path) dirfd.remove_directory(&path)
} }
@@ -611,22 +633,28 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
) -> Result<()> { ) -> Result<()> {
let required_rights = HandleRights::from_base(types::Rights::PATH_RENAME_SOURCE); let required_rights = HandleRights::from_base(types::Rights::PATH_RENAME_SOURCE);
let entry = self.get_entry(old_fd)?; let entry = self.get_entry(old_fd)?;
let (old_dirfd, old_path) = path::get( let (old_dirfd, old_path) = {
let old_path = old_path.as_str()?;
path::get(
&entry, &entry,
&required_rights, &required_rights,
types::Lookupflags::empty(), types::Lookupflags::empty(),
old_path, old_path.deref(),
true, true,
)?; )?
};
let required_rights = HandleRights::from_base(types::Rights::PATH_RENAME_TARGET); let required_rights = HandleRights::from_base(types::Rights::PATH_RENAME_TARGET);
let entry = self.get_entry(new_fd)?; let entry = self.get_entry(new_fd)?;
let (new_dirfd, new_path) = path::get( let (new_dirfd, new_path) = {
let new_path = new_path.as_str()?;
path::get(
&entry, &entry,
&required_rights, &required_rights,
types::Lookupflags::empty(), types::Lookupflags::empty(),
new_path, new_path.deref(),
true, true,
)?; )?
};
old_dirfd.rename(&old_path, new_dirfd, &new_path) old_dirfd.rename(&old_path, new_dirfd, &new_path)
} }
@@ -638,28 +666,34 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
) -> Result<()> { ) -> Result<()> {
let required_rights = HandleRights::from_base(types::Rights::PATH_SYMLINK); let required_rights = HandleRights::from_base(types::Rights::PATH_SYMLINK);
let entry = self.get_entry(dirfd)?; let entry = self.get_entry(dirfd)?;
let (new_fd, new_path) = path::get( let (new_fd, new_path) = {
let new_path = new_path.as_str()?;
path::get(
&entry, &entry,
&required_rights, &required_rights,
types::Lookupflags::empty(), types::Lookupflags::empty(),
new_path, new_path.deref(),
true, true,
)?; )?
};
let old_path = old_path.as_str()?; let old_path = old_path.as_str()?;
trace!(old_path = &*old_path); trace!(old_path = old_path.deref());
new_fd.symlink(&old_path, &new_path) new_fd.symlink(&old_path, &new_path)
} }
fn path_unlink_file(&self, dirfd: types::Fd, path: &GuestPtr<'_, str>) -> Result<()> { fn path_unlink_file(&self, dirfd: types::Fd, path: &GuestPtr<'_, str>) -> Result<()> {
let required_rights = HandleRights::from_base(types::Rights::PATH_UNLINK_FILE); let required_rights = HandleRights::from_base(types::Rights::PATH_UNLINK_FILE);
let entry = self.get_entry(dirfd)?; let entry = self.get_entry(dirfd)?;
let (dirfd, path) = path::get( let (dirfd, path) = {
let path = path.as_str()?;
path::get(
&entry, &entry,
&required_rights, &required_rights,
types::Lookupflags::empty(), types::Lookupflags::empty(),
path, path.deref(),
false, false,
)?; )?
};
dirfd.unlink_file(&path)?; dirfd.unlink_file(&path)?;
Ok(()) Ok(())
} }