mirror of https://github.com/golang/go.git
os: recognize EFTYPE, EINVAL as a refusal to open a symlink
NetBSD returns EFTYPE when opening a symlink with O_NOFOLLOW. Dragonfly seems to return EINVAL. Only check for EINVAL on Dragonfly, since that seems like a bit of a broad net. Change-Id: I031357816f1fe4c370373001207e65996087597f Reviewed-on: https://go-review.googlesource.com/c/go/+/630396 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
0a0a7a5642
commit
57147256e6
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build netbsd
|
||||
|
||||
package os
|
||||
|
||||
import "syscall"
|
||||
|
||||
// isNoFollowErr reports whether err may result from O_NOFOLLOW blocking an open operation.
|
||||
func isNoFollowErr(err error) bool {
|
||||
// NetBSD returns EFTYPE, but check the other possibilities as well.
|
||||
switch err {
|
||||
case syscall.ELOOP, syscall.EMLINK, syscall.EFTYPE:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2024 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || openbsd || solaris || wasip1
|
||||
|
||||
package os
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// isNoFollowErr reports whether err may result from O_NOFOLLOW blocking an open operation.
|
||||
func isNoFollowErr(err error) bool {
|
||||
switch err {
|
||||
case syscall.ELOOP, syscall.EMLINK:
|
||||
return true
|
||||
}
|
||||
if runtime.GOOS == "dragonfly" {
|
||||
// Dragonfly appears to return EINVAL from openat in this case.
|
||||
if err == syscall.EINVAL {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -61,7 +61,7 @@ func openRootInRoot(r *Root, name string) (*Root, error) {
|
|||
fd, err := doInRoot(r, name, func(parent int, name string) (fd int, err error) {
|
||||
ignoringEINTR(func() error {
|
||||
fd, err = unix.Openat(parent, name, syscall.O_NOFOLLOW|syscall.O_CLOEXEC, 0)
|
||||
if err == syscall.ELOOP || err == syscall.EMLINK {
|
||||
if isNoFollowErr(err) {
|
||||
err = checkSymlink(parent, name, err)
|
||||
}
|
||||
return err
|
||||
|
|
@ -79,7 +79,7 @@ func rootOpenFileNolog(root *Root, name string, flag int, perm FileMode) (*File,
|
|||
fd, err := doInRoot(root, name, func(parent int, name string) (fd int, err error) {
|
||||
ignoringEINTR(func() error {
|
||||
fd, err = unix.Openat(parent, name, syscall.O_NOFOLLOW|syscall.O_CLOEXEC|flag, uint32(perm))
|
||||
if err == syscall.ELOOP || err == syscall.ENOTDIR || err == syscall.EMLINK {
|
||||
if isNoFollowErr(err) || err == syscall.ENOTDIR {
|
||||
err = checkSymlink(parent, name, err)
|
||||
}
|
||||
return err
|
||||
|
|
@ -100,7 +100,7 @@ func rootOpenDir(parent int, name string) (int, error) {
|
|||
)
|
||||
ignoringEINTR(func() error {
|
||||
fd, err = unix.Openat(parent, name, syscall.O_NOFOLLOW|syscall.O_CLOEXEC|syscall.O_DIRECTORY, 0)
|
||||
if err == syscall.ELOOP || err == syscall.ENOTDIR || err == syscall.EMLINK {
|
||||
if isNoFollowErr(err) || err == syscall.ENOTDIR {
|
||||
err = checkSymlink(parent, name, err)
|
||||
} else if err == syscall.ENOTSUP || err == syscall.EOPNOTSUPP {
|
||||
// ENOTSUP and EOPNOTSUPP are often, but not always, the same errno.
|
||||
|
|
|
|||
Loading…
Reference in New Issue