mirror of
https://github.com/pgsty/minio.git
synced 2026-08-11 00:33:28 +03:00
fix: guard the ReadParts trace path against an empty part list
ReadParts built its disk-health trace path from partMetaPaths[0] with no length check, so a caller passing no paths at all indexed an empty slice. xlStorage.ReadParts handles an empty list perfectly well - it returns an empty result - so the panic came entirely from the metrics bookkeeping wrapped around it. The reachable caller is ReadPartsHandler, which decodes its path list from a msgpack request body that an authenticated peer controls, and neither the handler, the storage-REST client, nor the path guard rejects an empty one: guardPaths ranges over the slice, so an empty slice passes vacuously. net/http recovers a panicking handler, so this is not a crash - which is what makes it worth fixing rather than merely tidy. ReadPartsHandler calls keepHTTPResponseAlive before it calls ReadParts, and that helper spawns a goroutine whose only exit is receiving from the channel done() writes. Panicking in between skips both done(err) and done(nil), so the process survives and the keep-alive goroutine and its ten-second ticker stay parked forever - one per request, driven by a request body the caller chooses. Repeating one malformed frame exhausts the node. The fix follows DeleteVersions in the same decorator, which already guards the identical "merely for tracing" lookup; ReadParts was the one method missing the pattern. It also covers the second entry point, the per-disk errgroup in readParts, where a panic has no recover at all and would take the process down. That path is screened at the S3 boundary today, so this is defence in depth there. No error is returned for the empty case. The storage layer's answer to an empty list is an empty result, and turning that into an error would be a behaviour change on a path that is merely degenerate. Co-authored-by: ChatGPT <noreply@openai.com> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -713,7 +713,12 @@ func (p *xlStorageDiskIDCheck) StatInfoFile(ctx context.Context, volume, path st
|
||||
}
|
||||
|
||||
func (p *xlStorageDiskIDCheck) ReadParts(ctx context.Context, volume string, partMetaPaths ...string) ([]*ObjectPartInfo, error) {
|
||||
ctx, done, err := p.TrackDiskHealth(ctx, storageMetricReadParts, volume, path.Dir(partMetaPaths[0]))
|
||||
// Merely for tracing storage
|
||||
partPath := ""
|
||||
if len(partMetaPaths) > 0 {
|
||||
partPath = path.Dir(partMetaPaths[0])
|
||||
}
|
||||
ctx, done, err := p.TrackDiskHealth(ctx, storageMetricReadParts, volume, partPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user