diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index c654effb83f5..8c600ead0e2e 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -11,6 +11,7 @@ * * - FS_IOC_ADD_ENCRYPTION_KEY * - FS_IOC_REMOVE_ENCRYPTION_KEY + * - FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS * - FS_IOC_GET_ENCRYPTION_KEY_STATUS * * See the "User API" section of Documentation/filesystems/fscrypt.rst for more @@ -699,8 +700,10 @@ static int try_to_lock_encrypted_files(struct super_block *sb, /* * Try to remove an fscrypt master encryption key. * - * This removes the current user's claim to the key, then removes the key itself - * if no other users have claims. + * FS_IOC_REMOVE_ENCRYPTION_KEY (all_users=false) removes the current user's + * claim to the key, then removes the key itself if no other users have claims. + * FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS (all_users=true) always removes the + * key itself. * * To "remove the key itself", first we wipe the actual master key secret, so * that no more inodes can be unlocked with it. Then we try to evict all cached @@ -715,7 +718,7 @@ static int try_to_lock_encrypted_files(struct super_block *sb, * For more details, see the "Removing keys" section of * Documentation/filesystems/fscrypt.rst. */ -int fscrypt_ioctl_remove_key(struct file *filp, void __user *_uarg) +static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users) { struct super_block *sb = file_inode(filp)->i_sb; struct fscrypt_remove_key_arg __user *uarg = _uarg; @@ -751,9 +754,12 @@ int fscrypt_ioctl_remove_key(struct file *filp, void __user *_uarg) down_write(&key->sem); - /* If relevant, remove current user's claim to the key */ + /* If relevant, remove current user's (or all users) claim to the key */ if (mk->mk_users && mk->mk_users->keys.nr_leaves_on_tree != 0) { - err = remove_master_key_user(mk); + if (all_users) + err = keyring_clear(mk->mk_users); + else + err = remove_master_key_user(mk); if (err) { up_write(&key->sem); goto out_put_key; @@ -809,8 +815,21 @@ out_put_key: err = put_user(status_flags, &uarg->removal_status_flags); return err; } + +int fscrypt_ioctl_remove_key(struct file *filp, void __user *uarg) +{ + return do_remove_key(filp, uarg, false); +} EXPORT_SYMBOL_GPL(fscrypt_ioctl_remove_key); +int fscrypt_ioctl_remove_key_all_users(struct file *filp, void __user *uarg) +{ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return do_remove_key(filp, uarg, true); +} +EXPORT_SYMBOL_GPL(fscrypt_ioctl_remove_key_all_users); + /* * Retrieve the status of an fscrypt master encryption key. * diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 8b8ff0484042..f622f7460ed8 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -143,6 +143,8 @@ extern int fscrypt_inherit_context(struct inode *, struct inode *, extern void fscrypt_sb_free(struct super_block *sb); extern int fscrypt_ioctl_add_key(struct file *filp, void __user *arg); extern int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg); +extern int fscrypt_ioctl_remove_key_all_users(struct file *filp, + void __user *arg); extern int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg); /* keysetup.c */ @@ -396,6 +398,12 @@ static inline int fscrypt_ioctl_remove_key(struct file *filp, void __user *arg) return -EOPNOTSUPP; } +static inline int fscrypt_ioctl_remove_key_all_users(struct file *filp, + void __user *arg) +{ + return -EOPNOTSUPP; +} + static inline int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg) { diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index b9fb775e3db8..39ccfe9311c3 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -148,6 +148,7 @@ struct fscrypt_get_key_status_arg { #define FS_IOC_GET_ENCRYPTION_POLICY_EX _IOWR('f', 22, __u8[9]) /* size + version */ #define FS_IOC_ADD_ENCRYPTION_KEY _IOWR('f', 23, struct fscrypt_add_key_arg) #define FS_IOC_REMOVE_ENCRYPTION_KEY _IOWR('f', 24, struct fscrypt_remove_key_arg) +#define FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS _IOWR('f', 25, struct fscrypt_remove_key_arg) #define FS_IOC_GET_ENCRYPTION_KEY_STATUS _IOWR('f', 26, struct fscrypt_get_key_status_arg) /**********************************************************************/