-
Notifications
You must be signed in to change notification settings - Fork 2.1k
[stable8.2] Heal unencrypted file sizes at download time #22008
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
[stable8.2] Heal unencrypted file sizes at download time #22008
Conversation
Whenever the unencrypted size is -1 or equal to the encrypted size, interpret this as an error and enable a repair routine inside the encryption stream wrapper. The repair routine will count how many bytes of decrypted content was returned and then update the cache when closing the stream.
|
By analyzing the blame information on this pull request, we identified @schiesbn, @jknockaert and @DeepDiver1975 to be potential reviewers |
|
I understand this is part of a mechanism that fixes inconsistencies in the database when they get noticed? Sounds like an excellent idea. I will have a look at it over the weekend. |
|
For every test, manually update the "size" column in the database using the real file size from disk (in the data folder)
|
|
|
I tested this on two broken instances and it fixed the issue there. The clients are syncing again (and by this fixing the broken entries) and also the web UI works again.
|
|
This is a 👍 from my side. |
|
Just got some feedback - it works in in IE/Edge but not in Firefox or Chrome (also not on the 2nd or 3rd try). I guess we need to check this again. |
|
Hopefully not some caching issue? |
I just asked for some curl responses. |
I also asked for the network console output. |
curl download said: Seems to be correct. |
|
@PVince81 mentioned that this could also be an off-by-one error. |
|
Ok, I was able to reproduce the bug by uploading a file that has exactly 8191 bytes. |
|
Looks like my tentative optimization is wrong. For some reason the size of |
|
|
The proposed fix will make things worse when it is called in the context of a http-range request: the size will be off without possibility to detect it later on; so basically the oc file system corrupts. Upon opening the encrypted file and detecting an inconsistency the correct unencrypted filesize should be determined using the getFileSize procedure I implemented in #11659 (which was never released before encryption 2.0 arrived). This implementation is efficient and robust. As for how to detect an inconsistency there are multiple ways: either a test which is evaluated upon every file opening, or maybe a flag set in a background process (but still then the flag value needs to be evaluated upon opening). In case the unencrypted filesize is updated a flag should be set to write it back to the database upon closing the stream. |
|
@jknockaert I'm worried about performance or potential slow downs, that's why we're trying to do it on the fly in a single-pass. Regarding range requests, maybe in that specific situation the repairing code should simply be disabled. Does getFileSize require re-reading the full file or is it able to somehow compute the correct size without performance impact ? |
|
|
@PVince81 getFileSize (which would have to be updated for compatibility with encryption 2.0) doesn't require re-reading the full file for seekable (encrypted) streams. |
|
A one-shot penatly is acceptable, but before doing so we should detect whether a repair is needed in the first place. And only if a repair needs to be done, then do it once. Would it work if we modified this PR to call getFileSize() + fix the cache entry at the beginning as soon as the discrepancy is detected: https://github.com/owncloud/core/pull/22008/files#diff-7e61c5b95e4e1be3406a3959ae86d2d2R262 ? Or alternatively, at the end. |
|
@jknockaert as usual, thanks a lot for your advice 😄 |
|
@PVince81 Sounds like a good idea. So upon stream opening:
|
|
@schiesbn can you comment on this ? |
|
While I am thinking of the topic, I wonder if we should add an option somewhere to do a file scan and fix/report encryption issues. Such a scan would check for unencrypted files, incorrect file sizes, but also for the presence of all required keys. There's now far too much opportunities for corrupting the encryption process, eg. by php timeouts, without the possibility to validate. The scan would then fix what is fixable (access to private keys needed), and report everything else. I'm also thinking of the recovery keys here; the idea introduced in #18951 touches this concern. But maybe we should open a separate ticket for this. |
|
@jknockaert I thought about this too. Unfortunately occ files:scan on the CLI doesn't have the user's passwords, so unable to compute and fix unencrypted sizes. The most it could do is set the "encrypted" flag and maybe the size to "-1" to trigger this PR's logic, if "encrypted" was 0 initially. |
|
@PVince81 What about adding this to the user settings page? There's already an encryption related section where the user can activate the recovery key functionality. |
|
@jknockaert there is a risk to run into timeouts if the PHP call takes too long. |
|
@PVince81 OK, so the test would suffer from the same corruption that it tries to detect. |
|
So far I still think this is the best solution: #22008 (comment) |
|
@schiesbn any update on this critical issue ? |
|
I think the easiest solution is not to try to fix the unencrypted size in fseek. Otherwise it will become to complex for the corner case we want to fix. See my last commit. Otherwise code from @PVince81 looks good and works as expected 👍 |
|
note for @jknockaert we decided to disable the repair routine when fseek was detected. |
|
Forward port here #22567 |
|
No this is not good. The entire wrapper is designed under the assumption that the unencrypted filesize is correctly known upon access. That's why I first had to merge #11659 (to determine the unencrypted filesize without using the wrapper) before I could rewrite the wrapper in #14383. The Encryption 2.0 wrapper is conceptually identical to #14383. |
|
@schiesbn What's complex about writing a procedure to determine unencrypted size and write it to the filecache? It would fit in nicely together in one place in the code and in a place where it is called deterministically (when opening the file). The current PR has code spread out over diverse subroutines which are called by low level php code in a fairly unpredictable manner (remember the php bug we hit in #16452). |
|
@jknockaert after thinking once more about it I think you are right... Please have a look at this PR #22579. Is this the solution you had in mind? |
|
Obsoleted by the better solution #22579 which doesn't require two downloads |
|
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Whenever the unencrypted size is -1 or equal to the encrypted size,
interpret this as an error and enable a repair routine inside the
encryption stream wrapper.
The repair routine will count how many bytes of decrypted content was
returned and then update the cache when closing the stream.
This fix is very specific to encryption but has the advantage of not impairing (slowing down) the regular download cases.
@MorrisJobke @icewind1991 @schiesbn
Fixes #21751 but only for encryption