mirror of
https://github.com/minio/minio.git
synced 2025-01-25 21:53:16 -05:00
fix: make sure to lock CopyObject for in-place updates (#10492)
This commit is contained in:
parent
5c47ce456e
commit
02c1a08a5b
@ -0,0 +1,6 @@
|
|||||||
|
CVE-2018-17075
|
||||||
|
CVE-2018-17848
|
||||||
|
CVE-2018-17846
|
||||||
|
CVE-2018-17847
|
||||||
|
CVE-2018-17143
|
||||||
|
CVE-2018-17142
|
@ -18,6 +18,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -179,20 +180,24 @@ func replicateObject(ctx context.Context, bucket, object, versionID string, obje
|
|||||||
if tgt == nil {
|
if tgt == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gr, err := objectAPI.GetObjectNInfo(ctx, bucket, object, nil, http.Header{}, readLock, ObjectOptions{})
|
gr, err := objectAPI.GetObjectNInfo(ctx, bucket, object, nil, http.Header{}, readLock, ObjectOptions{
|
||||||
|
VersionID: versionID,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer gr.Close()
|
|
||||||
objInfo := gr.ObjInfo
|
objInfo := gr.ObjInfo
|
||||||
size, err := objInfo.GetActualSize()
|
size, err := objInfo.GetActualSize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.LogIf(ctx, err)
|
logger.LogIf(ctx, err)
|
||||||
|
gr.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dest := cfg.GetDestination()
|
dest := cfg.GetDestination()
|
||||||
if dest.Bucket == "" {
|
if dest.Bucket == "" {
|
||||||
|
gr.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// In the rare event that replication is in pending state either due to
|
// In the rare event that replication is in pending state either due to
|
||||||
@ -201,6 +206,7 @@ func replicateObject(ctx context.Context, bucket, object, versionID string, obje
|
|||||||
if healPending {
|
if healPending {
|
||||||
_, err := tgt.StatObject(ctx, dest.Bucket, object, miniogo.StatObjectOptions{VersionID: objInfo.VersionID})
|
_, err := tgt.StatObject(ctx, dest.Bucket, object, miniogo.StatObjectOptions{VersionID: objInfo.VersionID})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
gr.Close()
|
||||||
// object with same VersionID already exists, replication kicked off by
|
// object with same VersionID already exists, replication kicked off by
|
||||||
// PutObject might have completed.
|
// PutObject might have completed.
|
||||||
return
|
return
|
||||||
@ -210,6 +216,7 @@ func replicateObject(ctx context.Context, bucket, object, versionID string, obje
|
|||||||
|
|
||||||
replicationStatus := replication.Complete
|
replicationStatus := replication.Complete
|
||||||
_, err = tgt.PutObject(ctx, dest.Bucket, object, gr, size, "", "", putOpts)
|
_, err = tgt.PutObject(ctx, dest.Bucket, object, gr, size, "", "", putOpts)
|
||||||
|
gr.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
replicationStatus = replication.Failed
|
replicationStatus = replication.Failed
|
||||||
// Notify replication failure event.
|
// Notify replication failure event.
|
||||||
@ -231,8 +238,10 @@ func replicateObject(ctx context.Context, bucket, object, versionID string, obje
|
|||||||
objInfo.metadataOnly = true // Perform only metadata updates.
|
objInfo.metadataOnly = true // Perform only metadata updates.
|
||||||
if _, err = objectAPI.CopyObject(ctx, bucket, object, bucket, object, objInfo, ObjectOptions{
|
if _, err = objectAPI.CopyObject(ctx, bucket, object, bucket, object, objInfo, ObjectOptions{
|
||||||
VersionID: objInfo.VersionID,
|
VersionID: objInfo.VersionID,
|
||||||
}, ObjectOptions{VersionID: objInfo.VersionID}); err != nil {
|
}, ObjectOptions{
|
||||||
logger.LogIf(ctx, err)
|
VersionID: objInfo.VersionID,
|
||||||
|
}); err != nil {
|
||||||
|
logger.LogIf(ctx, fmt.Errorf("Unable to update replication metadata for %s: %s", objInfo.VersionID, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,6 +426,8 @@ func (d *dataUpdateTracker) deserialize(src io.Reader, newerThan time.Time) erro
|
|||||||
}
|
}
|
||||||
// Ignore what remains on the stream.
|
// Ignore what remains on the stream.
|
||||||
// Update d:
|
// Update d:
|
||||||
|
d.mu.Lock()
|
||||||
|
defer d.mu.Unlock()
|
||||||
d.Current = dst.Current
|
d.Current = dst.Current
|
||||||
d.History = dst.History
|
d.History = dst.History
|
||||||
d.Saved = dst.Saved
|
d.Saved = dst.Saved
|
||||||
|
@ -72,6 +72,11 @@ func (er erasureObjects) CopyObject(ctx context.Context, srcBucket, srcObject, d
|
|||||||
return oi, NotImplemented{}
|
return oi, NotImplemented{}
|
||||||
}
|
}
|
||||||
defer ObjectPathUpdated(path.Join(dstBucket, dstObject))
|
defer ObjectPathUpdated(path.Join(dstBucket, dstObject))
|
||||||
|
lk := er.NewNSLock(ctx, dstBucket, dstObject)
|
||||||
|
if err := lk.GetLock(globalOperationTimeout); err != nil {
|
||||||
|
return oi, err
|
||||||
|
}
|
||||||
|
defer lk.Unlock()
|
||||||
|
|
||||||
// Read metadata associated with the object from all disks.
|
// Read metadata associated with the object from all disks.
|
||||||
storageDisks := er.getDisks()
|
storageDisks := er.getDisks()
|
||||||
@ -112,12 +117,13 @@ func (er erasureObjects) CopyObject(ctx context.Context, srcBucket, srcObject, d
|
|||||||
fi.VersionID = versionID // set any new versionID we might have created
|
fi.VersionID = versionID // set any new versionID we might have created
|
||||||
fi.ModTime = modTime // set modTime for the new versionID
|
fi.ModTime = modTime // set modTime for the new versionID
|
||||||
|
|
||||||
|
srcInfo.UserDefined["etag"] = srcInfo.ETag
|
||||||
|
|
||||||
// Update `xl.meta` content on each disks.
|
// Update `xl.meta` content on each disks.
|
||||||
for index := range metaArr {
|
for index := range metaArr {
|
||||||
metaArr[index].ModTime = modTime
|
metaArr[index].ModTime = modTime
|
||||||
metaArr[index].VersionID = versionID
|
metaArr[index].VersionID = versionID
|
||||||
metaArr[index].Metadata = srcInfo.UserDefined
|
metaArr[index].Metadata = srcInfo.UserDefined
|
||||||
metaArr[index].Metadata["etag"] = srcInfo.ETag
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tempObj := mustGetUUID()
|
tempObj := mustGetUUID()
|
||||||
@ -741,6 +747,12 @@ func (er erasureObjects) putObject(ctx context.Context, bucket string, object st
|
|||||||
return ObjectInfo{}, IncompleteBody{Bucket: bucket, Object: object}
|
return ObjectInfo{}, IncompleteBody{Bucket: bucket, Object: object}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lk := er.NewNSLock(ctx, bucket, object)
|
||||||
|
if err := lk.GetLock(globalOperationTimeout); err != nil {
|
||||||
|
return ObjectInfo{}, err
|
||||||
|
}
|
||||||
|
defer lk.Unlock()
|
||||||
|
|
||||||
for i, w := range writers {
|
for i, w := range writers {
|
||||||
if w == nil {
|
if w == nil {
|
||||||
onlineDisks[i] = nil
|
onlineDisks[i] = nil
|
||||||
@ -780,12 +792,6 @@ func (er erasureObjects) putObject(ctx context.Context, bucket string, object st
|
|||||||
return ObjectInfo{}, toObjectErr(err, bucket, object)
|
return ObjectInfo{}, toObjectErr(err, bucket, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
lk := er.NewNSLock(ctx, bucket, object)
|
|
||||||
if err := lk.GetLock(globalOperationTimeout); err != nil {
|
|
||||||
return ObjectInfo{}, err
|
|
||||||
}
|
|
||||||
defer lk.Unlock()
|
|
||||||
|
|
||||||
// Rename the successfully written temporary object to final location.
|
// Rename the successfully written temporary object to final location.
|
||||||
if onlineDisks, err = renameData(ctx, onlineDisks, minioMetaTmpBucket, tempObj, fi.DataDir, bucket, object, writeQuorum, nil); err != nil {
|
if onlineDisks, err = renameData(ctx, onlineDisks, minioMetaTmpBucket, tempObj, fi.DataDir, bucket, object, writeQuorum, nil); err != nil {
|
||||||
return ObjectInfo{}, toObjectErr(err, bucket, object)
|
return ObjectInfo{}, toObjectErr(err, bucket, object)
|
||||||
|
6
go.mod
6
go.mod
@ -79,9 +79,9 @@ require (
|
|||||||
github.com/willf/bloom v2.0.3+incompatible
|
github.com/willf/bloom v2.0.3+incompatible
|
||||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c
|
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c
|
||||||
go.etcd.io/etcd/v3 v3.3.0-rc.0.0.20200707003333-58bb8ae09f8e
|
go.etcd.io/etcd/v3 v3.3.0-rc.0.0.20200707003333-58bb8ae09f8e
|
||||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae
|
golang.org/x/sys v0.0.0-20200915084602-288bc346aa39
|
||||||
golang.org/x/tools v0.0.0-20200814172026-c4923e618c08 // indirect
|
golang.org/x/tools v0.0.0-20200814172026-c4923e618c08 // indirect
|
||||||
google.golang.org/api v0.5.0
|
google.golang.org/api v0.5.0
|
||||||
gopkg.in/jcmturner/gokrb5.v7 v7.3.0
|
gopkg.in/jcmturner/gokrb5.v7 v7.3.0
|
||||||
|
6
go.sum
6
go.sum
@ -501,6 +501,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnk
|
|||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
|
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
|
||||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
|
||||||
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
@ -530,6 +532,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
|
||||||
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFMd9CgUAcGx7V+qEg/h5IBI=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 h1:Wo7BWFiOk0QRFMLYMqJGFMd9CgUAcGx7V+qEg/h5IBI=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -564,6 +568,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20u
|
|||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200915084602-288bc346aa39 h1:356XA7ITklAU2//sYkjFeco+dH1bCRD8XCJ9FIEsvo4=
|
||||||
|
golang.org/x/sys v0.0.0-20200915084602-288bc346aa39/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU=
|
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU=
|
||||||
|
Loading…
x
Reference in New Issue
Block a user