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 #include +#include #include #include #include @@ -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,