fix(storage): validate internode paths and erasure payloads

Storage REST request bodies and Grid RPC frames bypass the HTTP validity middleware, allowing wire-supplied paths and malformed FileInfo values to reach xlStorage unchecked.

Wrap the remotely exposed StorageAPI with a guard that covers every path-bearing method, including nested metadata fields. Reject traversal and destructive volume-root aliases before path cleaning can erase them, and validate erasure geometry and part sizes at the same wire boundary. Keep a raw-volume check in getVolDir for peer-S3 calls that bypass the wrapper.

Reflection, fuzz, traversal, peer-S3, compatibility, and malformed-erasure tests pin the complete method surface and prove that legal object names remain accepted.

Co-authored-by: ChatGPT <noreply@openai.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Feng Ruohang
2026-08-04 22:40:43 +08:00
parent a36fd8fffb
commit ca7baa670d
6 changed files with 1370 additions and 1 deletions
+20
View File
@@ -69,6 +69,26 @@ func (e ErasureInfo) ShardSize() int64 {
return ceilFrac(e.BlockSize, int64(e.DataBlocks))
}
// HasNegativePartSize reports whether any part claims a negative size.
//
// Such metadata is never legitimate, and it is not merely cosmetic: a negative
// length floors both terms of ShardFileSize to zero, and checkPart's only
// integrity test is "st.Size() < expectedSize". A zero expectation is therefore
// satisfied by every file that exists, including a truncated shard, so the part
// is reported intact and a heal driven by the result skips the repair it should
// have performed.
//
// Note this holds even when the erasure parameters are entirely valid, so
// FileInfo.IsValid() - the check healing itself trusts - does not catch it.
func (fi FileInfo) HasNegativePartSize() bool {
for _, p := range fi.Parts {
if p.Size < 0 {
return true
}
}
return false
}
// IsValid - tells if erasure info fields are valid.
func (fi FileInfo) IsValid() bool {
if fi.Deleted {