WebAssembly / WebAssembly/wasi-libc
`fopen`/`openat` does not seem to preserve access flags
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 1k
- Forks
- 251
- Avg merge
- 7h 15m
- Merged PRs (30d)
- 3
Description
Tested on Linux with wasmtime v9.0.1 and wasi-sdk-20.0.
The following code (saved as open-rw.c) tries to open a file (that exists) for reading and writing:
#include <stdio.h>
#include <stdlib.h>
int main() {
// Note: using an `openat` call directly here with O_WRONLY or O_RDWR would have the same result
FILE* file = fopen("testfile", "w");
if (!file) return 1;
fclose(file);
return 0;
}
EDIT: The above code originally used the invalid flags "rw", it has been corrected to use "w"
However, when using wasi-libc, the actual syscall (for me it's openat2) is being passed O_RDONLY instead of the expected O_WRONLY. Note: same applies to O_RDWR, O_RDONLY is still passed instead.
Compiled with wasi-sdk-20.0:
$ ls testfile
testfile
$ $WASI_SDK/bin/clang --sysroot=$WASI_SDK/share/wasi-sysroot open-rw.c -o open-rw-sdk.wasm
$ strace -e trace=openat2 wasmtime --dir=. open-rw-sdk.wasm
openat2(3, "testfile", {flags=O_RDONLY|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = 5
+++ exited with 0 +++
Note that access flags are preserved in the equivalent Zig code (unless -lc to link libc is used in which case wasi-libc is built/linked and the O_RDONLY behavior occurs)
const std = @import("std");
pub fn main() !void {
var file = try std.fs.cwd().openFile("testfile", .{ .mode = .read_write });
defer file.close();
}
$ zig build-exe -target wasm32-wasi open-rw.zig -femit-bin=open-rw-zig.wasm
$ strace -e trace=openat2 wasmtime --dir=. open-rw-zig.wasm
openat2(3, "testfile", {flags=O_RDWR|O_APPEND|O_NOFOLLOW|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = 5
+++ exited with 0 +++
And are also preserved in the equivalent Rust code:
use std::fs::OpenOptions;
fn main() {
let mut _file = OpenOptions::new().read(true).write(true).open("testfile").unwrap();
}
$ strace -e trace=openat2 wasmtime --dir=. open-rw-rust.wasm
openat2(3, "testfile", {flags=O_RDWR|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = 5
+++ exited with 0 +++
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the open-rw.c reproducer with wasi-libc and tracing the fopen/openat path to the openat2 call. Follow how O_WRONLY and O_RDWR are translated, then verify that the resulting syscall preserves the requested access flags without regressing the existing read-only case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, wasm
- Domain
- backend, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100