Skip to content

Commit

Permalink
add adapter_{open|close}_badfd exports to Preview 1 adapter (byteco…
Browse files Browse the repository at this point in the history
…dealliance#7663)

* add `adapter_{open|close}_badfd` exports to Preview 1 adapter

This is to be used by `wasi-libc` to reserve file descriptors for its own use
(e.g. for sockets), ensuring that any attempt to pass them directly to Preview 1
functions will consistently return an error.

See WebAssembly/wasi-libc#447 for further details.

Signed-off-by: Joel Dice <[email protected]>

* add `preview2_adapter_badfd` test

Signed-off-by: Joel Dice <[email protected]>

---------

Signed-off-by: Joel Dice <[email protected]>
  • Loading branch information
dicej committed Dec 12, 2023
1 parent 759aa58 commit 60dacaf
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 7 deletions.
46 changes: 46 additions & 0 deletions crates/test-programs/src/bin/preview2_adapter_badfd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
fn main() {
#[link(wasm_import_module = "wasi_snapshot_preview1")]
extern "C" {
#[cfg_attr(target_arch = "wasm32", link_name = "adapter_open_badfd")]
fn adapter_open_badfd(fd: *mut u32) -> bool;

#[cfg_attr(target_arch = "wasm32", link_name = "adapter_close_badfd")]
fn adapter_close_badfd(fd: u32) -> bool;
}

unsafe {
let mut fd = 0;
assert!(adapter_open_badfd(&mut fd));

assert_eq!(wasi::fd_close(fd), Err(wasi::ERRNO_BADF));

assert_eq!(wasi::fd_fdstat_get(fd).map(drop), Err(wasi::ERRNO_BADF));

assert_eq!(wasi::fd_fdstat_set_rights(fd, 0, 0), Err(wasi::ERRNO_BADF));

let mut buffer = [0_u8; 1];
assert_eq!(
wasi::fd_read(
fd,
&[wasi::Iovec {
buf: buffer.as_mut_ptr(),
buf_len: 1
}]
),
Err(wasi::ERRNO_BADF)
);

assert_eq!(
wasi::fd_write(
fd,
&[wasi::Ciovec {
buf: buffer.as_ptr(),
buf_len: 1
}]
),
Err(wasi::ERRNO_BADF)
);

assert!(adapter_close_badfd(fd));
}
}
8 changes: 5 additions & 3 deletions crates/wasi-preview1-component-adapter/src/descriptors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub enum Descriptor {

/// Input and/or output wasi-streams, along with stream metadata.
Streams(Streams),

Bad,
}

/// Input and/or output wasi-streams, along with a stream type that
Expand Down Expand Up @@ -358,7 +360,7 @@ impl Descriptors {
) -> Result<&mut Streams, Errno> {
match self.get_mut(fd)? {
Descriptor::Streams(streams) => Ok(streams),
Descriptor::Closed(_) => Err(error),
Descriptor::Closed(_) | Descriptor::Bad => Err(error),
}
}

Expand Down Expand Up @@ -420,14 +422,14 @@ impl Descriptors {
pub fn get_read_stream(&self, fd: Fd) -> Result<&InputStream, Errno> {
match self.get(fd)? {
Descriptor::Streams(streams) => streams.get_read_stream(),
Descriptor::Closed(_) => Err(wasi::ERRNO_BADF),
Descriptor::Closed(_) | Descriptor::Bad => Err(wasi::ERRNO_BADF),
}
}

pub fn get_write_stream(&self, fd: Fd) -> Result<&OutputStream, Errno> {
match self.get(fd)? {
Descriptor::Streams(streams) => streams.get_write_stream(),
Descriptor::Closed(_) => Err(wasi::ERRNO_BADF),
Descriptor::Closed(_) | Descriptor::Bad => Err(wasi::ERRNO_BADF),
}
}
}
Expand Down
32 changes: 28 additions & 4 deletions crates/wasi-preview1-component-adapter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,26 @@ impl<T, E> TrappingUnwrap<T> for Result<T, E> {
}
}

