From 98261f39e992543a404353ba2d8f36cb739f329f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 9 Oct 2019 14:35:48 -0700 Subject: [PATCH] ANDROID: fscrypt: add key removal notifier chain Add a notifier chain so that sdcardfs can evict its dentries when an fscrypt key is about to be removed. This is needed for the FS_IOC_REMOVE_ENCRYPTION_KEY ioctl to properly "lock" the encrypted files underneath sdcardfs when an Android user is stopped. This is meant to be a temporary patch carried as part of the sdcardfs patchset until either we stop using sdcardfs, we get sdcardfs upstream, or we find a way to provide what sdcardfs needs while also benefitting a user upstream. Bug: 120446149 Bug: 142275883 Test: see I83b451a2bc40c72fcd01d24aa5c34ad8de427534 Change-Id: Iec79775a71057d05a371d77da4a6541cb8e09cb7 Signed-off-by: Eric Biggers --- fs/crypto/keyring.c | 22 ++++++++++++++++++++++ include/linux/fscrypt.h | 14 ++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index c34fa7c61b43..b3ce0db8b9b8 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -704,12 +704,34 @@ static int check_for_busy_inodes(struct super_block *sb, return -EBUSY; } +static BLOCKING_NOTIFIER_HEAD(fscrypt_key_removal_notifiers); + +/* + * Register a function to be executed when the FS_IOC_REMOVE_ENCRYPTION_KEY + * ioctl has removed a key and is about to try evicting inodes. + */ +int fscrypt_register_key_removal_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&fscrypt_key_removal_notifiers, + nb); +} +EXPORT_SYMBOL_GPL(fscrypt_register_key_removal_notifier); + +int fscrypt_unregister_key_removal_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&fscrypt_key_removal_notifiers, + nb); +} +EXPORT_SYMBOL_GPL(fscrypt_unregister_key_removal_notifier); + static int try_to_lock_encrypted_files(struct super_block *sb, struct fscrypt_master_key *mk) { int err1; int err2; + blocking_notifier_call_chain(&fscrypt_key_removal_notifiers, 0, NULL); + /* * An inode can't be evicted while it is dirty or has dirty pages. * Thus, we first have to clean the inodes in ->mk_decrypted_inodes. diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index f622f7460ed8..4ce4a970bb56 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -146,6 +146,8 @@ 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); +extern int fscrypt_register_key_removal_notifier(struct notifier_block *nb); +extern int fscrypt_unregister_key_removal_notifier(struct notifier_block *nb); /* keysetup.c */ extern int fscrypt_get_encryption_info(struct inode *); @@ -410,6 +412,18 @@ static inline int fscrypt_ioctl_get_key_status(struct file *filp, return -EOPNOTSUPP; } +static inline int fscrypt_register_key_removal_notifier( + struct notifier_block *nb) +{ + return 0; +} + +static inline int fscrypt_unregister_key_removal_notifier( + struct notifier_block *nb) +{ + return 0; +} + /* keysetup.c */ static inline int fscrypt_get_encryption_info(struct inode *inode) {