Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add adapter_{open|close}_badfd exports to Preview 1 adapter #7663

Merged
merged 2 commits into from
Dec 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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() {
"resource 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() {
"resource has children"
)
}
#[test_log::test]
fn preview2_adapter_badfd() {
run(PREVIEW2_ADAPTER_BADFD_COMPONENT, false).unwrap()
}