/// Allocate a file descriptor which will generate an `ERRNO_BADF` if passed to
/// any WASI Preview 1 function implemented by this adapter.
///
/// This is intended for use by `wasi-libc` during its incremental transition
/// from WASI Preview 1 to Preview 2. It will use this function to reserve
/// descriptors for its own use, valid only for use with libc functions.
#[no_mangle]
pub unsafe extern "C" fn adapter_open_badfd(fd: *mut u32) -> bool {
State::with(|state| {
*fd = state.descriptors_mut().open(Descriptor::Bad)?;
Ok(())
}) == wasi::ERRNO_SUCCESS
}

/// Close a descriptor previously opened using `adapter_open_badfd`.
#[no_mangle]
pub unsafe extern "C" fn adapter_close_badfd(fd: u32) -> bool {
State::with(|state| state.descriptors_mut().close(fd)) == wasi::ERRNO_SUCCESS
}

#[no_mangle]
pub unsafe extern "C" fn reset_adapter_state() {
let state = get_state_ptr();
Expand Down Expand Up @@ -525,6 +545,10 @@ pub unsafe extern "C" fn fd_allocate(fd: Fd, _offset: Filesize, _len: Filesize)
#[no_mangle]
pub unsafe extern "C" fn fd_close(fd: Fd) -> Errno {
State::with(|state| {
if let Descriptor::Bad = state.descriptors().get(fd)? {
return Err(wasi::ERRNO_BADF);
}

// If there's a dirent cache entry for this file descriptor then drop
// it since the descriptor is being closed and future calls to
// `fd_readdir` should return an error.
Expand Down Expand Up @@ -669,7 +693,7 @@ pub unsafe extern "C" fn fd_fdstat_get(fd: Fd, stat: *mut Fdstat) -> Errno {
});
Ok(())
}
Descriptor::Closed(_) => Err(ERRNO_BADF),
Descriptor::Closed(_) | Descriptor::Bad => Err(ERRNO_BADF),
}
})
}
Expand Down Expand Up @@ -716,7 +740,7 @@ pub unsafe extern "C" fn fd_fdstat_set_rights(
let ds = state.descriptors();
match ds.get(fd)? {
Descriptor::Streams(..) => Ok(()),
Descriptor::Closed(..) => Err(wasi::ERRNO_BADF),
Descriptor::Closed(..) | Descriptor::Bad => Err(wasi::ERRNO_BADF),
}
})
}
Expand Down Expand Up @@ -1028,7 +1052,7 @@ pub unsafe extern "C" fn fd_read(
forget(data);
Ok(())
}
Descriptor::Closed(_) => Err(ERRNO_BADF),
Descriptor::Closed(_) | Descriptor::Bad => Err(ERRNO_BADF),
}
})
}
Expand Down Expand Up @@ -1446,7 +1470,7 @@ pub unsafe extern "C" fn fd_write(
*nwritten = nbytes;
Ok(())
}
Descriptor::Closed(_) => Err(ERRNO_BADF),
Descriptor::Closed(_) | Descriptor::Bad => Err(ERRNO_BADF),
}
})
}
Expand Down
4 changes: 4 additions & 0 deletions crates/wasi/tests/all/async_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,3 +354,7 @@ async fn preview2_stream_pollable_traps() {
"entry still has children"
)
}
#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn preview2_adapter_badfd() {
run(PREVIEW2_ADAPTER_BADFD_COMPONENT, false).await.unwrap()
}
4 changes: 4 additions & 0 deletions crates/wasi/tests/all/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,7 @@ fn preview2_stream_pollable_traps() {
"entry still has children"
)
}
#[test_log::test]
fn preview2_adapter_badfd() {
run(PREVIEW2_ADAPTER_BADFD_COMPONENT, false).unwrap()
}

0 comments on commit 60dacaf

Please sign in to comment.