aboutsummaryrefslogtreecommitdiff
path: root/internal/syscallcompat
diff options
context:
space:
mode:
Diffstat (limited to 'internal/syscallcompat')
-rw-r--r--internal/syscallcompat/open_nofollow.go23
-rw-r--r--internal/syscallcompat/open_nofollow_test.go10
2 files changed, 16 insertions, 17 deletions
diff --git a/internal/syscallcompat/open_nofollow.go b/internal/syscallcompat/open_nofollow.go
index 4f75bd6..d440fc3 100644
--- a/internal/syscallcompat/open_nofollow.go
+++ b/internal/syscallcompat/open_nofollow.go
@@ -8,18 +8,18 @@ import (
"github.com/rfjakob/gocryptfs/internal/tlog"
)
-// OpenNofollow opens the file/dir at "relPath" in a way that is secure against
+// OpenDirNofollow opens the dir at "relPath" in a way that is secure against
// symlink attacks. Symlinks that are part of "relPath" are never followed.
// This function is implemented by walking the directory tree, starting at
// "baseDir", using the Openat syscall with the O_NOFOLLOW flag.
// Symlinks that are part of the "baseDir" path are followed.
-func OpenNofollow(baseDir string, relPath string, flags int, mode uint32) (fd int, err error) {
+func OpenDirNofollow(baseDir string, relPath string) (fd int, err error) {
if !filepath.IsAbs(baseDir) {
- tlog.Warn.Printf("BUG: OpenNofollow called with relative baseDir=%q", baseDir)
+ tlog.Warn.Printf("BUG: OpenDirNofollow called with relative baseDir=%q", baseDir)
return -1, syscall.EINVAL
}
if filepath.IsAbs(relPath) {
- tlog.Warn.Printf("BUG: OpenNofollow called with absolute relPath=%q", relPath)
+ tlog.Warn.Printf("BUG: OpenDirNofollow called with absolute relPath=%q", relPath)
return -1, syscall.EINVAL
}
// Open the base dir (following symlinks)
@@ -31,14 +31,11 @@ func OpenNofollow(baseDir string, relPath string, flags int, mode uint32) (fd in
if relPath == "" {
return dirfd, nil
}
- // Split the path into components and separate intermediate directories
- // and the final basename
+ // Split the path into components
parts := strings.Split(relPath, "/")
- dirs := parts[:len(parts)-1]
- final := parts[len(parts)-1]
- // Walk intermediate directories
+ // Walk the directory tree
var dirfd2 int
- for _, name := range dirs {
+ for _, name := range parts {
dirfd2, err = Openat(dirfd, name, syscall.O_RDONLY|syscall.O_NOFOLLOW|syscall.O_DIRECTORY, 0)
syscall.Close(dirfd)
if err != nil {
@@ -46,8 +43,6 @@ func OpenNofollow(baseDir string, relPath string, flags int, mode uint32) (fd in
}
dirfd = dirfd2
}
- defer syscall.Close(dirfd)
- // Open the final component with the flags and permissions requested by
- // the user plus forced NOFOLLOW.
- return Openat(dirfd, final, flags|syscall.O_NOFOLLOW, mode)
+ // Return fd to final directory
+ return dirfd, nil
}
diff --git a/internal/syscallcompat/open_nofollow_test.go b/internal/syscallcompat/open_nofollow_test.go
index 1f21557..1eeac3a 100644
--- a/internal/syscallcompat/open_nofollow_test.go
+++ b/internal/syscallcompat/open_nofollow_test.go
@@ -12,7 +12,11 @@ func TestOpenNofollow(t *testing.T) {
t.Fatal(err)
}
// Create a file
- fd, err := OpenNofollow(tmpDir, "d1/d2/d3/f1", syscall.O_RDWR|syscall.O_CREAT|syscall.O_EXCL, 0600)
+ dirfd, err := OpenDirNofollow(tmpDir, "d1/d2/d3")
+ if err != nil {
+ t.Fatal(err)
+ }
+ fd, err := Openat(dirfd, "f1", syscall.O_RDWR|syscall.O_CREAT|syscall.O_EXCL, 0600)
if err != nil {
t.Fatal(err)
}
@@ -27,7 +31,7 @@ func TestOpenNofollow(t *testing.T) {
t.Fatal(err)
}
os.Symlink(tmpDir+"/d1.renamed", tmpDir+"/d1")
- fd, err = OpenNofollow(tmpDir, "d1/d2/d3/f1", syscall.O_RDWR|syscall.O_CREAT, 0600)
+ fd, err = OpenDirNofollow(tmpDir, "d1/d2/d3")
if err == nil {
t.Fatalf("should have failed")
}
@@ -35,7 +39,7 @@ func TestOpenNofollow(t *testing.T) {
t.Errorf("expected ELOOP or ENOTDIR, got %v", err)
}
// Check to see that the base dir can be opened as well
- fd, err = OpenNofollow(tmpDir, "", syscall.O_RDONLY, 0)
+ fd, err = OpenDirNofollow(tmpDir, "")
if err != nil {
t.Errorf("cannot open base dir: %v", err)
} else {