]> git.baikalelectronics.ru Git - kernel.git/commit
fscrypt: don't evict dirty inodes after removing key
authorEric Biggers <ebiggers@google.com>
Thu, 5 Mar 2020 08:41:38 +0000 (00:41 -0800)
committerEric Biggers <ebiggers@google.com>
Sun, 8 Mar 2020 02:43:07 +0000 (18:43 -0800)
commitd780803507f78f35881630bafd19f87e5f8202d0
tree4c892e145402b8da6d2de8a5f8552dde1c91577f
parent5ffd64ecc0987e6f01533e7cc8fa89b7b34f793f
fscrypt: don't evict dirty inodes after removing key

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: ffde2a5e3c41 ("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.org
Signed-off-by: Eric Biggers <ebiggers@google.com>
fs/crypto/keysetup.c