Skip to content

fopen/openat does not seem to preserve access flags #415

@squeek502

Description

@squeek502

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 +++

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