protondrive: check the signed block list when a range asks for the whole file

A request for the whole file as a range, as "bytes=0-" from serve http
or webdav clients, was read as a ranged read, which can't check the
file's signed block list. It is now read as a full read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-11-11 20:01:02 +01:00
1 parent cb6e6759b8
commit 58fde59f34
3 files changed
+30 -3

No files matched your search

+4
View File
@@ -1162,6 +1162,10 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadClo
}
}
}
if known && offset == 0 && limit >= size {
// The whole file, as a full read, so the manifest is checked.
limit = -1
}
rc, err := o.fs.c.open(ctx, o.n, offset, limit)
if err != nil {
return nil, translateError(err, opObject)
+22
View File
@@ -340,6 +340,28 @@ func TestHostileServer(t *testing.T) {
})
}
t.Run("a range covering the whole of a file with swapped blocks", func(t *testing.T) {
ctx := context.Background()
remote, _, u := setupFakeRemote(t)
content := patternedContent(2*blockSize+10, 13)
seedCorrupted("swap-blocks")(u, content)
f := newFakeFs(t, remote, "")
o, err := f.NewObject(ctx, "victim.bin")
require.NoError(t, err)
size := int64(len(content))
require.Equal(t, size, o.Size())
for _, r := range []fs.RangeOption{{Start: 0, End: -1}, {Start: 0, End: size - 1}, {Start: 0, End: size + 100}} {
rc, err := o.Open(ctx, &r)
var got []byte
if err == nil {
got, err = io.ReadAll(rc)
_ = rc.Close()
}
assert.Error(t, err, "%v read without error", r)
assert.Zero(t, len(got), "%v: bytes released before the error", r)
}
})
t.Run("updating a file with an attacker-signed passphrase", func(t *testing.T) {
ctx := context.Background()
remote, _, u := setupFakeRemote(t)
+4 -3
View File
@@ -299,9 +299,10 @@ AES-GCM blocks; names, passphrases, hash keys and attributes without AEAD).
listed again (for a new URL) with another hash is an integrity error.
Failure is an error. An advanced option `ignore_signature_errors`
downgrades content and authorship signature failures to a logged `ERROR`
for users with legacy or shared data (#8003, #7344). **(call)** Ranged
reads check each block against its listed hash but cannot verify the
manifest; this is documented, as it is in the SDK.
for users with legacy or shared data (#8003, #7344). **(call)** A range
covering the whole file from offset 0 (as `bytes=0-`) is a full read.
Other ranged reads check each block against its listed hash but cannot
verify the manifest; this is documented, as it is in the SDK.
- A server serving an earlier revision whole (blocks, manifest and
extended attributes, all validly signed) under the current revision ID is
undetectable: nothing signed binds them to the revision. The SDK cannot