Skip to content
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
3 changes: 3 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ Unreleased.
* Fix a panic in the host caused by preview1 guests using `fd_renumber`.
[CVE-2025-53901](https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-fm79-3f68-h2fc).

* Fix a panic in the preview1 adapter caused by guests using `fd_renumber`.
[#11277](https://github.com/bytecodealliance/wasmtime/pull/11277)

--------------------------------------------------------------------------------

Release notes for previous releases of Wasmtime can be found on the respective
Expand Down
10 changes: 9 additions & 1 deletion crates/test-programs/src/bin/preview1_renumber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,15 @@ unsafe fn test_renumber(dir_fd: wasip1::Fd) {
"file descriptor range check",
);

wasip1::fd_renumber(fd_file3, u32::MAX).expect("renumbering file FD to `u32::MAX`");
wasip1::fd_renumber(fd_file3, 127).expect("renumbering FD to 127");
match wasip1::fd_renumber(127, u32::MAX) {
Err(wasip1::ERRNO_NOMEM) => {
// The preview1 adapter cannot handle more than 128 descriptors
eprintln!("fd_renumber({fd_file3}, {}) returned NOMEM", u32::MAX)
}
res => res.expect("renumbering FD to `u32::MAX`"),
}

let fd_file4 = wasip1::path_open(
dir_fd,
0,
Expand Down
30 changes: 17 additions & 13 deletions crates/wasi-preview1-component-adapter/src/descriptors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,8 @@ impl Descriptors {
.ok_or(wasi::ERRNO_BADF)
}

// Internal: close a fd, returning the descriptor.
fn close_(&mut self, fd: Fd) -> Result<Descriptor, Errno> {
// Close an fd.
pub fn close(&mut self, fd: Fd) -> Result<(), Errno> {
// Throw an error if closing an fd which is already closed
match self.get(fd)? {
Descriptor::Closed(_) => Err(wasi::ERRNO_BADF)?,
Expand All @@ -341,12 +341,7 @@ impl Descriptors {
let last_closed = self.closed;
let prev = std::mem::replace(self.get_mut(fd)?, Descriptor::Closed(last_closed));
self.closed = Some(fd);
Ok(prev)
}

// Close an fd.
pub fn close(&mut self, fd: Fd) -> Result<(), Errno> {
drop(self.close_(fd)?);
drop(prev);
Ok(())
}

Expand All @@ -366,11 +361,20 @@ impl Descriptors {
while self.table_len.get() as u32 <= to_fd {
self.push_closed()?;
}
// Then, close from_fd and put its contents into to_fd:
let desc = self.close_(from_fd)?;
// TODO FIXME if this overwrites a preopen, do we need to clear it from the preopen table?
*self.get_mut(to_fd)? = desc;

// Throw an error if renumbering a closed fd
match self.get(from_fd)? {
Descriptor::Closed(_) => Err(wasi::ERRNO_BADF)?,
_ => {}
}
// Close from_fd and put its contents into to_fd
if from_fd != to_fd {
// Mutate the descriptor to be closed, and push the closed fd onto the head of the linked list:
let last_closed = self.closed;
let desc = std::mem::replace(self.get_mut(from_fd)?, Descriptor::Closed(last_closed));
self.closed = Some(from_fd);
// TODO FIXME if this overwrites a preopen, do we need to clear it from the preopen table?
*self.get_mut(to_fd)? = desc;
}
Ok(())
}

Expand Down
1 change: 0 additions & 1 deletion crates/wasi/tests/all/p2/async_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,6 @@ async fn preview1_remove_nonempty_directory() {
.await
.unwrap()
}
#[ignore = "panics"]
#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn preview1_renumber() {
run(PREVIEW1_RENUMBER_COMPONENT, false).await.unwrap()
Expand Down
1 change: 0 additions & 1 deletion crates/wasi/tests/all/p2/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ fn preview1_remove_directory() {
fn preview1_remove_nonempty_directory() {
run(PREVIEW1_REMOVE_NONEMPTY_DIRECTORY_COMPONENT, false).unwrap()
}
#[ignore = "panics"]
#[test_log::test]
fn preview1_renumber() {
run(PREVIEW1_RENUMBER_COMPONENT, false).unwrap()
Expand Down
Loading