aboutsummaryrefslogtreecommitdiff
path: root/filesystem/filesystem.go
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2020-01-27 20:16:35 -0800
committerEric Biggers <ebiggers@google.com>2020-01-28 10:45:52 -0800
commit07d744068d437b09d7a07975e88e18440f5db2f3 (patch)
tree82171c13401976e80520f3ba98a02bc9c9d81ec4 /filesystem/filesystem.go
parent5c08edd521deadd36bec36662d30681b01253d62 (diff)
filesystem: don't overwrite existing protector links
When adding a protector to a policy, don't unconditionally overwrite the protector link, because it may already exist. Instead, if it already exists and points to the mount, just use it. If it already exists and points to the wrong place, return an error. Also add a bool to the return value of AddLinkedProtector() so that callers can check whether the link was newly created or not.
Diffstat (limited to 'filesystem/filesystem.go')
-rw-r--r--filesystem/filesystem.go37
1 files changed, 28 insertions, 9 deletions
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 9bae72b..e0ef110 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -393,24 +393,43 @@ func (m *Mount) AddProtector(data *metadata.ProtectorData) error {
}
// AddLinkedProtector adds a link in this filesystem to the protector metadata
-// in the dest filesystem.
-func (m *Mount) AddLinkedProtector(descriptor string, dest *Mount) error {
+// in the dest filesystem, if one doesn't already exist. On success, the return
+// value is a nil error and a bool that is true iff the link is newly created.
+func (m *Mount) AddLinkedProtector(descriptor string, dest *Mount) (bool, error) {
if err := m.CheckSetup(); err != nil {
- return err
+ return false, err
}
// Check that the link is good (descriptor exists, filesystem has UUID).
if _, err := dest.GetRegularProtector(descriptor); err != nil {
- return err
+ return false, err
+ }
+
+ linkPath := m.linkedProtectorPath(descriptor)
+
+ // Check whether the link already exists.
+ existingLink, err := ioutil.ReadFile(linkPath)
+ if err == nil {
+ existingLinkedMnt, err := getMountFromLink(string(existingLink))
+ if err != nil {
+ return false, err
+ }
+ if existingLinkedMnt != dest {
+ return false, errors.Wrapf(ErrFollowLink, "link %q points to %q, but expected %q",
+ linkPath, existingLinkedMnt.Path, dest.Path)
+ }
+ return false, nil
+ }
+ if !os.IsNotExist(err) {
+ return false, err
}
// Right now, we only make links using UUIDs.
- link, err := makeLink(dest, "UUID")
+ var newLink string
+ newLink, err = makeLink(dest, "UUID")
if err != nil {
- return dest.err(err)
+ return false, dest.err(err)
}
-
- path := m.linkedProtectorPath(descriptor)
- return m.err(m.writeDataAtomic(path, []byte(link)))
+ return true, m.err(m.writeDataAtomic(linkPath, []byte(newLink)))
}
// GetRegularProtector looks up the protector metadata by descriptor. This will