From f09d0a5922ef286a4cb17bee7ad7d0e935226443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Fri, 28 Jan 2022 21:25:35 +0000 Subject: [PATCH] check lock on writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- .../utils/decomposedfs/decomposedfs.go | 54 +++++++++---------- pkg/storage/utils/decomposedfs/grants.go | 17 +++++- pkg/storage/utils/decomposedfs/metadata.go | 16 ++++++ pkg/storage/utils/decomposedfs/recycle.go | 9 +++- pkg/storage/utils/decomposedfs/revisions.go | 9 +++- 5 files changed, 72 insertions(+), 33 deletions(-) diff --git a/pkg/storage/utils/decomposedfs/decomposedfs.go b/pkg/storage/utils/decomposedfs/decomposedfs.go index b037e6a0c2f..a356bc4d465 100644 --- a/pkg/storage/utils/decomposedfs/decomposedfs.go +++ b/pkg/storage/utils/decomposedfs/decomposedfs.go @@ -312,6 +312,14 @@ func (fs *Decomposedfs) CreateDir(ctx context.Context, ref *provider.Reference) return errtypes.PermissionDenied(filepath.Join(n.ParentID, n.Name)) } + // check lock + if lock := n.ReadLock(ctx); lock != nil { + lockID, _ := ctxpkg.ContextGetLockID(ctx) + if lock.LockId != lockID { + return errtypes.Locked(lock.LockId) + } + } + // verify child does not exist, yet if n, err = n.Child(ctx, name); err != nil { return @@ -434,7 +442,13 @@ func (fs *Decomposedfs) Move(ctx context.Context, oldRef, newRef *provider.Refer return } - // FIXME check is locked + // check lock on target + if lock := newNode.ReadLock(ctx); lock != nil { + lockID, _ := ctxpkg.ContextGetLockID(ctx) + if lock.LockId != lockID { + return errtypes.Locked(lock.LockId) // return we must return the current lockid + } + } return fs.tp.Move(ctx, oldNode, newNode) } @@ -524,34 +538,11 @@ func (fs *Decomposedfs) Delete(ctx context.Context, ref *provider.Reference) (er return errtypes.PermissionDenied(filepath.Join(node.ParentID, node.Name)) } - // WebDAV uses the Token - /* - from https://datatracker.ietf.org/doc/html/rfc4918#section-7 - - Of the methods defined in HTTP and WebDAV, PUT, POST, PROPPATCH, - LOCK, UNLOCK, MOVE, COPY (for the destination resource), DELETE, and - MKCOL are affected by write locks. All other HTTP/WebDAV methods - defined so far -- GET in particular -- function independently of a - write lock. - - from https://datatracker.ietf.org/doc/html/rfc4918#section-7.5 - - In order to prevent these collisions, a lock token MUST be submitted - by an authorized principal for all locked resources that a method may - change or the method MUST fail. A lock token is submitted when it - appears in an If header. For example, if a resource is to be moved - and both the source and destination are locked, then two lock tokens - must be submitted in the If header, one for the source and the other - for the destination. - - If: - () - - */ + // check lock if lock := node.ReadLock(ctx); lock != nil { lockID, _ := ctxpkg.ContextGetLockID(ctx) if lock.LockId != lockID { - return errtypes.Locked(lock.LockId) // return we must return the current lockid + return errtypes.Locked(lock.LockId) } } @@ -649,10 +640,15 @@ func (fs *Decomposedfs) SetLock(ctx context.Context, ref *provider.Reference, lo return errtypes.PermissionDenied(filepath.Join(node.ParentID, node.Name)) } - lockPath := node.InternalPath() + ".lock" - - // FIXME check is locked + // check lock + if lock := node.ReadLock(ctx); lock != nil { + lockID, _ := ctxpkg.ContextGetLockID(ctx) + if lock.LockId != lockID { + return errtypes.Locked(lock.LockId) + } + } + lockPath := node.InternalPath() + ".lock" // O_EXCL to make open fail when the file already exists f, err := os.OpenFile(lockPath, os.O_EXCL|os.O_CREATE|os.O_WRONLY, 0600) if err != nil { diff --git a/pkg/storage/utils/decomposedfs/grants.go b/pkg/storage/utils/decomposedfs/grants.go index 48beb9c018d..0c066aa4d87 100644 --- a/pkg/storage/utils/decomposedfs/grants.go +++ b/pkg/storage/utils/decomposedfs/grants.go @@ -25,6 +25,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" + ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/storage/utils/ace" "github.com/cs3org/reva/pkg/storage/utils/decomposedfs/node" @@ -62,7 +63,13 @@ func (fs *Decomposedfs) AddGrant(ctx context.Context, ref *provider.Reference, g return errtypes.PermissionDenied(filepath.Join(node.ParentID, node.Name)) } - // FIXME check is locked + // check lock + if lock := node.ReadLock(ctx); lock != nil { + lockID, _ := ctxpkg.ContextGetLockID(ctx) + if lock.LockId != lockID { + return errtypes.Locked(lock.LockId) + } + } np := fs.lu.InternalPath(node.ID) e := ace.FromGrant(g) @@ -144,7 +151,13 @@ func (fs *Decomposedfs) RemoveGrant(ctx context.Context, ref *provider.Reference return errtypes.PermissionDenied(filepath.Join(node.ParentID, node.Name)) } - // FIXME check is locked + // check lock + if lock := node.ReadLock(ctx); lock != nil { + lockID, _ := ctxpkg.ContextGetLockID(ctx) + if lock.LockId != lockID { + return errtypes.Locked(lock.LockId) + } + } var attr string if g.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_GROUP { diff --git a/pkg/storage/utils/decomposedfs/metadata.go b/pkg/storage/utils/decomposedfs/metadata.go index 658feb56047..577d7417c73 100644 --- a/pkg/storage/utils/decomposedfs/metadata.go +++ b/pkg/storage/utils/decomposedfs/metadata.go @@ -60,6 +60,14 @@ func (fs *Decomposedfs) SetArbitraryMetadata(ctx context.Context, ref *provider. return errtypes.PermissionDenied(filepath.Join(n.ParentID, n.Name)) } + // check lock + if lock := n.ReadLock(ctx); lock != nil { + lockID, _ := ctxpkg.ContextGetLockID(ctx) + if lock.LockId != lockID { + return errtypes.Locked(lock.LockId) + } + } + nodePath := n.InternalPath() errs := []error{} @@ -148,6 +156,14 @@ func (fs *Decomposedfs) UnsetArbitraryMetadata(ctx context.Context, ref *provide return errtypes.PermissionDenied(filepath.Join(n.ParentID, n.Name)) } + // check lock + if lock := n.ReadLock(ctx); lock != nil { + lockID, _ := ctxpkg.ContextGetLockID(ctx) + if lock.LockId != lockID { + return errtypes.Locked(lock.LockId) + } + } + nodePath := n.InternalPath() errs := []error{} for _, k := range keys { diff --git a/pkg/storage/utils/decomposedfs/recycle.go b/pkg/storage/utils/decomposedfs/recycle.go index 6c4cb2196ae..7d29c8bb4fc 100644 --- a/pkg/storage/utils/decomposedfs/recycle.go +++ b/pkg/storage/utils/decomposedfs/recycle.go @@ -29,6 +29,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/appctx" + ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/storage/utils/decomposedfs/node" "github.com/cs3org/reva/pkg/storage/utils/decomposedfs/xattrs" @@ -279,7 +280,13 @@ func (fs *Decomposedfs) RestoreRecycleItem(ctx context.Context, ref *provider.Re return errtypes.PermissionDenied(key) } - // FIXME check is locked + // check lock + if lock := targetNode.ReadLock(ctx); lock != nil { + lockID, _ := ctxpkg.ContextGetLockID(ctx) + if lock.LockId != lockID { + return errtypes.Locked(lock.LockId) + } + } // Run the restore func return restoreFunc() diff --git a/pkg/storage/utils/decomposedfs/revisions.go b/pkg/storage/utils/decomposedfs/revisions.go index 076883f2c00..7adaf58626b 100644 --- a/pkg/storage/utils/decomposedfs/revisions.go +++ b/pkg/storage/utils/decomposedfs/revisions.go @@ -28,6 +28,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/pkg/appctx" + ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/storage/utils/decomposedfs/node" "github.com/pkg/errors" @@ -165,7 +166,13 @@ func (fs *Decomposedfs) RestoreRevision(ctx context.Context, ref *provider.Refer return errtypes.PermissionDenied(filepath.Join(n.ParentID, n.Name)) } - // FIXME check is locked + // check lock + if lock := n.ReadLock(ctx); lock != nil { + lockID, _ := ctxpkg.ContextGetLockID(ctx) + if lock.LockId != lockID { + return errtypes.Locked(lock.LockId) + } + } // move current version to new revision nodePath := fs.lu.InternalPath(kp[0])