aboutsummaryrefslogtreecommitdiff
path: root/keyring
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2019-12-15 19:31:39 -0800
committerEric Biggers <ebiggers@google.com>2020-01-05 10:02:13 -0800
commit068879664efd8a0f983cbc3e8115571047fe9edd (patch)
tree51019d4d215c2c61b848b2aeaf7b2027952e65e8 /keyring
parent42e0dfe85ec7a75a2fa30c417d57eae60b5a881d (diff)
cmd/fscrypt, keyring: add --all-users option to 'fscrypt lock'
Allow root to provide the --all-users option to 'fscrypt lock' to force an encryption key to be removed from the filesystem (i.e., force an encrypted directory to be locked), even if other users have added it. To implement this option, we just need to use the FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS ioctl rather than FS_IOC_REMOVE_ENCRYPTION_KEY. In theory this option could be implemented for the user keyrings case too, but it would be difficult and the user keyrings are being deprecated for fscrypt, so don't bother.
Diffstat (limited to 'keyring')
-rw-r--r--keyring/fs_keyring.go29
-rw-r--r--keyring/keyring.go8
-rw-r--r--keyring/keyring_test.go50
3 files changed, 63 insertions, 24 deletions
diff --git a/keyring/fs_keyring.go b/keyring/fs_keyring.go
index 970105e..42c1648 100644
--- a/keyring/fs_keyring.go
+++ b/keyring/fs_keyring.go
@@ -228,16 +228,23 @@ func fsRemoveEncryptionKey(descriptor string, mount *filesystem.Mount,
return err
}
- savedPrivs, err := dropPrivsIfNeeded(user, &arg.Key_spec)
- if err != nil {
- return err
+ ioc := unix.FS_IOC_REMOVE_ENCRYPTION_KEY
+ iocName := "FS_IOC_REMOVE_ENCRYPTION_KEY"
+ var savedPrivs *savedPrivs
+ if user == nil {
+ ioc = unix.FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS
+ iocName = "FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS"
+ } else {
+ savedPrivs, err = dropPrivsIfNeeded(user, &arg.Key_spec)
+ if err != nil {
+ return err
+ }
}
- _, _, errno := unix.Syscall(unix.SYS_IOCTL, dir.Fd(),
- unix.FS_IOC_REMOVE_ENCRYPTION_KEY, uintptr(unsafe.Pointer(&arg)))
+ _, _, errno := unix.Syscall(unix.SYS_IOCTL, dir.Fd(), uintptr(ioc), uintptr(unsafe.Pointer(&arg)))
restorePrivs(savedPrivs)
- log.Printf("FS_IOC_REMOVE_ENCRYPTION_KEY(%q, %s) = %v, removal_status_flags=0x%x",
- mount.Path, descriptor, errno, arg.Removal_status_flags)
+ log.Printf("%s(%q, %s) = %v, removal_status_flags=0x%x",
+ iocName, mount.Path, descriptor, errno, arg.Removal_status_flags)
switch errno {
case 0:
switch {
@@ -251,9 +258,11 @@ func fsRemoveEncryptionKey(descriptor string, mount *filesystem.Mount,
// ENOKEY means either the key is completely missing or that the
// current user doesn't have a claim to it. Distinguish between
// these two cases by getting the key status.
- status, _ := fsGetEncryptionKeyStatus(descriptor, mount, user)
- if status == KeyPresentButOnlyOtherUsers {
- return ErrKeyAddedByOtherUsers
+ if user != nil {
+ status, _ := fsGetEncryptionKeyStatus(descriptor, mount, user)
+ if status == KeyPresentButOnlyOtherUsers {
+ return ErrKeyAddedByOtherUsers
+ }
}
return ErrKeyNotPresent
default:
diff --git a/keyring/keyring.go b/keyring/keyring.go
index 925d059..5a75153 100644
--- a/keyring/keyring.go
+++ b/keyring/keyring.go
@@ -100,9 +100,13 @@ func AddEncryptionKey(key *crypto.Key, descriptor string, options *Options) erro
// RemoveEncryptionKey removes an encryption policy key from a kernel keyring.
// It uses either the filesystem keyring for the target Mount or the user
// keyring for the target User.
-func RemoveEncryptionKey(descriptor string, options *Options) error {
+func RemoveEncryptionKey(descriptor string, options *Options, allUsers bool) error {
if shouldUseFsKeyring(descriptor, options) {
- return fsRemoveEncryptionKey(descriptor, options.Mount, options.User)
+ user := options.User
+ if allUsers {
+ user = nil
+ }
+ return fsRemoveEncryptionKey(descriptor, options.Mount, user)
}
return userRemoveKey(options.Service+descriptor, options.User)
}
diff --git a/keyring/keyring_test.go b/keyring/keyring_test.go
index a675a70..8912556 100644
--- a/keyring/keyring_test.go
+++ b/keyring/keyring_test.go
@@ -139,11 +139,11 @@ func testAddAndRemoveKey(t *testing.T, descriptor string, options *Options) {
t.Error(err)
}
assertKeyStatus(t, descriptor, options, KeyPresent)
- if err := RemoveEncryptionKey(descriptor, options); err != nil {
+ if err := RemoveEncryptionKey(descriptor, options, false); err != nil {
t.Error(err)
}
assertKeyStatus(t, descriptor, options, KeyAbsent)
- err := RemoveEncryptionKey(descriptor, options)
+ err := RemoveEncryptionKey(descriptor, options, false)
if err != ErrKeyNotPresent {
t.Error(err)
}
@@ -155,12 +155,12 @@ func testAddAndRemoveKey(t *testing.T, descriptor string, options *Options) {
if err := AddEncryptionKey(fakeValidPolicyKey, descriptor, options); err != nil {
t.Error("AddEncryptionKey should not fail if key already exists")
}
- RemoveEncryptionKey(descriptor, options)
+ RemoveEncryptionKey(descriptor, options, false)
assertKeyStatus(t, descriptor, options, KeyAbsent)
// Adding a key with wrong length should fail
if err := AddEncryptionKey(fakeInvalidPolicyKey, descriptor, options); err == nil {
- RemoveEncryptionKey(descriptor, options)
+ RemoveEncryptionKey(descriptor, options, false)
t.Error("AddEncryptionKey should fail with wrong-length key")
}
assertKeyStatus(t, descriptor, options, KeyAbsent)
@@ -227,14 +227,14 @@ func TestV2PolicyKeyCannotBeRemovedByAnotherUser(t *testing.T) {
assertKeyStatus(t, fakeV2Descriptor, rootOptions, KeyPresentButOnlyOtherUsers)
// Key shouldn't be removable by another user, even root.
- err := RemoveEncryptionKey(fakeV2Descriptor, user2Options)
+ err := RemoveEncryptionKey(fakeV2Descriptor, user2Options, false)
if err != ErrKeyAddedByOtherUsers {
t.Error(err)
}
assertKeyStatus(t, fakeV2Descriptor, user1Options, KeyPresent)
assertKeyStatus(t, fakeV2Descriptor, user2Options, KeyPresentButOnlyOtherUsers)
assertKeyStatus(t, fakeV2Descriptor, rootOptions, KeyPresentButOnlyOtherUsers)
- err = RemoveEncryptionKey(fakeV2Descriptor, rootOptions)
+ err = RemoveEncryptionKey(fakeV2Descriptor, rootOptions, false)
if err != ErrKeyAddedByOtherUsers {
t.Error(err)
}
@@ -242,7 +242,7 @@ func TestV2PolicyKeyCannotBeRemovedByAnotherUser(t *testing.T) {
assertKeyStatus(t, fakeV2Descriptor, user2Options, KeyPresentButOnlyOtherUsers)
assertKeyStatus(t, fakeV2Descriptor, rootOptions, KeyPresentButOnlyOtherUsers)
- if err := RemoveEncryptionKey(fakeV2Descriptor, user1Options); err != nil {
+ if err := RemoveEncryptionKey(fakeV2Descriptor, user1Options, false); err != nil {
t.Error(err)
}
assertKeyStatus(t, fakeV2Descriptor, user1Options, KeyAbsent)
@@ -267,7 +267,7 @@ func TestV2PolicyKeyMultipleUsers(t *testing.T) {
assertKeyStatus(t, fakeV2Descriptor, rootOptions, KeyPresentButOnlyOtherUsers)
// Remove key as one user.
- err := RemoveEncryptionKey(fakeV2Descriptor, user1Options)
+ err := RemoveEncryptionKey(fakeV2Descriptor, user1Options, false)
if err != ErrKeyAddedByOtherUsers {
t.Error(err)
}
@@ -276,7 +276,7 @@ func TestV2PolicyKeyMultipleUsers(t *testing.T) {
assertKeyStatus(t, fakeV2Descriptor, rootOptions, KeyPresentButOnlyOtherUsers)
// Remove key as the other user.
- err = RemoveEncryptionKey(fakeV2Descriptor, user2Options)
+ err = RemoveEncryptionKey(fakeV2Descriptor, user2Options, false)
if err != nil {
t.Error(err)
}
@@ -296,7 +296,7 @@ func TestV2PolicyKeyWrongDescriptor(t *testing.T) {
for _, desc := range wrongV2Descriptors {
if err := AddEncryptionKey(fakeValidPolicyKey, desc, options); err == nil {
- RemoveEncryptionKey(desc, options)
+ RemoveEncryptionKey(desc, options, false)
t.Error("For v2 policy keys, AddEncryptionKey should fail if the descriptor is wrong")
}
}
@@ -308,10 +308,10 @@ func TestV2PolicyKeyBadMount(t *testing.T) {
User: testUser,
}
if err := AddEncryptionKey(fakeValidPolicyKey, fakeV2Descriptor, options); err == nil {
- RemoveEncryptionKey(fakeV2Descriptor, options)
+ RemoveEncryptionKey(fakeV2Descriptor, options, false)
t.Error("AddEncryptionKey should have failed with bad mount!")
}
- if err := RemoveEncryptionKey(fakeV2Descriptor, options); err == nil {
+ if err := RemoveEncryptionKey(fakeV2Descriptor, options, false); err == nil {
t.Error("RemoveEncryptionKey should have failed with bad mount!")
}
status, err := GetEncryptionKeyStatus(fakeV2Descriptor, options)
@@ -322,3 +322,29 @@ func TestV2PolicyKeyBadMount(t *testing.T) {
t.Error("GetEncryptionKeyStatus should have returned unknown status!")
}
}
+
+func TestV2PolicyKeyRemoveForAllUsers(t *testing.T) {
+ rootOptions, userOptions := getOptionsForFsKeyringUsers(t, 2)
+ user1Options := userOptions[0]
+ user2Options := userOptions[1]
+
+ // Add key as two non-root users.
+ if err := AddEncryptionKey(fakeValidPolicyKey, fakeV2Descriptor, user1Options); err != nil {
+ t.Error(err)
+ }
+ if err := AddEncryptionKey(fakeValidPolicyKey, fakeV2Descriptor, user2Options); err != nil {
+ t.Error(err)
+ }
+ assertKeyStatus(t, fakeV2Descriptor, user1Options, KeyPresent)
+ assertKeyStatus(t, fakeV2Descriptor, user2Options, KeyPresent)
+ assertKeyStatus(t, fakeV2Descriptor, rootOptions, KeyPresentButOnlyOtherUsers)
+
+ // Remove key for all users as root.
+ err := RemoveEncryptionKey(fakeV2Descriptor, rootOptions, true)
+ if err != nil {
+ t.Error(err)
+ }
+ assertKeyStatus(t, fakeV2Descriptor, user1Options, KeyAbsent)
+ assertKeyStatus(t, fakeV2Descriptor, user2Options, KeyAbsent)
+ assertKeyStatus(t, fakeV2Descriptor, rootOptions, KeyAbsent)
+}