From e18cbf446e7b3bb8558bc8a3e5744ab6e1b84998 Mon Sep 17 00:00:00 2001 From: rohlem Date: Mon, 18 Aug 2025 14:27:33 +0200 Subject: [PATCH 1/3] std.os: restore plain linux.faccessat syscall wrapper, only use .faccessat2 when required for flags --- lib/std/os/linux.zig | 8 ++++++-- lib/std/posix.zig | 11 ++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 0ec059dc8795..db7a66689f4c 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1238,11 +1238,15 @@ pub fn access(path: [*:0]const u8, mode: u32) usize { if (@hasField(SYS, "access")) { return syscall2(.access, @intFromPtr(path), mode); } else { - return syscall4(.faccessat, @as(usize, @bitCast(@as(isize, AT.FDCWD))), @intFromPtr(path), mode, 0); + return faccessat(AT.FDCWD, path, mode); } } -pub fn faccessat(dirfd: i32, path: [*:0]const u8, mode: u32, flags: u32) usize { +pub fn faccessat(dirfd: i32, path: [*:0]const u8, mode: u32) usize { + return syscall3(.faccessat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), mode); +} + +pub fn faccessat2(dirfd: i32, path: [*:0]const u8, mode: u32, flags: u32) usize { return syscall4(.faccessat2, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), mode, flags); } diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 90ab157f0c20..f9e3ce6ad225 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -5054,7 +5054,16 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces } else if (native_os == .wasi and !builtin.link_libc) { return faccessat(dirfd, mem.sliceTo(path, 0), mode, flags); } - switch (errno(system.faccessat(dirfd, path, mode, flags))) { + + const need_flags = (flags != 0); + const faccessat_result = switch (system) { + linux => if (need_flags) //the older, simpler syscall should stay supported, so we only need to use faccessat2 if we need flags + linux.faccessat2(dirfd, path, mode, flags) + else + linux.faccessat(dirfd, path, mode), + else => system.faccessat(dirfd, path, mode, flags), + }; + switch (errno(faccessat_result)) { .SUCCESS => return, .ACCES => return error.AccessDenied, .PERM => return error.PermissionDenied, From b433373af72ca5be8f849ddc7885bb1b2e24d8d6 Mon Sep 17 00:00:00 2001 From: rohlem Date: Mon, 18 Aug 2025 14:31:51 +0200 Subject: [PATCH 2/3] std.posix.faccessatZ: return error.UnsupportedFlags on android (seccomp sandbox would SIGSYS) --- lib/std/posix.zig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/std/posix.zig b/lib/std/posix.zig index f9e3ce6ad225..9cfcad850862 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -5055,7 +5055,12 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces return faccessat(dirfd, mem.sliceTo(path, 0), mode, flags); } + const flags_unsupported = switch (system) { + linux => builtin.abi.isAndroid() //standard android programs run in a seccomp sandbox that seems to trigger signal 31 (SIGSYS) for faccessat2 + else => false, + }; const need_flags = (flags != 0); + if (need_flags and flags_unsupported) return error.UnsupportedFlags; const faccessat_result = switch (system) { linux => if (need_flags) //the older, simpler syscall should stay supported, so we only need to use faccessat2 if we need flags linux.faccessat2(dirfd, path, mode, flags) From 6e3fdb638b324b8fa234347a1fdb0dbe302b097b Mon Sep 17 00:00:00 2001 From: rohlem Date: Mon, 18 Aug 2025 15:34:59 +0200 Subject: [PATCH 3/3] std.posix.faccessatZ: return error.UnsupportedFlags on too old linux versions --- lib/std/posix.zig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 9cfcad850862..69cacf801084 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -5056,7 +5056,8 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces } const flags_unsupported = switch (system) { - linux => builtin.abi.isAndroid() //standard android programs run in a seccomp sandbox that seems to trigger signal 31 (SIGSYS) for faccessat2 + linux => (builtin.abi.isAndroid() //standard android programs run in a seccomp sandbox that seems to trigger signal 31 (SIGSYS) for faccessat2 + or builtin.target.os.isAtLeast(.linux, .{ .major = 5, .minor = 8, .patch = 0 }) != true), //faccessat2 was introduced in Linux 5.8 else => false, }; const need_flags = (flags != 0); @@ -5086,6 +5087,10 @@ pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) Acces return error.InvalidUtf8 else return unexpectedErrno(err), + .NOSYS => |err| if (system == linux) + return error.UnsupportedFlags + else + return unexpectedErrno(err), else => |err| return unexpectedErrno(err), } }