lib/model, lib/versioner: Prevent symlink attack via versioning (fixes #4286)

Prior to this, the following is possible:

- Create a symlink "foo -> /somewhere", it gets synced
- Delete "foo", it gets versioned
- Create "foo/bar", it gets synced
- Delete "foo/bar", it gets versioned in "/somewhere/bar"

With this change, versioners should never version symlinks.
This commit is contained in:
Jakob Borg
2017-07-25 11:36:09 +02:00
parent 54155cb42d
commit f1f21bf220
8 changed files with 146 additions and 5 deletions

View File

@@ -27,6 +27,8 @@ type External struct {
}
func NewExternal(folderID, folderPath string, params map[string]string) Versioner {
cleanSymlinks(folderPath)
command := params["command"]
s := External{
@@ -41,13 +43,16 @@ func NewExternal(folderID, folderPath string, params map[string]string) Versione
// Archive moves the named file away to a version archive. If this function
// returns nil, the named file does not exist any more (has been archived).
func (v External) Archive(filePath string) error {
_, err := osutil.Lstat(filePath)
info, err := osutil.Lstat(filePath)
if os.IsNotExist(err) {
l.Debugln("not archiving nonexistent file", filePath)
return nil
} else if err != nil {
return err
}
if info.Mode()&os.ModeSymlink != 0 {
panic("bug: attempting to version a symlink")
}
l.Debugln("archiving", filePath)