mirror of
https://github.com/syncthing/syncthing.git
synced 2026-06-23 16:10:33 -04:00
fix(fs, model): improve symlink resilience in file shortcut (#10739)
Ensure file was a file before the shortcut as well as after... (This was implied when talking to a correct implementation, but not enforced.) Make our file opening operations safe by default by ensuring the last path component is not a symlink. --------- Signed-off-by: Jakob Borg <jakob@kastelo.net>
This commit is contained in:
@@ -241,15 +241,7 @@ func (f *BasicFilesystem) DirNames(name string) ([]string, error) {
|
||||
}
|
||||
|
||||
func (f *BasicFilesystem) Open(name string) (File, error) {
|
||||
rootedName, err := f.rooted(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fd, err := os.Open(rootedName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return basicFile{fd, name}, err
|
||||
return f.OpenFile(name, os.O_RDONLY, 0)
|
||||
}
|
||||
|
||||
func (f *BasicFilesystem) OpenFile(name string, flags int, mode FileMode) (File, error) {
|
||||
@@ -257,6 +249,7 @@ func (f *BasicFilesystem) OpenFile(name string, flags int, mode FileMode) (File,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
flags |= alwaysOpenFlags // enforce extra bits in flags
|
||||
fd, err := os.OpenFile(rootedName, flags, os.FileMode(mode))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -265,15 +258,7 @@ func (f *BasicFilesystem) OpenFile(name string, flags int, mode FileMode) (File,
|
||||
}
|
||||
|
||||
func (f *BasicFilesystem) Create(name string) (File, error) {
|
||||
rootedName, err := f.rooted(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fd, err := os.Create(rootedName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return basicFile{fd, name}, err
|
||||
return f.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o666)
|
||||
}
|
||||
|
||||
func (*BasicFilesystem) Walk(_ string, _ WalkFunc) error {
|
||||
|
||||
@@ -14,8 +14,11 @@ import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const alwaysOpenFlags = syscall.O_NOFOLLOW // never open symlinks as the final path component
|
||||
|
||||
func (f *BasicFilesystem) CreateSymlink(target, name string) error {
|
||||
name, err := f.rooted(name)
|
||||
if err != nil {
|
||||
|
||||
@@ -21,6 +21,8 @@ import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const alwaysOpenFlags = 0 // no extra flags
|
||||
|
||||
var errNotSupported = errors.New("symlinks not supported")
|
||||
|
||||
func (BasicFilesystem) ReadSymlink(path string) (string, error) {
|
||||
|
||||
@@ -382,7 +382,7 @@ loop:
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if hasCurFile && file.BlocksEqual(curFile) {
|
||||
if hasCurFile && curFile.Type == file.Type && file.BlocksEqual(curFile) {
|
||||
// We are supposed to copy the entire file, and then fetch nothing. We
|
||||
// are only updating metadata, so we don't actually *need* to make the
|
||||
// copy.
|
||||
|
||||
Reference in New Issue
Block a user