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.
This commit is contained in:
Anis Elleuch 2021-06-09 18:51:19 +01:00 committed by GitHub
parent dd5e9493f1
commit 8e9e028c0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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)
}