| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Eric Biggers <ebiggers@google.com> |
| Date: Wed, 9 Oct 2019 14:35:49 -0700 |
| Subject: ANDROID: sdcardfs: evict dentries on fscrypt key removal |
| |
| Use the fscrypt key removal notifier chain to make sdcardfs 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. |
| |
| Test: pm create-user 10 |
| am start-user 10 |
| find /data/media/10/ # filenames are in plaintext form |
| am stop-user 10 |
| find /data/media/10/ # filenames are in ciphertext form |
| |
| (But currently the kernel and vold still warn about other files |
| still being open, due to b/140762419) |
| |
| Bug: 120446149 |
| Bug: 142275883 |
| Change-Id: I83b451a2bc40c72fcd01d24aa5c34ad8de427534 |
| Signed-off-by: Eric Biggers <ebiggers@google.com> |
| --- |
| fs/sdcardfs/main.c | 7 +++++++ |
| fs/sdcardfs/sdcardfs.h | 3 +++ |
| fs/sdcardfs/super.c | 17 +++++++++++++++++ |
| 3 files changed, 27 insertions(+) |
| |
| diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c |
| index 818122410bfe..19fa9c4af462 100644 |
| --- a/fs/sdcardfs/main.c |
| +++ b/fs/sdcardfs/main.c |
| @@ -21,6 +21,7 @@ |
| #include "sdcardfs.h" |
| #include <linux/fs_context.h> |
| #include <linux/fs_parser.h> |
| +#include <linux/fscrypt.h> |
| #include <linux/module.h> |
| #include <linux/types.h> |
| #include <linux/parser.h> |
| @@ -293,6 +294,9 @@ static int __sdcardfs_fill_super( |
| list_add(&sb_info->list, &sdcardfs_super_list); |
| mutex_unlock(&sdcardfs_super_list_lock); |
| |
| + sb_info->fscrypt_nb.notifier_call = sdcardfs_on_fscrypt_key_removed; |
| + fscrypt_register_key_removal_notifier(&sb_info->fscrypt_nb); |
| + |
| if (!(fc->sb_flags & SB_SILENT)) |
| pr_info("sdcardfs: mounted on top of %s type %s\n", |
| dev_name, lower_sb->s_type->name); |
| @@ -331,6 +335,9 @@ void sdcardfs_kill_sb(struct super_block *sb) |
| |
| if (sb->s_magic == SDCARDFS_SUPER_MAGIC && sb->s_fs_info) { |
| sbi = SDCARDFS_SB(sb); |
| + |
| + fscrypt_unregister_key_removal_notifier(&sbi->fscrypt_nb); |
| + |
| mutex_lock(&sdcardfs_super_list_lock); |
| list_del(&sbi->list); |
| mutex_unlock(&sdcardfs_super_list_lock); |
| diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h |
| index f813d23cddcd..4af4f163399b 100644 |
| --- a/fs/sdcardfs/sdcardfs.h |
| +++ b/fs/sdcardfs/sdcardfs.h |
| @@ -152,6 +152,8 @@ extern struct inode *sdcardfs_iget(struct super_block *sb, |
| struct inode *lower_inode, userid_t id); |
| extern int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb, |
| struct path *lower_path, userid_t id); |
| +extern int sdcardfs_on_fscrypt_key_removed(struct notifier_block *nb, |
| + unsigned long action, void *data); |
| |
| /* file private data */ |
| struct sdcardfs_file_info { |
| @@ -231,6 +233,7 @@ struct sdcardfs_sb_info { |
| struct path obbpath; |
| void *pkgl_id; |
| struct list_head list; |
| + struct notifier_block fscrypt_nb; |
| }; |
| |
| /* |
| diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c |
| index 6b1d27e5067b..3d8762e012b8 100644 |
| --- a/fs/sdcardfs/super.c |
| +++ b/fs/sdcardfs/super.c |
| @@ -282,6 +282,23 @@ static int sdcardfs_show_options(struct vfsmount *mnt, struct seq_file *m, |
| return 0; |
| }; |
| |
| +int sdcardfs_on_fscrypt_key_removed(struct notifier_block *nb, |
| + unsigned long action, void *data) |
| +{ |
| + struct sdcardfs_sb_info *sbi = container_of(nb, struct sdcardfs_sb_info, |
| + fscrypt_nb); |
| + |
| + /* |
| + * Evict any unused sdcardfs dentries (and hence any unused sdcardfs |
| + * inodes, since sdcardfs doesn't cache unpinned inodes by themselves) |
| + * so that the lower filesystem's encrypted inodes can be evicted. |
| + * This is needed to make the FS_IOC_REMOVE_ENCRYPTION_KEY ioctl |
| + * properly "lock" the files underneath the sdcardfs mount. |
| + */ |
| + shrink_dcache_sb(sbi->sb); |
| + return NOTIFY_OK; |
| +} |
| + |
| const struct super_operations sdcardfs_sops = { |
| .put_super = sdcardfs_put_super, |
| .statfs = sdcardfs_statfs, |