-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lib/model: Allow updates to deleted files (fixes #3839) #3840
lib/model: Allow updates to deleted files (fixes #3839) #3840
Conversation
// and not a symlink or empty space. If it's already deleted, handle | ||
// the check inside deleteFile deleteDir only in the scenario where | ||
// the subject we are supposed to delete actually exists. | ||
if !fi.IsDeleted() && !osutil.IsDir(f.dir, filepath.Dir(fi.Name)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems dangerous, because a path that traverses Symlinks might end up in buckets
. I think this allows an attacker to delete known files outside of the folder.
// and not a symlink or empty space. If it's already deleted, handle | ||
// the check inside deleteFile deleteDir only in the scenario where | ||
// the subject we are supposed to delete actually exists. | ||
if !fi.IsDeleted() && !osutil.IsDir(f.dir, filepath.Dir(fi.Name)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is unnecessary. (Line 515)
// Verify that the thing we are handling lives inside a directory, | ||
// and not a symlink or empty space. | ||
if !osutil.IsDir(f.dir, filepath.Dir(file.Name)) { | ||
f.newError(file.Name, "deleteDir isDir", errNotDir) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The delete was successful at this point, the error is pointless.
E.g. foo/bar
was renamed to baz/bar
and a Symlink foo -> baz
was created. The Lstat
check succeeds but the real file foo/bar
doesn't exist anymore.
I think that the following check should be enough:
if !osutil.IsDir(f.dir, filepath.Dir(file.Name)) {
f.dbUpdates <- dbUpdateJob{file, dbUpdateDeleteDir}
return
}
Lstat
is not required.
// Verify that the thing we are handling lives inside a directory, | ||
// and not a symlink or empty space. | ||
if !osutil.IsDir(f.dir, filepath.Dir(file.Name)) { | ||
f.newError(file.Name, "deleteFile isDir", errNotDir) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as deleteDir
@@ -1532,7 +1540,7 @@ func (f *sendReceiveFolder) dbUpdaterRoutine() { | |||
} | |||
lastFile = file | |||
if err := syncFn(file); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above changes allow file
to traverse a Symlink. You have to check with isDir
, before calling syncFn
. It prevents fsyncing files outside of the folder and the fsync errors disappear.
Instead of handling the inconsistency on the filesystem, could we fix it in the database directly? |
Not sure what you mean. Wasn't the point thatthe db is racey compared with the fs? |
Maybe I'm misunderstanding. But isn't the problem that we have:
and we get deletes for them:
so we remove both. We then get an update:
but we can't resurrect it because the dir is gone and fails the parent check? Similar thing when dir is ignored and dir/file unignored. My alternative idea for handling this is in |
I don't think thats the problem as we'd get the dir entry too. The issue as far as I understand it is: A and B has dir/file |
To be honest, I still think this somewhat contains holes.
This whole "resurrecting dir" stuff is now impossible.