aboutsummaryrefslogtreecommitdiff
path: root/actions
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2022-02-23 12:35:04 -0800
committerEric Biggers <ebiggers@google.com>2022-02-23 12:35:04 -0800
commitd4ce0b892cbe68db9f90f4015342e6a9069b079c (patch)
tree9934a74b71590b5e4bcd0067391ffe3ec602a77a /actions
parent85a747493ff368a72f511619ecd391016ecb933c (diff)
Make all new metadata files owned by user when needed
Since commit 4c7c6631cc5a ("Set owner of login protectors to correct user"), login protectors are made owned by the user when root creates one on a user's behalf. That's good, but the same isn't true of other files that get created at the same time: - The policy protecting the directory - The protector link file, if the policy is on a different filesystem - The recovery protector, if the policy is on a different filesystem - The recovery instructions file In preparation for setting all metadata files to mode 0600, start making all these files owned by the user in this scenario as well.
Diffstat (limited to 'actions')
-rw-r--r--actions/policy.go36
-rw-r--r--actions/policy_test.go8
-rw-r--r--actions/protector.go16
-rw-r--r--actions/protector_test.go4
-rw-r--r--actions/recovery.go8
5 files changed, 56 insertions, 16 deletions
diff --git a/actions/policy.go b/actions/policy.go
index 3b8eb30..3b20176 100644
--- a/actions/policy.go
+++ b/actions/policy.go
@@ -23,6 +23,7 @@ import (
"fmt"
"log"
"os"
+ "os/user"
"github.com/golang/protobuf/proto"
"github.com/pkg/errors"
@@ -178,6 +179,7 @@ type Policy struct {
data *metadata.PolicyData
key *crypto.Key
created bool
+ ownerIfCreating *user.User
newLinkedProtectors []string
}
@@ -210,6 +212,12 @@ func CreatePolicy(ctx *Context, protector *Protector) (*Policy, error) {
created: true,
}
+ policy.ownerIfCreating, err = getOwnerOfMetadataForProtector(protector)
+ if err != nil {
+ policy.Lock()
+ return nil, err
+ }
+
if err = policy.AddProtector(protector); err != nil {
policy.Lock()
return nil, err
@@ -410,6 +418,25 @@ func (policy *Policy) UsesProtector(protector *Protector) bool {
return ok
}
+// getOwnerOfMetadataForProtector returns the User to whom the owner of any new
+// policies or protector links for the given protector should be set.
+//
+// This will return a non-nil value only when the protector is a login protector
+// and the process is running as root. In this scenario, root is setting up
+// encryption on the user's behalf, so we need to make new policies and
+// protector links owned by the user (rather than root) to allow them to be read
+// by the user, just like the login protector itself which is handled elsewhere.
+func getOwnerOfMetadataForProtector(protector *Protector) (*user.User, error) {
+ if protector.data.Source == metadata.SourceType_pam_passphrase && util.IsUserRoot() {
+ owner, err := util.UserFromUID(protector.data.Uid)
+ if err != nil {
+ return nil, err
+ }
+ return owner, nil
+ }
+ return nil, nil
+}
+
// AddProtector updates the data that is wrapping the Policy Key so that the
// provided Protector is now protecting the specified Policy. If an error is
// returned, no data has been changed. If the policy and protector are on
@@ -427,8 +454,13 @@ func (policy *Policy) AddProtector(protector *Protector) error {
// to it on the policy's filesystem.
if policy.Context.Mount != protector.Context.Mount {
log.Printf("policy on %s\n protector on %s\n", policy.Context.Mount, protector.Context.Mount)
+ ownerIfCreating, err := getOwnerOfMetadataForProtector(protector)
+ if err != nil {
+ return err
+ }
isNewLink, err := policy.Context.Mount.AddLinkedProtector(
- protector.Descriptor(), protector.Context.Mount, protector.Context.TrustedUser)
+ protector.Descriptor(), protector.Context.Mount,
+ protector.Context.TrustedUser, ownerIfCreating)
if err != nil {
return err
}
@@ -554,7 +586,7 @@ func (policy *Policy) CanBeAppliedWithoutProvisioning() bool {
// commitData writes the Policy's current data to the filesystem.
func (policy *Policy) commitData() error {
- return policy.Context.Mount.AddPolicy(policy.data)
+ return policy.Context.Mount.AddPolicy(policy.data, policy.ownerIfCreating)
}
// findWrappedPolicyKey returns the index of the wrapped policy key
diff --git a/actions/policy_test.go b/actions/policy_test.go
index 07943b8..8248862 100644
--- a/actions/policy_test.go
+++ b/actions/policy_test.go
@@ -27,7 +27,7 @@ import (
// Makes a protector and policy
func makeBoth() (*Protector, *Policy, error) {
- protector, err := CreateProtector(testContext, testProtectorName, goodCallback)
+ protector, err := CreateProtector(testContext, testProtectorName, goodCallback, nil)
if err != nil {
return nil, nil, err
}
@@ -68,7 +68,7 @@ func TestPolicyGoodAddProtector(t *testing.T) {
t.Fatal(err)
}
- pro2, err := CreateProtector(testContext, testProtectorName2, goodCallback)
+ pro2, err := CreateProtector(testContext, testProtectorName2, goodCallback, nil)
if err != nil {
t.Fatal(err)
}
@@ -103,7 +103,7 @@ func TestPolicyGoodRemoveProtector(t *testing.T) {
t.Fatal(err)
}
- pro2, err := CreateProtector(testContext, testProtectorName2, goodCallback)
+ pro2, err := CreateProtector(testContext, testProtectorName2, goodCallback, nil)
if err != nil {
t.Fatal(err)
}
@@ -129,7 +129,7 @@ func TestPolicyBadRemoveProtector(t *testing.T) {
t.Fatal(err)
}
- pro2, err := CreateProtector(testContext, testProtectorName2, goodCallback)
+ pro2, err := CreateProtector(testContext, testProtectorName2, goodCallback, nil)
if err != nil {
t.Fatal(err)
}
diff --git a/actions/protector.go b/actions/protector.go
index 1171c83..b986eb0 100644
--- a/actions/protector.go
+++ b/actions/protector.go
@@ -109,17 +109,18 @@ func checkIfUserHasLoginProtector(ctx *Context, uid int64) error {
// to unlock policies and create new polices. As with the key struct, a
// Protector should be wiped after use.
type Protector struct {
- Context *Context
- data *metadata.ProtectorData
- key *crypto.Key
- created bool
+ Context *Context
+ data *metadata.ProtectorData
+ key *crypto.Key
+ created bool
+ ownerIfCreating *user.User
}
// CreateProtector creates an unlocked protector with a given name (name only
// needed for custom and raw protector types). The keyFn provided to create the
// Protector key will only be called once. If an error is returned, no data has
// been changed on the filesystem.
-func CreateProtector(ctx *Context, name string, keyFn KeyFunc) (*Protector, error) {
+func CreateProtector(ctx *Context, name string, keyFn KeyFunc, owner *user.User) (*Protector, error) {
if err := ctx.checkContext(); err != nil {
return nil, err
}
@@ -147,7 +148,8 @@ func CreateProtector(ctx *Context, name string, keyFn KeyFunc) (*Protector, erro
Name: name,
Source: ctx.Config.Source,
},
- created: true,
+ created: true,
+ ownerIfCreating: owner,
}
// Extra data is needed for some SourceTypes
@@ -294,5 +296,5 @@ func (protector *Protector) Rewrap(keyFn KeyFunc) error {
return err
}
- return protector.Context.Mount.AddProtector(protector.data)
+ return protector.Context.Mount.AddProtector(protector.data, protector.ownerIfCreating)
}
diff --git a/actions/protector_test.go b/actions/protector_test.go
index 6c81d49..f20dbcf 100644
--- a/actions/protector_test.go
+++ b/actions/protector_test.go
@@ -43,7 +43,7 @@ func badCallback(info ProtectorInfo, retry bool) (*crypto.Key, error) {
// Tests that we can create a valid protector.
func TestCreateProtector(t *testing.T) {
- p, err := CreateProtector(testContext, testProtectorName, goodCallback)
+ p, err := CreateProtector(testContext, testProtectorName, goodCallback, nil)
if err != nil {
t.Error(err)
} else {
@@ -54,7 +54,7 @@ func TestCreateProtector(t *testing.T) {
// Tests that a failure in the callback is relayed back to the caller.
func TestBadCallback(t *testing.T) {
- p, err := CreateProtector(testContext, testProtectorName, badCallback)
+ p, err := CreateProtector(testContext, testProtectorName, badCallback, nil)
if err == nil {
p.Lock()
p.Destroy()
diff --git a/actions/recovery.go b/actions/recovery.go
index f533906..8a769cc 100644
--- a/actions/recovery.go
+++ b/actions/recovery.go
@@ -25,6 +25,7 @@ import (
"github.com/google/fscrypt/crypto"
"github.com/google/fscrypt/metadata"
+ "github.com/google/fscrypt/util"
)
// modifiedContextWithSource returns a copy of ctx with the protector source
@@ -66,7 +67,7 @@ func AddRecoveryPassphrase(policy *Policy, dirname string) (*crypto.Key, *Protec
if seq != 1 {
name += " (" + strconv.Itoa(seq) + ")"
}
- recoveryProtector, err = CreateProtector(customCtx, name, getPassphraseFn)
+ recoveryProtector, err = CreateProtector(customCtx, name, getPassphraseFn, policy.ownerIfCreating)
if err == nil {
break
}
@@ -121,5 +122,10 @@ It is safe to keep it around though, as the recovery passphrase is high-entropy.
if _, err = file.WriteString(str); err != nil {
return err
}
+ if recoveryProtector.ownerIfCreating != nil {
+ if err = util.Chown(file, recoveryProtector.ownerIfCreating); err != nil {
+ return err
+ }
+ }
return file.Sync()
}