Skip to content

fd_support.rs: missing handlers for poll/select/pipe/fchmod/preadv/pwritev; mkdir/mknod/access registered with wrong spec #148

@rennergade

Description

@rennergade

Cross-referencing the syscall constants in lib/grate-rs/src/constants/syscall_numbers.rs against the FD_HANDLER_TABLE in lib/grate-rs/src/fd_support.rs. Several syscalls lind-wasm exposes are unrouted, and three path-only syscalls are registered with a DIRFD_ARG_1 spec that doesn't match their argument shape.

Missing handlers

The syscall constant exists; no entry in FD_HANDLER_TABLE:

Syscall # Why it matters Suggested spec
SYS_POLL 7 The POLL_1 spec is already defined in the file but never wired into a handler POLL_1
SYS_PIPE 22 Creates two new fds; every test using pipe() is unrouted new spec — see below
SYS_SELECT 23 Needs fd_set translation; no spec or handler today new spec
SYS_FCHMOD 91 Plain fd arg FD_ARG_1
SYS_PPOLL 271 Same shape as poll POLL_1
SYS_PIPE2 293 Like pipe but with cloexec/nonblock flag new spec
SYS_PREADV 295 Plain fd arg FD_ARG_1
SYS_PWRITEV 296 Plain fd arg FD_ARG_1

pipe/pipe2 need a new FdArgKind (or extension of the existing SOCKPAIR shape) that allocates two new vfds for kernel fds returned in an int[2] cage buffer. select needs an fd_set-translating shape; the simplest implementation is to walk the three fd_sets and remap each set bit using the existing translator, then forward.

Wrongly registered (path-only syscalls flagged as having a dirfd)

These three are path-basedarg[0] is a const char *, not a vfd. They are currently registered with DIRFD_ARG_1, which makes the handler try to translate the path pointer as a virtual fd; that will fail fdtables::translate_virtual_fd and return EBADF (or whatever errno fd_support converts that to) without ever reaching the kernel.

Syscall Currently Should be
SYS_MKDIR DIRFD_ARG_1 &[] (no fd args) — or remove from the table if nothing in the fd-routing path needs to see it
SYS_MKNOD DIRFD_ARG_1 &[]
SYS_ACCESS DIRFD_ARG_1 &[]

The dirfd-bearing siblings (openat, unlinkat, symlinkat, readlinkat) are correctly registered separately — mkdir/mknod/access are the plain path-only forms.

If these are passing tests today it's because the fs-routing layer above intercepts them before they reach fd_support's translator. The mis-registered specs are still latent bugs that bite as soon as a path happens to land near a low integer.

Bugs / dead code in fd_translation_handler_impl (worth fixing while in here)

  • should_dup2 block (lines 360–377): flags is computed but never used; get_specific_virtual_fd is called with a hardcoded 0 for cloexec instead of should_cloexec. dup3's O_CLOEXEC flag is therefore ignored on the resulting vfd entry.
  • should_poll block (lines 409–411): args[0] = pollfds_ptr as u64 runs after the syscall, on a local. Either dead code, or it was meant to write the pollfds back to cage memory with translated vfds (and should be moved to before the syscall, operating on cage memory via copy_data_between_cages, not the local).
  • EPFD branch (lines 313–317): .unwrap().get(...).unwrap() panics if the cage hasn't initialized epoll state. Should return EBADF.
  • socketpair (lines 395–407): get_unused_virtual_fd(...).unwrap() can panic on EMFILE; should error out and roll back the partial allocation.
  • Error path (line 357 if ret < 0 { return ret; }): any pollfds we translated in-place to underfds remain corrupted from the cage's perspective when the syscall fails. Should restore the original vfds on the error path.
  • SYS_MMAP fd handling (line 209): checks kernel_fd == u64::MAX to detect MAP_ANONYMOUS, but the wasm32 ABI may pass -1 differently (sign-extended 0xFFFFFFFF vs 0xFFFFFFFFFFFFFFFF). Worth confirming.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions