Skip to content

[WasmFS] Node backend can't open a write-only (0200) file for writing #27847

Open

Description

@typedrat

With WasmFS, the Node backend opens a file for O_WRONLY as if it were O_RDWR: NodeState::open passes fs.openSync an fopen-style mode string, and since the only write-only strings ("w", "a") truncate or append, O_WRONLY uses "r+" (node_backend.cpp#L47-L56, with a TODO). The host then refuses a file that may be written but not read, so a file with mode 0200 can't be opened for writing at all. That includes the open(O_CREAT | O_WRONLY, 0200) that creates it, since the backend creates the file and then opens it again.

Because of #27825, the host's EACCES is currently taken for a file descriptor, so the writes below land on the host's stderr and the file stays empty. With #27825 fixed, the open() fails with EACCES instead. Either way the file can't be written. (As root the host allows the open, so this only shows up for other users.)

Version of emscripten/emsdk:

emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 6.0.11-git (f9ce3a19e)

main at f9ce3a1 with the toolchain from test/emsdk_version.txt (c366a3c2), Node.js v24.19.0, x86_64 Linux, run as a non-root user.

Test case (writeonly.c):

#include <emscripten/wasmfs.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main() {
  wasmfs_create_directory("/host", 0777, wasmfs_create_node_backend("."));

  int fd = open("/host/file", O_CREAT | O_WRONLY | O_EXCL, 0200);
  printf("open(O_CREAT | O_WRONLY, 0200) = %d\n", fd);
  ssize_t n = write(fd, "abc", 3);
  printf("write = %zd\n", n);
  close(fd);

  fd = open("/host/file", O_WRONLY);
  printf("open(O_WRONLY) = %d\n", fd);
  return 0;
}

Failing command line in full:

$ emcc -sWASMFS writeonly.c -o writeonly.js
$ node writeonly.js 2>stderr.txt
open(O_CREAT | O_WRONLY, 0200) = 3
write = 3
open(O_WRONLY) = 3
$ cat stderr.txt
abc
$ stat -c '%s bytes' file
0 bytes

Expected: write puts abc in file, and the second open() succeeds, as on Linux. Passing numeric flags (fs.constants.O_WRONLY and friends) to fs.openSync instead of a mode string would avoid the mapping problem; I have a PR ready for that.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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