From 8e9e028c0c6808e912916a2080d23b6d42453735 Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Wed, 9 Jun 2021 18:51:19 +0100 Subject: [PATCH] fix: safe update of the audit objectErasureMap (#12477) objectErasureMap in the audit holds information about the objects involved in the current S3 operation such as pool index, set an index, and disk endpoints. One user saw a crash due to a concurrent update of objectErasureMap information. Use sync.Map to prevent a crash. --- cmd/erasure-sets.go | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/cmd/erasure-sets.go b/cmd/erasure-sets.go index 5e79beb6d..2b4b26304 100644 --- a/cmd/erasure-sets.go +++ b/cmd/erasure-sets.go @@ -20,6 +20,7 @@ package cmd import ( "context" "encoding/binary" + "encoding/json" "errors" "fmt" "hash/crc32" @@ -521,6 +522,21 @@ type auditObjectOp struct { Disks []string `json:"disks"` } +type auditObjectErasureMap struct { + sync.Map +} + +// Define how to marshal auditObjectErasureMap so it can be +// printed in the audit webhook notification request. +func (a *auditObjectErasureMap) MarshalJSON() ([]byte, error) { + mapCopy := make(map[string]auditObjectOp) + a.Range(func(k, v interface{}) bool { + mapCopy[k.(string)] = v.(auditObjectOp) + return true + }) + return json.Marshal(mapCopy) +} + func auditObjectErasureSet(ctx context.Context, object string, set *erasureObjects) { if len(logger.AuditTargets) == 0 { return @@ -534,20 +550,20 @@ func auditObjectErasureSet(ctx context.Context, object string, set *erasureObjec Disks: set.getEndpoints(), } - var objectErasureSetTag map[string]auditObjectOp + var objectErasureSetTag *auditObjectErasureMap reqInfo := logger.GetReqInfo(ctx) for _, kv := range reqInfo.GetTags() { if kv.Key == objectErasureMapKey { - objectErasureSetTag = kv.Val.(map[string]auditObjectOp) + objectErasureSetTag = kv.Val.(*auditObjectErasureMap) break } } if objectErasureSetTag == nil { - objectErasureSetTag = make(map[string]auditObjectOp) + objectErasureSetTag = &auditObjectErasureMap{} } - objectErasureSetTag[object] = op + objectErasureSetTag.Store(object, op) reqInfo.SetTags(objectErasureMapKey, objectErasureSetTag) }