• Eric Biggers's avatar
    fscrypt: add fscrypt_prepare_new_inode() and fscrypt_set_context() · a992b20c
    Eric Biggers authored
    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: default avatarJeff Layton <jlayton@kernel.org>
    Link: https://lore.kernel.org/r/20200917041136.178600-2-ebiggers@kernel.orgSigned-off-by: default avatarEric Biggers <ebiggers@google.com>
    a992b20c
policy.c 25 KB