Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access flags are lost when using openat from wasi-libc #9054

Open
squeek502 opened this issue Jul 31, 2024 · 1 comment
Open

Access flags are lost when using openat from wasi-libc #9054

squeek502 opened this issue Jul 31, 2024 · 1 comment
Labels
bug Incorrect behavior in the current implementation that needs fixing

Comments

@squeek502
Copy link

squeek502 commented Jul 31, 2024

Test Case

open-dir-tmpdir-rw-sdk-23.zip

Steps to Reproduce

#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    mkdirat(AT_FDCWD, "testdir", 0777);
    {
        // Opening with O_RDWR fails as expected if the dirfd is AT_FDCWD
        int dir = openat(AT_FDCWD, "testdir", O_RDWR);
        if (dir != -1) return 1;
    }

    // Open "testdir" for real now since we want to use it as the dirfd for openat
    int dir = openat(AT_FDCWD, "testdir", O_RDONLY|O_DIRECTORY);
    mkdirat(dir, "subdir", 0777);

    // Try to open the subdir with O_RDWR, this should fail with EISDIR but it succeeds
    // because the O_RDWR is lost and the openat2 syscall is called with O_RDONLY
    // instead
    int testdir = openat(dir, "subdir", O_RDWR);

    if (testdir != -1) return 1;
    return 0;
}

Built via:

$ WASI_SDK=/home/ryan/Downloads/wasi-sdk-23.0-x86_64-linux
$ $WASI_SDK/bin/clang --sysroot=$WASI_SDK/share/wasi-sysroot open-dir-tmpdir-rw.c -o open-dir-tmpdir-rw-sdk-23.wasm

Run with strace via:

$ strace -e trace=openat2 wasmtime --dir=. open-dir-tmpdir-rw-sdk-23.wasm
openat2(3, "testdir", {flags=O_RDWR|O_LARGEFILE|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = -1 EISDIR (Is a directory)
openat2(3, "testdir", {flags=O_RDONLY|O_LARGEFILE|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = 11
openat2(11, "subdir", {flags=O_RDONLY|O_LARGEFILE|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = 12
+++ exited with 1 +++

Expected Results

The test program should exit with 0, and the last openat call should have O_RDWR set instead of O_RDONLY.

Actual Results

The test program exits with 1, since the last openat call loses the O_RDWR flag and erroneously sets O_RDONLY instead.

Versions and Environment

Wasmtime version or commit: wasi-sdk 23.0 and wasmtime 23.0.1

Operating system: Linux

Architecture: x86_64

Extra Info

This is a partial regression of a bug that was fixed by #6463. This bug is not present in wasmtime versions v9.0.1-v14.0.4

wasi-libc issue: WebAssembly/wasi-libc#415

@squeek502 squeek502 added the bug Incorrect behavior in the current implementation that needs fixing label Jul 31, 2024
@alexcrichton
Copy link
Member

Thanks for the report! It's not clear to me precisely where the fault lies when debugging this. Notes that follow are intended not as a fix for this issue but what I've found so far.

I've determined that this is "just a difference" between -Spreview2={y,n} which is wasi-common (old) vs wasmtime-wasi (new (ish)). The default, wasmtime-wasi, fails this test while wasi-common passes it. It appears due to this line where fd_fdstat_get on the dir variable in the program above is returning different results. This does not look related to path_open.

In wasmtime-wasi the fd_fdstat_get call returns

result=Ok(Fdstat { fs_filetype: Directory, fs_flags: Fdflags(0x0), fs_rights_base: Rights(... | FD_READ | ...), fs_rights_inheriting: Rights(... | FD_READ | ...) })

whereas wasi-common returns:

result=Ok(Fdstat { fs_filetype: Directory, fs_flags: Fdflags(0x0), fs_rights_base: Rights(...), fs_rights_inheriting: Rights(... | FD_READ | ... | FD_WRITE | ...) })

notably there's a difference in fs_rights_inheriting. This means that with wasi-common the request to write this directory is NOT masked out, hence the error. With wasmtime-wasi the request to write is masked out because fs_rights_inheriting doesn't have the write bit set.

@pchickey as the liberator of rights (hah!) are you able to recall the history around this? Is this something where we should update wasmtime-wasi to have the same fixed return value of fs_rights_inheriting? Or should we update wasi-libc to do something different about masking here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Incorrect behavior in the current implementation that needs fixing
Projects
None yet
Development

No branches or pull requests

2 participants