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:
1 parent
cb6e6759b8
commit
58fde59f34
3 files changed
+30
-3
No files matched your search
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user