OpenCloudOS-Kernel/fs/crypto
Eric Biggers a992b20cd4 fscrypt: add fscrypt_prepare_new_inode() and fscrypt_set_context()
fscrypt_get_encryption_info() is intended to be GFP_NOFS-safe.  But
actually it isn't, since it uses functions like crypto_alloc_skcipher()
which aren't GFP_NOFS-safe, even when called under memalloc_nofs_save().
Therefore it can deadlock when called from a context that needs
GFP_NOFS, e.g. during an ext4 transaction or between f2fs_lock_op() and
f2fs_unlock_op().  This happens when creating a new encrypted file.

We can't fix this by just not setting up the key for new inodes right
away, since new symlinks need their key to encrypt the symlink target.

So we need to set up the new inode's key before starting the
transaction.  But just calling fscrypt_get_encryption_info() earlier
doesn't work, since it assumes the encryption context is already set,
and the encryption context can't be set until the transaction.

The recently proposed fscrypt support for the ceph filesystem
(https://lkml.kernel.org/linux-fscrypt/20200821182813.52570-1-jlayton@kernel.org/T/#u)
will have this same ordering problem too, since ceph will need to
encrypt new symlinks before setting their encryption context.

Finally, f2fs can deadlock when the filesystem is mounted with
'-o test_dummy_encryption' and a new file is created in an existing
unencrypted directory.  Similarly, this is caused by holding too many
locks when calling fscrypt_get_encryption_info().

To solve all these problems, add new helper functions:

- fscrypt_prepare_new_inode() sets up a new inode's encryption key
  (fscrypt_info), using the parent directory's encryption policy and a
  new random nonce.  It neither reads nor writes the encryption context.

- fscrypt_set_context() persists the encryption context of a new inode,
  using the information from the fscrypt_info already in memory.  This
  replaces fscrypt_inherit_context().

Temporarily keep fscrypt_inherit_context() around until all filesystems
have been converted to use fscrypt_set_context().

Acked-by: Jeff Layton <jlayton@kernel.org>
Link: https://lore.kernel.org/r/20200917041136.178600-2-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>
2020-09-22 06:48:29 -07:00
..
Kconfig fscrypt: switch fscrypt_do_sha256() to use the SHA-256 library 2020-07-21 16:02:13 -07:00
Makefile fscrypt: add inline encryption support 2020-07-08 10:29:30 -07:00
bio.c fscrypt: add inline encryption support 2020-07-08 10:29:30 -07:00
crypto.c fscrypt: rename FS_KEY_DERIVATION_NONCE_SIZE 2020-07-20 17:26:33 -07:00
fname.c fscrypt: drop unused inode argument from fscrypt_fname_alloc_buffer 2020-09-07 15:27:42 -07:00
fscrypt_private.h fscrypt: add fscrypt_prepare_new_inode() and fscrypt_set_context() 2020-09-22 06:48:29 -07:00
hkdf.c fscrypt: use crypto_shash_tfm_digest() 2020-05-08 15:32:14 +10:00
hooks.c fscrypt: drop unused inode argument from fscrypt_fname_alloc_buffer 2020-09-07 15:27:42 -07:00
inline_crypt.c mm, treewide: rename kzfree() to kfree_sensitive() 2020-08-07 11:33:22 -07:00
keyring.c mm, treewide: rename kzfree() to kfree_sensitive() 2020-08-07 11:33:22 -07:00
keysetup.c fscrypt: add fscrypt_prepare_new_inode() and fscrypt_set_context() 2020-09-22 06:48:29 -07:00
keysetup_v1.c mm, treewide: rename kzfree() to kfree_sensitive() 2020-08-07 11:33:22 -07:00
policy.c fscrypt: add fscrypt_prepare_new_inode() and fscrypt_set_context() 2020-09-22 06:48:29 -07:00