Merge remote-tracking branch 'upstream/master' into poll

This commit is contained in:
Marcin Mielniczuk
2020-01-14 16:40:23 +01:00
104 changed files with 2056 additions and 1607 deletions

View File

@@ -155,8 +155,21 @@ impl FdEntry {
rights_base: wasi::__wasi_rights_t,
rights_inheriting: wasi::__wasi_rights_t,
) -> Result<()> {
if !self.rights_base & rights_base != 0 || !self.rights_inheriting & rights_inheriting != 0
{
let missing_base = !self.rights_base & rights_base;
let missing_inheriting = !self.rights_inheriting & rights_inheriting;
if missing_base != 0 || missing_inheriting != 0 {
log::trace!(
" | validate_rights failed: required: \
rights_base = {:#x}, rights_inheriting = {:#x}; \
actual: rights_base = {:#x}, rights_inheriting = {:#x}; \
missing_base = {:#x}, missing_inheriting = {:#x}",
rights_base,
rights_inheriting,
self.rights_base,
self.rights_inheriting,
missing_base,
missing_inheriting
);
Err(Error::ENOTCAPABLE)
} else {
Ok(())

View File

@@ -67,7 +67,7 @@ hostcalls! {
) -> wasi::__wasi_errno_t;
pub unsafe fn fd_fdstat_set_flags(
wasi_ctx: &WasiCtx,
wasi_ctx: &mut WasiCtx,
memory: &mut [u8],
fd: wasi::__wasi_fd_t,
fdflags: wasi::__wasi_fdflags_t,

View File

@@ -5,7 +5,6 @@ use crate::fdentry::{Descriptor, FdEntry};
use crate::helpers::*;
use crate::memory::*;
use crate::sandboxed_tty_writer::SandboxedTTYWriter;
use crate::sys::fdentry_impl::determine_type_rights;
use crate::sys::hostcalls_impl::fs_helpers::path_open_rights;
use crate::sys::{host_impl, hostcalls_impl};
use crate::{helpers, host, wasi, wasi32, Error, Result};
@@ -299,19 +298,24 @@ pub(crate) unsafe fn fd_fdstat_get(
}
pub(crate) unsafe fn fd_fdstat_set_flags(
wasi_ctx: &WasiCtx,
wasi_ctx: &mut WasiCtx,
_memory: &mut [u8],
fd: wasi::__wasi_fd_t,
fdflags: wasi::__wasi_fdflags_t,
) -> Result<()> {
trace!("fd_fdstat_set_flags(fd={:?}, fdflags={:#x?})", fd, fdflags);
let fd = wasi_ctx
.get_fd_entry(fd)?
.as_descriptor(0, 0)?
.as_os_handle();
let descriptor = wasi_ctx
.get_fd_entry_mut(fd)?
.as_descriptor_mut(wasi::__WASI_RIGHTS_FD_FDSTAT_SET_FLAGS, 0)?;
hostcalls_impl::fd_fdstat_set_flags(&fd, fdflags)
if let Some(new_handle) =
hostcalls_impl::fd_fdstat_set_flags(&descriptor.as_os_handle(), fdflags)?
{
*descriptor = Descriptor::OsHandle(new_handle);
}
Ok(())
}
pub(crate) unsafe fn fd_fdstat_set_rights(
@@ -574,6 +578,11 @@ pub(crate) unsafe fn path_open(
let (needed_base, needed_inheriting) =
path_open_rights(fs_rights_base, fs_rights_inheriting, oflags, fs_flags);
trace!(
" | needed_base = {}, needed_inheriting = {}",
needed_base,
needed_inheriting
);
let fe = wasi_ctx.get_fd_entry(dirfd)?;
let resolved = path_get(
fe,
@@ -593,13 +602,20 @@ pub(crate) unsafe fn path_open(
| wasi::__WASI_RIGHTS_FD_FILESTAT_SET_SIZE)
!= 0;
trace!(
" | calling path_open impl: read={}, write={}",
read,
write
);
let fd = hostcalls_impl::path_open(resolved, read, write, oflags, fs_flags)?;
// Determine the type of the new file descriptor and which rights contradict with this type
let (_ty, max_base, max_inheriting) = determine_type_rights(&fd)?;
let mut fe = FdEntry::from(fd)?;
fe.rights_base &= max_base;
fe.rights_inheriting &= max_inheriting;
// We need to manually deny the rights which are not explicitly requested.
// This should not be needed, but currently determine_type_and_access_rights,
// which is used by FdEntry::from, may grant extra rights while inferring it
// from the open mode.
fe.rights_base &= fs_rights_base;
fe.rights_inheriting &= fs_rights_inheriting;
let guest_fd = wasi_ctx.insert_fd_entry(fe)?;
trace!(" | *fd={:?}", guest_fd);
@@ -709,7 +725,10 @@ pub(crate) unsafe fn fd_filestat_get(
filestat_ptr
);
let fd = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_file()?;
let fd = wasi_ctx
.get_fd_entry(fd)?
.as_descriptor(wasi::__WASI_RIGHTS_FD_FILESTAT_GET, 0)?
.as_file()?;
let host_filestat = hostcalls_impl::fd_filestat_get(fd)?;
trace!(" | *filestat_ptr={:?}", host_filestat);

View File

@@ -242,9 +242,9 @@ pub(crate) fn poll_oneoff(
{
let wasi_fd = unsafe { subscription.u.fd_readwrite.file_descriptor };
let rights = if r#type == wasi::__WASI_EVENTTYPE_FD_READ {
wasi::__WASI_RIGHTS_FD_READ
wasi::__WASI_RIGHTS_FD_READ | wasi::__WASI_RIGHTS_POLL_FD_READWRITE
} else {
wasi::__WASI_RIGHTS_FD_WRITE
wasi::__WASI_RIGHTS_FD_WRITE | wasi::__WASI_RIGHTS_POLL_FD_READWRITE
};
match unsafe {

View File

@@ -29,9 +29,14 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result<wasi::__wasi_fdflags_t> {
.map_err(Into::into)
}
pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> Result<()> {
pub(crate) fn fd_fdstat_set_flags(
fd: &File,
fdflags: wasi::__wasi_fdflags_t,
) -> Result<Option<OsHandle>> {
let nix_flags = host_impl::nix_from_fdflags(fdflags);
unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), nix_flags) }.map_err(Into::into)
unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), nix_flags) }
.map(|_| None)
.map_err(Into::into)
}
pub(crate) fn fd_advise(

View File

@@ -5,7 +5,7 @@ use crate::ctx::WasiCtx;
use crate::fdentry::FdEntry;
use crate::host::{Dirent, FileType};
use crate::hostcalls_impl::{fd_filestat_set_times_impl, PathGet};
use crate::sys::fdentry_impl::determine_type_rights;
use crate::sys::fdentry_impl::{determine_type_rights, OsHandle};
use crate::sys::host_impl::{self, path_from_host};
use crate::sys::hostcalls_impl::fs_helpers::PathGetExt;
use crate::{wasi, Error, Result};
@@ -78,8 +78,26 @@ pub(crate) fn fd_fdstat_get(fd: &File) -> Result<wasi::__wasi_fdflags_t> {
Ok(fdflags)
}
pub(crate) fn fd_fdstat_set_flags(fd: &File, fdflags: wasi::__wasi_fdflags_t) -> Result<()> {
unimplemented!("fd_fdstat_set_flags")
pub(crate) fn fd_fdstat_set_flags(
fd: &File,
fdflags: wasi::__wasi_fdflags_t,
) -> Result<Option<OsHandle>> {
let handle = unsafe { fd.as_raw_handle() };
let access_mode = winx::file::query_access_information(handle)?;
let new_access_mode = file_access_mode_from_fdflags(
fdflags,
access_mode.contains(AccessMode::FILE_READ_DATA),
access_mode.contains(AccessMode::FILE_WRITE_DATA)
| access_mode.contains(AccessMode::FILE_APPEND_DATA),
);
unsafe {
Ok(Some(OsHandle::from(File::from_raw_handle(
winx::file::reopen_file(handle, new_access_mode, file_flags_from_fdflags(fdflags))?,
))))
}
}
pub(crate) fn fd_advise(
@@ -119,9 +137,20 @@ pub(crate) fn path_open(
) -> Result<File> {
use winx::file::{AccessMode, CreationDisposition, Flags};
let is_trunc = oflags & wasi::__WASI_OFLAGS_TRUNC != 0;
if is_trunc {
// Windows does not support append mode when opening for truncation
// This is because truncation requires `GENERIC_WRITE` access, which will override the removal
// of the `FILE_WRITE_DATA` permission.
if fdflags & wasi::__WASI_FDFLAGS_APPEND != 0 {
return Err(Error::ENOTSUP);
}
}
// convert open flags
// note: the calls to `write(true)` are to bypass an internal OpenOption check
// the write flag will ultimately be ignored when `access_mode` is called below.
// the write flag will ultimately be ignored when `access_mode` is calculated below.
let mut opts = OpenOptions::new();
match creation_disposition_from_oflags(oflags) {
CreationDisposition::CREATE_ALWAYS => {
@@ -168,7 +197,14 @@ pub(crate) fn path_open(
},
}
opts.access_mode(file_access_mode_from_fdflags(fdflags, read, write).bits())
let mut access_mode = file_access_mode_from_fdflags(fdflags, read, write);
// Truncation requires the special `GENERIC_WRITE` bit set (this is why it doesn't work with append-only mode)
if is_trunc {
access_mode |= AccessMode::GENERIC_WRITE;
}
opts.access_mode(access_mode.bits())
.custom_flags(file_flags_from_fdflags(fdflags).bits())
.open(&path)
.map_err(Into::into)
@@ -195,12 +231,15 @@ fn file_access_mode_from_fdflags(
) -> AccessMode {
let mut access_mode = AccessMode::READ_CONTROL;
// Note that `GENERIC_READ` and `GENERIC_WRITE` cannot be used to properly support append-only mode
// The file-specific flags `FILE_GENERIC_READ` and `FILE_GENERIC_WRITE` are used here instead
// These flags have the same semantic meaning for file objects, but allow removal of specific permissions (see below)
if read {
access_mode.insert(AccessMode::GENERIC_READ);
access_mode.insert(AccessMode::FILE_GENERIC_READ);
}
if write {
access_mode.insert(AccessMode::GENERIC_WRITE);
access_mode.insert(AccessMode::FILE_GENERIC_WRITE);
}
// For append, grant the handle FILE_APPEND_DATA access but *not* FILE_WRITE_DATA.