diff options
-rw-r--r-- | internal/syscallcompat/emulate.go | 20 | ||||
-rw-r--r-- | internal/syscallcompat/emulate_test.go | 29 | ||||
-rw-r--r-- | internal/syscallcompat/sys_common.go | 20 | ||||
-rw-r--r-- | internal/syscallcompat/sys_common_test.go | 29 | ||||
-rw-r--r-- | internal/syscallcompat/sys_darwin.go | 4 | ||||
-rw-r--r-- | internal/syscallcompat/sys_linux.go | 18 |
6 files changed, 49 insertions, 71 deletions
diff --git a/internal/syscallcompat/emulate.go b/internal/syscallcompat/emulate.go index c0a0d09..35e17c6 100644 --- a/internal/syscallcompat/emulate.go +++ b/internal/syscallcompat/emulate.go @@ -11,26 +11,6 @@ import ( var chdirMutex sync.Mutex -// emulateOpenat emulates the syscall for platforms that don't have it -// in the kernel (darwin). -func emulateOpenat(dirfd int, path string, flags int, mode uint32) (int, error) { - if !filepath.IsAbs(path) { - chdirMutex.Lock() - defer chdirMutex.Unlock() - cwd, err := syscall.Open(".", syscall.O_RDONLY, 0) - if err != nil { - return -1, err - } - defer syscall.Close(cwd) - err = syscall.Fchdir(dirfd) - if err != nil { - return -1, err - } - defer syscall.Fchdir(cwd) - } - return syscall.Open(path, flags, mode) -} - // emulateRenameat emulates the syscall for platforms that don't have it // in the kernel (darwin). func emulateRenameat(olddirfd int, oldpath string, newdirfd int, newpath string) error { diff --git a/internal/syscallcompat/emulate_test.go b/internal/syscallcompat/emulate_test.go index 2cf2698..9b1994b 100644 --- a/internal/syscallcompat/emulate_test.go +++ b/internal/syscallcompat/emulate_test.go @@ -9,35 +9,6 @@ import ( "golang.org/x/sys/unix" ) -func TestEmulateOpenat(t *testing.T) { - _, err := emulateOpenat(tmpDirFd, "testOpenAt", 0, 0) - if err == nil { - t.Errorf("should have failed") - } - fd, err := os.Create(tmpDir + "/testOpenAt") - if err != nil { - t.Fatal(err) - } - fd.Close() - rawFd, err := emulateOpenat(tmpDirFd, "testOpenAt", 0, 0) - if err != nil { - t.Fatal(err) - } - defer syscall.Close(rawFd) - if rawFd < 0 { - t.Fatalf("rawFd=%d", rawFd) - } - // Test with absolute path - rawFd, err = emulateOpenat(-1, tmpDir+"/testOpenAt", 0, 0) - if err != nil { - t.Fatal(err) - } - defer syscall.Close(rawFd) - if rawFd < 0 { - t.Fatalf("rawFd=%d", rawFd) - } -} - func TestEmulateRenameat(t *testing.T) { os.Mkdir(tmpDir+"/dir1", 0700) dir1, err := os.Open(tmpDir + "/dir1") diff --git a/internal/syscallcompat/sys_common.go b/internal/syscallcompat/sys_common.go index a1aa66d..a5b2c05 100644 --- a/internal/syscallcompat/sys_common.go +++ b/internal/syscallcompat/sys_common.go @@ -5,6 +5,8 @@ import ( "syscall" "golang.org/x/sys/unix" + + "github.com/rfjakob/gocryptfs/internal/tlog" ) // PATH_MAX is the maximum allowed path length on Linux. @@ -42,6 +44,24 @@ func Faccessat(dirfd int, path string, mode uint32) error { return unix.Faccessat(dirfd, path, mode, 0) } +// Openat wraps the Openat syscall. +func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + if flags&syscall.O_CREAT != 0 { + // O_CREAT should be used with O_EXCL. O_NOFOLLOW has no effect with O_EXCL. + if flags&syscall.O_EXCL == 0 { + tlog.Warn.Printf("Openat: O_CREAT without O_EXCL: flags = %#x", flags) + flags |= syscall.O_EXCL + } + } else { + // If O_CREAT is not used, we should use O_NOFOLLOW + if flags&syscall.O_NOFOLLOW == 0 { + tlog.Warn.Printf("Openat: O_NOFOLLOW missing: flags = %#x", flags) + flags |= syscall.O_NOFOLLOW + } + } + return unix.Openat(dirfd, path, flags, mode) +} + // Linkat exists both in Linux and in MacOS 10.10+. func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) { return unix.Linkat(olddirfd, oldpath, newdirfd, newpath, flags) diff --git a/internal/syscallcompat/sys_common_test.go b/internal/syscallcompat/sys_common_test.go index 455774f..db6719e 100644 --- a/internal/syscallcompat/sys_common_test.go +++ b/internal/syscallcompat/sys_common_test.go @@ -34,6 +34,35 @@ func TestReadlinkat(t *testing.T) { } } +func TestOpenat(t *testing.T) { + _, err := Openat(tmpDirFd, "testOpenAt", 0, 0) + if err == nil { + t.Errorf("should have failed") + } + fd, err := os.Create(tmpDir + "/testOpenAt") + if err != nil { + t.Fatal(err) + } + fd.Close() + rawFd, err := Openat(tmpDirFd, "testOpenAt", 0, 0) + if err != nil { + t.Fatal(err) + } + defer syscall.Close(rawFd) + if rawFd < 0 { + t.Fatalf("rawFd=%d", rawFd) + } + // Test with absolute path + rawFd, err = Openat(-1, tmpDir+"/testOpenAt", 0, 0) + if err != nil { + t.Fatal(err) + } + defer syscall.Close(rawFd) + if rawFd < 0 { + t.Fatalf("rawFd=%d", rawFd) + } +} + func TestFchmodat(t *testing.T) { regular := "TestFchmodat_Regular" f, err := os.OpenFile(tmpDir+"/"+regular, os.O_CREATE|os.O_WRONLY, 0000) diff --git a/internal/syscallcompat/sys_darwin.go b/internal/syscallcompat/sys_darwin.go index a260db6..358123c 100644 --- a/internal/syscallcompat/sys_darwin.go +++ b/internal/syscallcompat/sys_darwin.go @@ -57,10 +57,6 @@ func Dup3(oldfd int, newfd int, flags int) (err error) { //// Emulated Syscalls (see emulate.go) //////////////// //////////////////////////////////////////////////////// -func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { - return emulateOpenat(dirfd, path, flags, mode) -} - func OpenatUser(dirfd int, path string, flags int, mode uint32, context *fuse.Context) (fd int, err error) { if context != nil { runtime.LockOSThread() diff --git a/internal/syscallcompat/sys_linux.go b/internal/syscallcompat/sys_linux.go index 6f2a70d..d5dc021 100644 --- a/internal/syscallcompat/sys_linux.go +++ b/internal/syscallcompat/sys_linux.go @@ -58,24 +58,6 @@ func Fallocate(fd int, mode uint32, off int64, len int64) (err error) { return syscall.Fallocate(fd, mode, off, len) } -// Openat wraps the Openat syscall. -func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { - if flags&syscall.O_CREAT != 0 { - // O_CREAT should be used with O_EXCL. O_NOFOLLOW has no effect with O_EXCL. - if flags&syscall.O_EXCL == 0 { - tlog.Warn.Printf("Openat: O_CREAT without O_EXCL: flags = %#x", flags) - flags |= syscall.O_EXCL - } - } else { - // If O_CREAT is not used, we should use O_NOFOLLOW - if flags&syscall.O_NOFOLLOW == 0 { - tlog.Warn.Printf("Openat: O_NOFOLLOW missing: flags = %#x", flags) - flags |= syscall.O_NOFOLLOW - } - } - return syscall.Openat(dirfd, path, flags, mode) -} - // OpenatUser runs the Openat syscall in the context of a different user. func OpenatUser(dirfd int, path string, flags int, mode uint32, context *fuse.Context) (fd int, err error) { if context != nil { |