From 4c7c6631cc5a27cc6b4431f5ad3805a2d624c5f5 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 19 Dec 2021 21:19:25 -0600 Subject: Set owner of login protectors to correct user When the root user creates a login protector for a non-root user, make sure to chown() the protector file to make it owned by the user. Without this, the protector cannot be updated by the user, which causes it to get out of sync if the user changes their login passphrase. Fixes https://github.com/google/fscrypt/issues/319 --- filesystem/filesystem.go | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'filesystem') diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index 9b5b7e2..456a4fc 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -37,6 +37,7 @@ import ( "io/ioutil" "log" "os" + "os/user" "path/filepath" "sort" "strings" @@ -47,6 +48,7 @@ import ( "golang.org/x/sys/unix" "github.com/google/fscrypt/metadata" + "github.com/google/fscrypt/util" ) // ErrAlreadySetup indicates that a filesystem is already setup for fscrypt. @@ -392,7 +394,7 @@ func syncDirectory(dirPath string) error { // writeDataAtomic writes the data to the path such that the data is either // written to stable storage or an error is returned. -func (m *Mount) writeDataAtomic(path string, data []byte) error { +func (m *Mount) writeDataAtomic(path string, data []byte, owner *user.User) error { // Write the data to a temporary file, sync it, then rename into place // so that the operation will be atomic. dirPath := filepath.Dir(path) @@ -407,6 +409,14 @@ func (m *Mount) writeDataAtomic(path string, data []byte) error { tempFile.Close() return err } + if owner != nil { + if err = util.Chown(tempFile, owner); err != nil { + log.Printf("could not set owner of %q to %v: %v", + path, owner.Username, err) + tempFile.Close() + return err + } + } if _, err = tempFile.Write(data); err != nil { tempFile.Close() return err @@ -428,7 +438,7 @@ func (m *Mount) writeDataAtomic(path string, data []byte) error { // addMetadata writes the metadata structure to the file with the specified // path. This will overwrite any existing data. The operation is atomic. -func (m *Mount) addMetadata(path string, md metadata.Metadata) error { +func (m *Mount) addMetadata(path string, md metadata.Metadata, owner *user.User) error { if err := md.CheckValidity(); err != nil { return errors.Wrap(err, "provided metadata is invalid") } @@ -439,7 +449,7 @@ func (m *Mount) addMetadata(path string, md metadata.Metadata) error { } log.Printf("writing metadata to %q", path) - return m.writeDataAtomic(path, data) + return m.writeDataAtomic(path, data, owner) } // getMetadata reads the metadata structure from the file with the specified @@ -480,7 +490,8 @@ func (m *Mount) removeMetadata(path string) error { // will fail with ErrLinkedProtector if a linked protector with this descriptor // already exists on the filesystem. func (m *Mount) AddProtector(data *metadata.ProtectorData) error { - if err := m.CheckSetup(); err != nil { + var err error + if err = m.CheckSetup(); err != nil { return err } if isRegularFile(m.linkedProtectorPath(data.ProtectorDescriptor)) { @@ -488,7 +499,15 @@ func (m *Mount) AddProtector(data *metadata.ProtectorData) error { data.ProtectorDescriptor, m.Path) } path := m.protectorPath(data.ProtectorDescriptor) - return m.addMetadata(path, data) + + var owner *user.User + if data.Source == metadata.SourceType_pam_passphrase && util.IsUserRoot() { + owner, err = util.UserFromUID(data.Uid) + if err != nil { + return err + } + } + return m.addMetadata(path, data, owner) } // AddLinkedProtector adds a link in this filesystem to the protector metadata @@ -528,7 +547,7 @@ func (m *Mount) AddLinkedProtector(descriptor string, dest *Mount) (bool, error) if err != nil { return false, err } - return true, m.writeDataAtomic(linkPath, []byte(newLink)) + return true, m.writeDataAtomic(linkPath, []byte(newLink), nil) } // GetRegularProtector looks up the protector metadata by descriptor. This will @@ -609,7 +628,7 @@ func (m *Mount) AddPolicy(data *metadata.PolicyData) error { return err } - return m.addMetadata(m.PolicyPath(data.KeyDescriptor), data) + return m.addMetadata(m.PolicyPath(data.KeyDescriptor), data, nil) } // GetPolicy looks up the policy metadata by descriptor. -- cgit v1.2.3