os: fix Root test failures on AIX AIX has two behaviours that differ from other platforms, causing test failures introduced by the CVE-2026-39822 fix (CL 797661). Paths ending in / on non-directory targets may succeed on AIX instead of returning ENOTDIR. This affects opening a regular file as "target/" and following a symlink whose stored target ends in "/" (e.g. "link -> file/"). Skip the affected consistency test cases on AIX. AIX allows read(2) on a directory file descriptor, returning directory bytes instead of EISDIR. This causes root.ReadFile on a directory target to succeed with err=nil. AIX is added to the exception similar to NetBSD. Neither change affects the security fix; AIX was not vulnerable to the original issue because it does not follow symlinks through a trailing slash when O_NOFOLLOW is set. Fixes #80382 Change-Id: I8ddb3bc841c3d94bfeb91659dc6b3216a6a0d992 Reviewed-on: https://go-review.googlesource.com/c/go/+/840085 Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/src/os/root_test.go b/src/os/root_test.go index 8d20ba0..c947edf 100644 --- a/src/os/root_test.go +++ b/src/os/root_test.go
@@ -1139,6 +1139,13 @@ // os.Create returns ENOTDIR or EISDIR depending on the platform. return runtime.GOOS == "js" }, + check: func(t *testing.T) { + if runtime.GOOS == "aix" { + // On AIX, opening a regular file with a trailing slash succeeds, + // whereas os.Root returns ENOTDIR. + t.Skip("known inconsistency on aix") + } + }, }, { name: "file in path", fs: []string{ @@ -1210,6 +1217,13 @@ "link => file/", }, open: "link", + check: func(t *testing.T) { + if runtime.GOOS == "aix" { + // On AIX, a symlink whose stored target ends in a slash is + // followed successfully, whereas os.Root returns ENOTDIR. + t.Skip("known inconsistency on aix") + } + }, }, { name: "long file name", open: strings.Repeat("a", 500), @@ -2273,6 +2287,15 @@ } } + if runtime.GOOS == "aix" { + // On AIX, paths ending in / on non-directory targets may succeed + // instead of returning ENOTDIR, so root and non-root results + // are inconsistent. See https://go.dev/issue/80382. + if rootTest.source.anySlashSuffix() || rootTest.target.anySlashSuffix() { + return + } + } + osResult, osErr := f(t, osTest) t.Cleanup(func() { @@ -3279,9 +3302,9 @@ case runtime.GOOS == "plan9": // Plan9 lets you read from directories. // Just rely on consistency checks. - case runtime.GOOS == "netbsd": + case runtime.GOOS == "netbsd", runtime.GOOS == "aix": // See https://go.dev/issue/80322: - // NetBSD builder appears to be succeeding on read-from-dir as well. + // NetBSD and AIX builders appear to be succeeding on read-from-dir as well. return "", gotErr case test.target.finalKind() == testFileDir: test.wantError(t, gotErr, errAny)