Skip to content

Commit fb0c27c

Browse files
neildgopherbot
authored andcommitted
os: do not follow dangling symlinks in Root when O_CREATE|O_EXCL on AIX
OpenFile with O_CREATE|O_EXCL should not follow dangling symlinks. On AIX it does, because AIX's openat(2) apparently returns ELOOP in this case. Most Unices return EEXIST. Ensure that we never follow symlinks in the final component of the path when opening a file with O_CREATE|O_EXCL. Fixes #73924 Change-Id: I869afb7faefccb0bb29d155553a7d7e5be80467d Reviewed-on: https://go-review.googlesource.com/c/go/+/677735 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Damien Neil <dneil@google.com> Reviewed-by: Alan Donovan <adonovan@google.com>
1 parent 1cafdfb commit fb0c27c

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

src/os/root_unix.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,18 @@ func rootOpenFileNolog(root *Root, name string, flag int, perm FileMode) (*File,
8383
fd, err := doInRoot(root, name, nil, func(parent int, name string) (fd int, err error) {
8484
ignoringEINTR(func() error {
8585
fd, err = unix.Openat(parent, name, syscall.O_NOFOLLOW|syscall.O_CLOEXEC|flag, uint32(perm))
86-
if isNoFollowErr(err) || err == syscall.ENOTDIR {
87-
err = checkSymlink(parent, name, err)
86+
if err != nil {
87+
// Never follow symlinks when O_CREATE|O_EXCL, no matter
88+
// what error the OS returns.
89+
isCreateExcl := flag&(O_CREATE|O_EXCL) == (O_CREATE | O_EXCL)
90+
if !isCreateExcl && (isNoFollowErr(err) || err == syscall.ENOTDIR) {
91+
err = checkSymlink(parent, name, err)
92+
}
93+
// AIX returns ELOOP instead of EEXIST for a dangling symlink.
94+
// Convert this to EEXIST so it matches ErrExists.
95+
if isCreateExcl && err == syscall.ELOOP {
96+
err = syscall.EEXIST
97+
}
8898
}
8999
return err
90100
})

0 commit comments

Comments
 (0)