Mounttablelib: Allow the Admin of a directory to delete any
contained nodes. James, this Bud's for you.
Change-Id: I81da2bcfd6ba4039696384bb6fd9a384318cb6a2
diff --git a/services/mounttable/mounttablelib/mounttable.go b/services/mounttable/mounttablelib/mounttable.go
index a3582ff..3d9fa39 100644
--- a/services/mounttable/mounttablelib/mounttable.go
+++ b/services/mounttable/mounttablelib/mounttable.go
@@ -360,7 +360,7 @@
// findNode finds a node in the table and optionally creates a path to it.
//
// If a node is found, on return it and its parent are locked.
-func (mt *mountTable) findNode(ctx *context.T, call security.Call, elems []string, create bool, tags []mounttable.Tag) (*node, error) {
+func (mt *mountTable) findNode(ctx *context.T, call security.Call, elems []string, create bool, tags, ptags []mounttable.Tag) (*node, error) {
n, nelems, err := mt.traverse(ctx, call, elems, create)
if err != nil {
return nil, err
@@ -373,10 +373,18 @@
n.Unlock()
return nil, nil
}
+ // Either the node has to satisfy tags or the parent has to satisfy ptags.
if err := n.satisfies(mt, ctx, call, tags); err != nil {
- n.parent.Unlock()
- n.Unlock()
- return nil, err
+ if ptags == nil {
+ n.parent.Unlock()
+ n.Unlock()
+ return nil, err
+ }
+ if err := n.parent.satisfies(mt, ctx, call, ptags); err != nil {
+ n.parent.Unlock()
+ n.Unlock()
+ return nil, err
+ }
}
return n, nil
}
@@ -486,7 +494,7 @@
}
// Find/create node in namespace and add the mount.
- n, werr := mt.findNode(ctx, call.Security(), ms.elems, true, mountTags)
+ n, werr := mt.findNode(ctx, call.Security(), ms.elems, true, mountTags, nil)
if werr != nil {
return werr
}
@@ -579,7 +587,7 @@
func (ms *mountContext) Unmount(ctx *context.T, call rpc.ServerCall, server string) error {
vlog.VI(2).Infof("*********************Unmount %q, %s", ms.name, server)
mt := ms.mt
- n, err := mt.findNode(ctx, call.Security(), ms.elems, false, mountTags)
+ n, err := mt.findNode(ctx, call.Security(), ms.elems, false, mountTags, nil)
if err != nil {
return err
}
@@ -612,8 +620,9 @@
return verror.New(errCantDeleteRoot, ctx)
}
mt := ms.mt
- // Find and lock the parent node.
- n, err := mt.findNode(ctx, call.Security(), ms.elems, false, removeTags)
+ // Find and lock the parent node and parent node. Either the node or its parent has
+ // to satisfy removeTags.
+ n, err := mt.findNode(ctx, call.Security(), ms.elems, false, removeTags, removeTags)
if err != nil {
return err
}
@@ -758,7 +767,7 @@
go func() {
defer close(ch)
// If there was an access error, just ignore the entry, i.e., make it invisible.
- n, err := mt.findNode(ctx, scall, ms.elems, false, nil)
+ n, err := mt.findNode(ctx, scall, ms.elems, false, nil, nil)
if err != nil {
return
}
@@ -793,7 +802,7 @@
mt := ms.mt
// Find/create node in namespace and add the mount.
- n, err := mt.findNode(ctx, call.Security(), ms.elems, true, setTags)
+ n, err := mt.findNode(ctx, call.Security(), ms.elems, true, setTags, nil)
if err != nil {
return err
}
@@ -839,7 +848,7 @@
mt := ms.mt
// Find node in namespace and add the mount.
- n, err := mt.findNode(ctx, call.Security(), ms.elems, false, getTags)
+ n, err := mt.findNode(ctx, call.Security(), ms.elems, false, getTags, nil)
if err != nil {
return nil, "", err
}
diff --git a/services/mounttable/mounttablelib/mounttable_test.go b/services/mounttable/mounttablelib/mounttable_test.go
index a8f9e7f..aa64dea 100644
--- a/services/mounttable/mounttablelib/mounttable_test.go
+++ b/services/mounttable/mounttablelib/mounttable_test.go
@@ -601,6 +601,12 @@
checkExists(t, rootCtx, estr, "one/bright/day", false)
doDeleteNode(t, bobCtx, estr, "one/bright", true)
checkExists(t, rootCtx, estr, "one/bright", false)
+
+ // Make sure directory admin can delete directory children.
+ perms := access.Permissions{"Admin": access.AccessList{In: []security.BlessingPattern{"bob"}}}
+ doSetPermissions(t, bobCtx, estr, "hoohaa", perms, "", false)
+ doDeleteNode(t, rootCtx, estr, "hoohaa", true)
+ checkExists(t, rootCtx, estr, "hoohaa", false)
}
func TestServerFormat(t *testing.T) {
diff --git a/services/mounttable/mounttablelib/persistentstore.go b/services/mounttable/mounttablelib/persistentstore.go
index 0cb614d..a96eb19 100644
--- a/services/mounttable/mounttablelib/persistentstore.go
+++ b/services/mounttable/mounttablelib/persistentstore.go
@@ -131,7 +131,7 @@
}
elems := strings.Split(e.N, "/")
- n, err := mt.findNode(nil, nil, elems, true, nil)
+ n, err := mt.findNode(nil, nil, elems, true, nil, nil)
if n != nil || err == nil {
n.creator = e.C
if e.D {
diff --git a/services/mounttable/mounttablelib/versionedpermissions.go b/services/mounttable/mounttablelib/versionedpermissions.go
index 95a044a..85069b8 100644
--- a/services/mounttable/mounttablelib/versionedpermissions.go
+++ b/services/mounttable/mounttablelib/versionedpermissions.go
@@ -143,7 +143,7 @@
}
// Create name and add the Permissions map to it.
- n, err := mt.findNode(nil, nil, elems, true, nil)
+ n, err := mt.findNode(nil, nil, elems, true, nil, nil)
if n != nil || err == nil {
vlog.VI(2).Infof("added perms %v to %s", perms, name)
if isPattern {