-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Check the file type after open() in Dir.openFile() when using WASI #15824
Conversation
When the `O_DIRECTORY` flag is not present, Wasmtime now opens files and directories the same way, and returns a descriptor in any case. So, explicitly check the file type after opening it, and return `err.IsDir` if what we actually have is a directory. Fixes the `lib/std/fs` `"file operations on directories"` test on WASI with Wasmtime 9.0.0
I would guess that wasmtime behaves differently here on Windows vs non-Windows (i.e. I don't think the I'm having a very hard time navigating wasmtime/wasi spec/etc to understand if/where this behavior is specified, why it changed, how it changed, etc. My naive first impression is that it seems like it'd be a wasmtime/wasi spec bug, assuming at least that wasmtime wants each host platform to behave the same; from #13157 (comment):
|
Here is where the change may have been introduced. I think the intent was to be In line with how |
Thanks for the link, that makes sense. I was wrong about Windows needing file or directory specified in its open calls; see d3f87f8. Perhaps the wasi spec would be interested in a |
Also related: #5732 Lines 458 to 460 in a0652fb
I wonder if this would be considered a wasmtime bug, in that it seems like it's allowing opening directories for writing. EDIT: Actually, why isn't the |
I can't reproduce the $ wasmtime --version
wasmtime-cli 9.0.1
$ zig version
0.11.0-dev.3277+a0652fb93
$ zig test --zig-lib-dir lib --main-pkg-path lib/std -target wasm32-wasi --test-cmd wasmtime --test-cmd --dir=. --test-cmd-bin lib/std/std.zig
...
1106/2505 test.file operations on directories... OK
...
2354 passed; 151 skipped; 0 failed. |
Still failing for me with wasmtime 9.0.1:
|
Is that the intended behavior, or a wasmtime bug? /cc @jameysharp |
I don't understand what this test is trying to do, and I also don't understand WASI very well, either in spec or in implementation. So I don't know how to answer that question. I do think the idea of a And I'm curious about this as well:
|
@jameysharp The test opens a directory (without I think this is a recent change. On CI which is still running Wasmtime 2.0.2, the test passes. |
The failure is related to linking libc. I can reproduce it if I add |
EDIT: This comment can be ignored (only the "Here's how I'm testing" part is relevant), see the next comment for better info Looks like // notes: 0x1b5 = 437 which is openat2, 0x3 is the cwd's fd, 0x18 is sizeof(struct open_how)
syscall_0x1b5(0x3, 0x7ffe0db39fc8, 0x7ffe0db39f68, 0x18, 0, 0) = 0x5 According to the openat2 docs, all the possible errors of Here's how I'm testing: // open-dir-rw.zig
const std = @import("std");
pub fn main() !void {
const test_dir_name = "testdir";
try std.fs.cwd().makePath("testdir");
try std.testing.expectError(error.IsDir, std.fs.cwd().openFile(test_dir_name, .{ .mode = .read_write }));
}
or with strace
EDIT: Here's the relevant line from
So most likely EDIT#2: I think this is as far as I can go for now. My debugging skills are not up to par for this task, but hopefully this is enough of a starting point that someone with better debugging skills can figure out what's happening here. |
Updated With openat2(3, "testdir", {flags=O_RDONLY|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = 5
Without openat2(3, "testdir", {flags=O_RDWR|O_APPEND|O_NOFOLLOW|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = -1 EISDIR (Is a directory) (stack trace is the same as above) EDIT: Note also that changing EDIT: The bug doesn't seem to be on the Zig side. If I add std.debug.print("openatZ RDWR={}\n", .{flags & O.RDWR == O.RDWR}); before this line: Line 1734 in bfe02ff
then it prints:
EDIT#2: The equivalent C program compiled to wasm exhibits the same (buggy) behavior: #include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main() {
int rc = openat(AT_FDCWD, "testdir", O_RDWR);
return 0;
}
EDIT#3: Can also reproduce this with
$ strace -e trace=openat2 wasmtime --dir=. open-dir-rw-c-sdk.wasm
openat2(3, "testdir", {flags=O_RDONLY|O_CLOEXEC, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = 5 EDIT#4: Made a |
The test is failing since this exact commit in |
This is actually a bug in Wasmtime: bytecodealliance/wasmtime#6462 And more importantly, they are planning to released a fixed version soon, so we don't need the extra That was also a good reminder that we should constantly keep Thanks a lot @squeek502 for your help and investigation! |
When the
O_DIRECTORY
flag is not present, Wasmtime now opens files and directories the same way, and returns a descriptor in any case.So, explicitly check the file type after opening it, and return
err.IsDir
if what we actually have is a directory.Fixes the
lib/std/fs
"file operations on directories"
test on WASI with Wasmtime 9.0.0