![Jakob Unterwurzacher](/assets/img/avatar_default.png)
The function used to do two things: 1) Walk the directory tree in a manner safe from symlink attacks 2) Open the final component in the mode requested by the caller This change drops (2), which was only used once, and lets the caller handle it. This simplifies the function and makes it fit for reuse in forward mode in openBackingPath(), and for using O_PATH on Linux.
49 lines
1.4 KiB
Go
49 lines
1.4 KiB
Go
package syscallcompat
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strings"
|
|
"syscall"
|
|
|
|
"github.com/rfjakob/gocryptfs/internal/tlog"
|
|
)
|
|
|
|
// 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 OpenDirNofollow(baseDir string, relPath string) (fd int, err error) {
|
|
if !filepath.IsAbs(baseDir) {
|
|
tlog.Warn.Printf("BUG: OpenDirNofollow called with relative baseDir=%q", baseDir)
|
|
return -1, syscall.EINVAL
|
|
}
|
|
if filepath.IsAbs(relPath) {
|
|
tlog.Warn.Printf("BUG: OpenDirNofollow called with absolute relPath=%q", relPath)
|
|
return -1, syscall.EINVAL
|
|
}
|
|
// Open the base dir (following symlinks)
|
|
dirfd, err := syscall.Open(baseDir, syscall.O_RDONLY|syscall.O_DIRECTORY, 0)
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
// Caller wanted to open baseDir itself?
|
|
if relPath == "" {
|
|
return dirfd, nil
|
|
}
|
|
// Split the path into components
|
|
parts := strings.Split(relPath, "/")
|
|
// Walk the directory tree
|
|
var dirfd2 int
|
|
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 {
|
|
return -1, err
|
|
}
|
|
dirfd = dirfd2
|
|
}
|
|
// Return fd to final directory
|
|
return dirfd, nil
|
|
}
|