authorgravatar for pat.github@tullmann.orgPat Tullmann <pat.github@tullmann.org> 2025-02-18 17:16:13-08:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-03-24 16:20:45+01:00
log02373eb2a59f4a16a06460c244958e236b1c5291
treed76d3dbdccbe37ac7728dd05e91888b8296eddaa
parentf304d8e50afac12ac209f850ced4f9ddf3bcff3b

lib/std/: WASI code should follow POSIX semantics for AccessDenied/PermissionDenied

Use error.AccessDenied for permissions (rights) failures on Wasi (`EACCES`) and error.PermissionDenied (`EPERM`) for systemic failures. And pass-through underlying Wasi errors (PermissionDenied or AccessDenied) without mapping.

2 files changed, 11 insertions(+), 16 deletions(-)

lib/std/fs/test.zig+1-1
...@@ -383,7 +383,7 @@ test "openDirAbsolute" {...@@ -383,7 +383,7 @@ test "openDirAbsolute" {
383383
384test "openDir cwd parent '..'" {384test "openDir cwd parent '..'" {
385 var dir = fs.cwd().openDir("..", .{}) catch |err| {385 var dir = fs.cwd().openDir("..", .{}) catch |err| {
386 if (native_os == .wasi and err == error.AccessDenied) {386 if (native_os == .wasi and err == error.PermissionDenied) {
387 return; // This is okay. WASI disallows escaping from the fs sandbox387 return; // This is okay. WASI disallows escaping from the fs sandbox
388 }388 }
389 return err;389 return err;
lib/std/posix.zig+10-15
...@@ -1740,7 +1740,7 @@ pub fn openatWasi(...@@ -1740,7 +1740,7 @@ pub fn openatWasi(
1740 .NOMEM => return error.SystemResources,1740 .NOMEM => return error.SystemResources,
1741 .NOSPC => return error.NoSpaceLeft,1741 .NOSPC => return error.NoSpaceLeft,
1742 .NOTDIR => return error.NotDir,1742 .NOTDIR => return error.NotDir,
1743 .PERM => return error.AccessDenied,1743 .PERM => return error.PermissionDenied,
1744 .EXIST => return error.PathAlreadyExists,1744 .EXIST => return error.PathAlreadyExists,
1745 .BUSY => return error.DeviceBusy,1745 .BUSY => return error.DeviceBusy,
1746 .NOTCAPABLE => return error.AccessDenied,1746 .NOTCAPABLE => return error.AccessDenied,
...@@ -2178,7 +2178,7 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c...@@ -2178,7 +2178,7 @@ pub fn symlinkatWasi(target_path: []const u8, newdirfd: fd_t, sym_link_path: []c
2178 .INVAL => unreachable,2178 .INVAL => unreachable,
2179 .BADF => unreachable,2179 .BADF => unreachable,
2180 .ACCES => return error.AccessDenied,2180 .ACCES => return error.AccessDenied,
2181 .PERM => return error.AccessDenied,2181 .PERM => return error.PermissionDenied,
2182 .DQUOT => return error.DiskQuota,2182 .DQUOT => return error.DiskQuota,
2183 .EXIST => return error.PathAlreadyExists,2183 .EXIST => return error.PathAlreadyExists,
2184 .IO => return error.FileSystem,2184 .IO => return error.FileSystem,
...@@ -2502,7 +2502,7 @@ pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatErro...@@ -2502,7 +2502,7 @@ pub fn unlinkatWasi(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatErro
2502 switch (res) {2502 switch (res) {
2503 .SUCCESS => return,2503 .SUCCESS => return,
2504 .ACCES => return error.AccessDenied,2504 .ACCES => return error.AccessDenied,
2505 .PERM => return error.AccessDenied,2505 .PERM => return error.PermissionDenied,
2506 .BUSY => return error.FileBusy,2506 .BUSY => return error.FileBusy,
2507 .FAULT => unreachable,2507 .FAULT => unreachable,
2508 .IO => return error.FileSystem,2508 .IO => return error.FileSystem,
...@@ -2698,7 +2698,7 @@ fn renameatWasi(old: RelativePathWasi, new: RelativePathWasi) RenameError!void {...@@ -2698,7 +2698,7 @@ fn renameatWasi(old: RelativePathWasi, new: RelativePathWasi) RenameError!void {
2698 switch (wasi.path_rename(old.dir_fd, old.relative_path.ptr, old.relative_path.len, new.dir_fd, new.relative_path.ptr, new.relative_path.len)) {2698 switch (wasi.path_rename(old.dir_fd, old.relative_path.ptr, old.relative_path.len, new.dir_fd, new.relative_path.ptr, new.relative_path.len)) {
2699 .SUCCESS => return,2699 .SUCCESS => return,
2700 .ACCES => return error.AccessDenied,2700 .ACCES => return error.AccessDenied,
2701 .PERM => return error.AccessDenied,2701 .PERM => return error.PermissionDenied,
2702 .BUSY => return error.FileBusy,2702 .BUSY => return error.FileBusy,
2703 .DQUOT => return error.DiskQuota,2703 .DQUOT => return error.DiskQuota,
2704 .FAULT => unreachable,2704 .FAULT => unreachable,
...@@ -2903,7 +2903,7 @@ pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: mode_t) MakeDir...@@ -2903,7 +2903,7 @@ pub fn mkdiratWasi(dir_fd: fd_t, sub_dir_path: []const u8, mode: mode_t) MakeDir
2903 .SUCCESS => return,2903 .SUCCESS => return,
2904 .ACCES => return error.AccessDenied,2904 .ACCES => return error.AccessDenied,
2905 .BADF => unreachable,2905 .BADF => unreachable,
2906 .PERM => return error.AccessDenied,2906 .PERM => return error.PermissionDenied,
2907 .DQUOT => return error.DiskQuota,2907 .DQUOT => return error.DiskQuota,
2908 .EXIST => return error.PathAlreadyExists,2908 .EXIST => return error.PathAlreadyExists,
2909 .FAULT => unreachable,2909 .FAULT => unreachable,
...@@ -4952,19 +4952,14 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr...@@ -4952,19 +4952,14 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr
4952 } else if (native_os == .wasi and !builtin.link_libc) {4952 } else if (native_os == .wasi and !builtin.link_libc) {
4953 const resolved: RelativePathWasi = .{ .dir_fd = dirfd, .relative_path = path };4953 const resolved: RelativePathWasi = .{ .dir_fd = dirfd, .relative_path = path };
49544954
4955 const st = blk: {4955 const st = try std.os.fstatat_wasi(dirfd, path, .{
4956 break :blk std.os.fstatat_wasi(dirfd, path, .{4956 .SYMLINK_FOLLOW = (flags & AT.SYMLINK_NOFOLLOW) == 0,
4957 .SYMLINK_FOLLOW = (flags & AT.SYMLINK_NOFOLLOW) == 0,4957 });
4958 });
4959 } catch |err| switch (err) {
4960 error.AccessDenied => return error.PermissionDenied,
4961 else => |e| return e,
4962 };
49634958
4964 if (mode != F_OK) {4959 if (mode != F_OK) {
4965 var directory: wasi.fdstat_t = undefined;4960 var directory: wasi.fdstat_t = undefined;
4966 if (wasi.fd_fdstat_get(resolved.dir_fd, &directory) != .SUCCESS) {4961 if (wasi.fd_fdstat_get(resolved.dir_fd, &directory) != .SUCCESS) {
4967 return error.PermissionDenied;4962 return error.AccessDenied;
4968 }4963 }
49694964
4970 var rights: wasi.rights_t = .{};4965 var rights: wasi.rights_t = .{};
...@@ -4984,7 +4979,7 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr...@@ -4984,7 +4979,7 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr
4984 const rights_int: u64 = @bitCast(rights);4979 const rights_int: u64 = @bitCast(rights);
4985 const inheriting_int: u64 = @bitCast(directory.fs_rights_inheriting);4980 const inheriting_int: u64 = @bitCast(directory.fs_rights_inheriting);
4986 if ((rights_int & inheriting_int) != rights_int) {4981 if ((rights_int & inheriting_int) != rights_int) {
4987 return error.PermissionDenied;4982 return error.AccessDenied;
4988 }4983 }
4989 }4984 }
4990 return;4985 return;