• Eric Biggers's avatar
    fscrypt: don't evict dirty inodes after removing key · 2b4eae95
    Eric Biggers authored
    After FS_IOC_REMOVE_ENCRYPTION_KEY removes a key, it syncs the
    filesystem and tries to get and put all inodes that were unlocked by the
    key so that unused inodes get evicted via fscrypt_drop_inode().
    Normally, the inodes are all clean due to the sync.
    
    However, after the filesystem is sync'ed, userspace can modify and close
    one of the files.  (Userspace is *supposed* to close the files before
    removing the key.  But it doesn't always happen, and the kernel can't
    assume it.)  This causes the inode to be dirtied and have i_count == 0.
    Then, fscrypt_drop_inode() failed to consider this case and indicated
    that the inode can be dropped, causing the write to be lost.
    
    On f2fs, other problems such as a filesystem freeze could occur due to
    the inode being freed while still on f2fs's dirty inode list.
    
    Fix this bug by making fscrypt_drop_inode() only drop clean inodes.
    
    I've written an xfstest which detects this bug on ext4, f2fs, and ubifs.
    
    Fixes: b1c0ec35 ("fscrypt: add FS_IOC_REMOVE_ENCRYPTION_KEY ioctl")
    Cc: <stable@vger.kernel.org> # v5.4+
    Link: https://lore.kernel.org/r/20200305084138.653498-1-ebiggers@kernel.orgSigned-off-by: default avatarEric Biggers <ebiggers@google.com>
    2b4eae95
keysetup.c 15.8 KB