Browse Source

Add Rust impl of wasmtime_ssp_fd_prestat_get

In more detail, this commit:
* makes fd_prestat_get safe
* rewrites fd_prestats_get_entry in (safe) Rust
* creates helper macros for rwlock read lock and unlock
pull/132/head
Jakub Konka 6 years ago
committed by Dan Gohman
parent
commit
5c555406ca
  1. 2
      wasmtime-wasi/build.rs
  2. 8
      wasmtime-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h
  3. 8
      wasmtime-wasi/sandboxed-system-primitives/src/locking.h
  4. 30
      wasmtime-wasi/sandboxed-system-primitives/src/posix.c
  5. 5
      wasmtime-wasi/sandboxed-system-primitives/src/posix.h
  6. 56
      wasmtime-wasi/src/host_impls.rs
  7. 2
      wasmtime-wasi/src/syscalls.rs

2
wasmtime-wasi/build.rs

@ -20,8 +20,10 @@ fn main() {
.whitelist_function("fd_prestats_init")
.whitelist_function("fd_prestats_insert")
.whitelist_function("argv_environ_init")
.whitelist_function("rwlock_.*")
.whitelist_type("__wasi_.*")
.whitelist_type("fd_table")
.whitelist_type("fd_prestat")
.whitelist_type("fd_prestats")
.whitelist_type("argv_environ_values")
.whitelist_var("__WASI_.*")

8
wasmtime-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h

@ -497,14 +497,6 @@ __wasi_errno_t wasmtime_ssp_environ_sizes_get(
size_t *environ_buf_size
) WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_prestat_get(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_prestats *prestats,
#endif
__wasi_fd_t fd,
__wasi_prestat_t *buf
) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) __attribute__((__warn_unused_result__));
__wasi_errno_t wasmtime_ssp_fd_prestat_dir_name(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_prestats *prestats,

8
wasmtime-wasi/sandboxed-system-primitives/src/locking.h

@ -83,21 +83,21 @@ struct LOCKABLE rwlock {
pthread_rwlock_t object;
};
static inline void rwlock_init(struct rwlock *lock) REQUIRES_UNLOCKED(*lock) {
void rwlock_init(struct rwlock *lock) REQUIRES_UNLOCKED(*lock) {
pthread_rwlock_init(&lock->object, NULL);
}
static inline void rwlock_rdlock(struct rwlock *lock)
void rwlock_rdlock(struct rwlock *lock)
LOCKS_SHARED(*lock) NO_LOCK_ANALYSIS {
pthread_rwlock_rdlock(&lock->object);
}
static inline void rwlock_wrlock(struct rwlock *lock)
void rwlock_wrlock(struct rwlock *lock)
LOCKS_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS {
pthread_rwlock_wrlock(&lock->object);
}
static inline void rwlock_unlock(struct rwlock *lock)
void rwlock_unlock(struct rwlock *lock)
UNLOCKS(*lock) NO_LOCK_ANALYSIS {
pthread_rwlock_unlock(&lock->object);
}

30
wasmtime-wasi/sandboxed-system-primitives/src/posix.c

@ -243,10 +243,6 @@ __wasi_errno_t wasmtime_ssp_clock_time_get(
return 0;
}
struct fd_prestat {
const char *dir;
};
void fd_prestats_init(
struct fd_prestats *pt
) {
@ -653,32 +649,6 @@ static __wasi_errno_t fd_table_insert_fd(
return fd_table_insert(ft, fo, rights_base, rights_inheriting, out);
}
__wasi_errno_t wasmtime_ssp_fd_prestat_get(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_prestats *prestats,
#endif
__wasi_fd_t fd,
__wasi_prestat_t *buf
) {
rwlock_rdlock(&prestats->lock);
struct fd_prestat *prestat;
__wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat);
if (error != 0) {
rwlock_unlock(&prestats->lock);
return error;
}
*buf = (__wasi_prestat_t) {
.pr_type = __WASI_PREOPENTYPE_DIR,
};
buf->u.dir.pr_name_len = strlen(prestat->dir);
rwlock_unlock(&prestats->lock);
return 0;
}
__wasi_errno_t wasmtime_ssp_fd_prestat_dir_name(
#if !defined(WASMTIME_SSP_STATIC_CURFDS)
struct fd_prestats *prestats,

5
wasmtime-wasi/sandboxed-system-primitives/src/posix.h

@ -18,9 +18,12 @@
#include "locking.h"
struct fd_entry;
struct fd_prestat;
struct syscalls;
struct fd_prestat {
const char *dir;
};
struct fd_table {
struct rwlock lock;
struct fd_entry *entries;

56
wasmtime-wasi/src/host_impls.rs

@ -88,10 +88,66 @@ fn convert_errno(error: Errno) -> host::__wasi_errno_t {
}
}
fn fd_prestats_get_entry(
pt: &host::fd_prestats,
fd: host::__wasi_fd_t,
) -> Option<&host::fd_prestat> {
// Test for file descriptor existence
if fd as usize >= pt.size {
return None;
}
let prestat = unsafe { &*pt.prestats.add(fd as usize) };
if prestat.dir == ::std::ptr::null() {
return None;
}
Some(prestat)
}
macro_rules! rwlock_rdlock {
($prestats:expr) => {
unsafe {
host::rwlock_rdlock(&mut (*$prestats).lock as *mut host::rwlock);
}
};
}
macro_rules! rwlock_unlock {
($prestats:expr) => {
unsafe {
host::rwlock_unlock(&mut (*$prestats).lock as *mut host::rwlock);
}
};
}
pub fn wasmtime_ssp_proc_exit(rval: wasm32::__wasi_exitcode_t) {
::std::process::exit(rval as i32)
}
pub fn wasmtime_ssp_fd_prestat_get(
prestats: &mut host::fd_prestats,
fd: host::__wasi_fd_t,
buf: &mut host::__wasi_prestat_t,
) -> host::__wasi_errno_t {
rwlock_rdlock!(prestats);
let ret_code = if let Some(prestat) = fd_prestats_get_entry(prestats, fd) {
(*buf).pr_type = host::__WASI_PREOPENTYPE_DIR as host::__wasi_preopentype_t;
unsafe {
let dir_name = ::std::ffi::CStr::from_ptr((*prestat).dir).to_str().unwrap();
(*buf).u.dir.pr_name_len = dir_name.len();
}
host::__WASI_ESUCCESS
} else {
host::__WASI_EBADF
};
rwlock_unlock!(prestats);
ret_code
}
pub fn wasmtime_ssp_sched_yield() -> host::__wasi_errno_t {
unsafe {
if libc::sched_yield() < 0 {

2
wasmtime-wasi/src/syscalls.rs

@ -380,7 +380,7 @@ syscalls! {
return return_encoded_errno(e);
}
let e = host::wasmtime_ssp_fd_prestat_get(prestats, fd, &mut host_buf);
let e = host_impls::wasmtime_ssp_fd_prestat_get(&mut *prestats, fd, &mut host_buf);
encode_prestat_byref(vmctx, buf, host_buf);

Loading…
Cancel
Save