mirror of
https://github.com/golang/go
synced 2024-11-23 04:20:03 -07:00
syscall: fix opening of directories on wasip1
Go programs targeting GOOS=wasip1 were failing to open directories when executed with runtimes like wasmtime or wasmedge due to requesting rights for operations that are not supported on directories such as fd_read, fd_write, etc... This change addresses the issue by performing a second path_open when observing EISDIR, and masking the requested rights to only ask for permissions to perform operations supported by a directory. Change-Id: Ibf65acf4a38bc848a649f41dbd026507d8b63c82 Reviewed-on: https://go-review.googlesource.com/c/go/+/490755 Auto-Submit: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
4badad8d47
commit
4b66502dda
@ -100,6 +100,63 @@ const (
|
|||||||
fullRights = rights(^uint32(0))
|
fullRights = rights(^uint32(0))
|
||||||
readRights = rights(RIGHT_FD_READ | RIGHT_FD_READDIR)
|
readRights = rights(RIGHT_FD_READ | RIGHT_FD_READDIR)
|
||||||
writeRights = rights(RIGHT_FD_DATASYNC | RIGHT_FD_WRITE | RIGHT_FD_ALLOCATE | RIGHT_PATH_FILESTAT_SET_SIZE)
|
writeRights = rights(RIGHT_FD_DATASYNC | RIGHT_FD_WRITE | RIGHT_FD_ALLOCATE | RIGHT_PATH_FILESTAT_SET_SIZE)
|
||||||
|
|
||||||
|
// Some runtimes have very strict expectations when it comes to which
|
||||||
|
// rights can be enabled on files opened by path_open. The fileRights
|
||||||
|
// constant is used as a mask to retain only bits for operations that
|
||||||
|
// are supported on files.
|
||||||
|
fileRights rights = RIGHT_FD_DATASYNC |
|
||||||
|
RIGHT_FD_READ |
|
||||||
|
RIGHT_FD_SEEK |
|
||||||
|
RIGHT_FDSTAT_SET_FLAGS |
|
||||||
|
RIGHT_FD_SYNC |
|
||||||
|
RIGHT_FD_TELL |
|
||||||
|
RIGHT_FD_WRITE |
|
||||||
|
RIGHT_FD_ADVISE |
|
||||||
|
RIGHT_FD_ALLOCATE |
|
||||||
|
RIGHT_PATH_CREATE_DIRECTORY |
|
||||||
|
RIGHT_PATH_CREATE_FILE |
|
||||||
|
RIGHT_PATH_LINK_SOURCE |
|
||||||
|
RIGHT_PATH_LINK_TARGET |
|
||||||
|
RIGHT_PATH_OPEN |
|
||||||
|
RIGHT_FD_READDIR |
|
||||||
|
RIGHT_PATH_READLINK |
|
||||||
|
RIGHT_PATH_RENAME_SOURCE |
|
||||||
|
RIGHT_PATH_RENAME_TARGET |
|
||||||
|
RIGHT_PATH_FILESTAT_GET |
|
||||||
|
RIGHT_PATH_FILESTAT_SET_SIZE |
|
||||||
|
RIGHT_PATH_FILESTAT_SET_TIMES |
|
||||||
|
RIGHT_FD_FILESTAT_GET |
|
||||||
|
RIGHT_FD_FILESTAT_SET_SIZE |
|
||||||
|
RIGHT_FD_FILESTAT_SET_TIMES |
|
||||||
|
RIGHT_PATH_SYMLINK |
|
||||||
|
RIGHT_PATH_REMOVE_DIRECTORY |
|
||||||
|
RIGHT_PATH_UNLINK_FILE |
|
||||||
|
RIGHT_POLL_FD_READWRITE
|
||||||
|
|
||||||
|
// Runtimes like wasmtime and wasmedge will refuse to open directories
|
||||||
|
// if the rights requested by the application exceed the operations that
|
||||||
|
// can be performed on a directory.
|
||||||
|
dirRights rights = RIGHT_FD_SEEK |
|
||||||
|
RIGHT_FDSTAT_SET_FLAGS |
|
||||||
|
RIGHT_FD_SYNC |
|
||||||
|
RIGHT_PATH_CREATE_DIRECTORY |
|
||||||
|
RIGHT_PATH_CREATE_FILE |
|
||||||
|
RIGHT_PATH_LINK_SOURCE |
|
||||||
|
RIGHT_PATH_LINK_TARGET |
|
||||||
|
RIGHT_PATH_OPEN |
|
||||||
|
RIGHT_FD_READDIR |
|
||||||
|
RIGHT_PATH_READLINK |
|
||||||
|
RIGHT_PATH_RENAME_SOURCE |
|
||||||
|
RIGHT_PATH_RENAME_TARGET |
|
||||||
|
RIGHT_PATH_FILESTAT_GET |
|
||||||
|
RIGHT_PATH_FILESTAT_SET_SIZE |
|
||||||
|
RIGHT_PATH_FILESTAT_SET_TIMES |
|
||||||
|
RIGHT_FD_FILESTAT_GET |
|
||||||
|
RIGHT_FD_FILESTAT_SET_TIMES |
|
||||||
|
RIGHT_PATH_SYMLINK |
|
||||||
|
RIGHT_PATH_REMOVE_DIRECTORY |
|
||||||
|
RIGHT_PATH_UNLINK_FILE
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://github.com/WebAssembly/WASI/blob/a2b96e81c0586125cc4dc79a5be0b78d9a059925/legacy/preview1/docs.md#-fd_closefd-fd---result-errno
|
// https://github.com/WebAssembly/WASI/blob/a2b96e81c0586125cc4dc79a5be0b78d9a059925/legacy/preview1/docs.md#-fd_closefd-fd---result-errno
|
||||||
@ -435,11 +492,11 @@ func Open(path string, openmode int, perm uint32) (int, error) {
|
|||||||
var rights rights
|
var rights rights
|
||||||
switch openmode & (O_RDONLY | O_WRONLY | O_RDWR) {
|
switch openmode & (O_RDONLY | O_WRONLY | O_RDWR) {
|
||||||
case O_RDONLY:
|
case O_RDONLY:
|
||||||
rights = fullRights & ^writeRights
|
rights = fileRights & ^writeRights
|
||||||
case O_WRONLY:
|
case O_WRONLY:
|
||||||
rights = fullRights & ^readRights
|
rights = fileRights & ^readRights
|
||||||
case O_RDWR:
|
case O_RDWR:
|
||||||
rights = fullRights
|
rights = fileRights
|
||||||
}
|
}
|
||||||
|
|
||||||
var fdflags fdflags
|
var fdflags fdflags
|
||||||
@ -458,10 +515,32 @@ func Open(path string, openmode int, perm uint32) (int, error) {
|
|||||||
pathLen,
|
pathLen,
|
||||||
oflags,
|
oflags,
|
||||||
rights,
|
rights,
|
||||||
fullRights,
|
fileRights,
|
||||||
fdflags,
|
fdflags,
|
||||||
unsafe.Pointer(&fd),
|
unsafe.Pointer(&fd),
|
||||||
)
|
)
|
||||||
|
if errno == EISDIR && oflags == 0 && fdflags == 0 && ((rights & writeRights) == 0) {
|
||||||
|
// wasmtime and wasmedge will error if attempting to open a directory
|
||||||
|
// because we are asking for too many rights. However, we cannot
|
||||||
|
// determine ahread of time if the path we are about to open is a
|
||||||
|
// directory, so instead we fallback to a second call to path_open with
|
||||||
|
// a more limited set of rights.
|
||||||
|
//
|
||||||
|
// This approach is subject to a race if the file system is modified
|
||||||
|
// concurrently, so we also inject OFLAG_DIRECTORY to ensure that we do
|
||||||
|
// not accidentally open a file which is not a directory.
|
||||||
|
errno = path_open(
|
||||||
|
dirFd,
|
||||||
|
LOOKUP_SYMLINK_FOLLOW,
|
||||||
|
pathPtr,
|
||||||
|
pathLen,
|
||||||
|
oflags|OFLAG_DIRECTORY,
|
||||||
|
rights&dirRights,
|
||||||
|
fileRights,
|
||||||
|
fdflags,
|
||||||
|
unsafe.Pointer(&fd),
|
||||||
|
)
|
||||||
|
}
|
||||||
return int(fd), errnoErr(errno)
|
return int(fd), errnoErr(errno)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user