r12f opened issue #5313:
Thanks for filing a feature request! Please fill out the TODOs below.
Feature
This issue is created for discussing if we could make FileEntry, DirEntry and TableFileExt public. The change is fairly small and can be found here: https://github.com/futurewei-cloud/wasmtime/commit/f5c9e94446f7331b9da5837abfd33e8c45e4a95a.
I tried to search existing issues but didn't find any discussion on it specifically, hence created one to see if this makes sense. But if this is already discussed before, please feel free to resolve this as dup and I am really sorry for the trouble.
Benefit
The reason of this change is to enable host to access the raw FD of each WASI table items and maybe better access control.
If my understanding is correct, currently, the WASI table acts like fd table, and it can hold files, dirs, sockets, and maybe more things in future, e.g. special devices. And the index of each item is basically the fd from WASM program point of view.
And say, if we would like to create a new API for the items only, then it will be better to allow the host to get the raw fd or other info to call the system call, or to do deeper checks on the resource type (w/ downgrade cast maybe) and fail the call if access is not valid.
Here I am going to use socket as an example, but i know it is a bad example, since WASI has a large proposal for socket and wasi has entry for implement this function too, and here I am just using it as demo:
Say, we like to create a API: shutdown. To make it work, we need 2 things:
- Raw FD so we can call the socket API.
- The type of the FD, so we know this is a socket, not file or dir.
So to check the request, we could implement functions like below to help us get the raw fd (similar for downgrade_cast for checking resource type too):
async fn get_socket_by_fd(wasi_ctx: &mut WasiCtx, socket_fd: socket::RawFd) -> Result<AttachedSocket> { use std::os::unix::prelude::AsRawFd; use std::os::unix::prelude::FromRawFd; let wasi_fd = socket_fd.try_into().unwrap(); let wasi_table_entry = match wasi_ctx.table().get_file(wasi_fd) { Ok(v) => v, Err(_) => anyhow::bail!("Socket doesn't exist. Access denied."), }; let wasi_file_fd = wasi_table_entry.get_cap(FileCaps::POLL_READWRITE)?.pollable(); let raw_fd = match wasi_file_fd { Some(v) => v.as_raw_fd(), None => anyhow::bail!("Failed to get raw FD for socket. FD is likely not a socket."), }; let socket = unsafe { Socket::from_raw_fd(raw_fd) }; Ok(AttachedSocket(Some(socket))) }
Implementation
https://github.com/futurewei-cloud/wasmtime/commit/f5c9e94446f7331b9da5837abfd33e8c45e4a95a
Alternatives
We could also implement everything in the WASI API layer, but it also means this layer will contains all special APIs for every single type of entry, which can be messy.
Last updated: Dec 23 2024 at 12:05 UTC