From 651f77d3386a86e55a1279b1175cde34aa56433e Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 9 Oct 2019 14:35:49 -0700 Subject: [PATCH] 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 --- 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 d890c5711907..19312ee881cc 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -19,6 +19,7 @@ */ #include "sdcardfs.h" +#include #include #include #include @@ -374,6 +375,9 @@ static int sdcardfs_read_super(struct vfsmount *mnt, struct super_block *sb, 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 (!silent) pr_info("sdcardfs: mounted on top of %s type %s\n", dev_name, lower_sb->s_type->name); @@ -444,6 +448,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 9ccf62cc8d92..401445e9121d 100644 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -151,6 +151,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 { @@ -224,6 +226,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 1240ef2f9d74..b2ba09a6ab94 100644 --- a/fs/sdcardfs/super.c +++ b/fs/sdcardfs/super.c @@ -319,6 +319,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,