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:
@@ -28,6 +28,8 @@ type Trashcan struct {
|
||||
}
|
||||
|
||||
func NewTrashcan(folderID, folderPath string, params map[string]string) Versioner {
|
||||
cleanSymlinks(folderPath)
|
||||
|
||||
cleanoutDays, _ := strconv.Atoi(params["cleanoutDays"])
|
||||
// On error we default to 0, "do not clean out the trash can"
|
||||
|
||||
@@ -44,13 +46,16 @@ func NewTrashcan(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 (t *Trashcan) 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")
|
||||
}
|
||||
|
||||
versionsDir := filepath.Join(t.folderPath, ".stversions")
|
||||
if _, err := os.Stat(versionsDir); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user