diff options
Diffstat (limited to 'internal/syscallcompat')
| -rw-r--r-- | internal/syscallcompat/open_nofollow.go | 23 | ||||
| -rw-r--r-- | internal/syscallcompat/open_nofollow_test.go | 10 | 
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 { | 
