@@ -53,14 +53,15 @@ struct fscrypt_context_v2 {
};
/*
- * fscrypt_context - the encryption context of an inode
+ * fscrypt_context - the encryption context of an object
*
* This is the on-disk equivalent of an fscrypt_policy, stored alongside each
- * encrypted file usually in a hidden extended attribute. It contains the
- * fields from the fscrypt_policy, in order to identify the encryption algorithm
- * and key with which the file is encrypted. It also contains a nonce that was
- * randomly generated by fscrypt itself; this is used as KDF input or as a tweak
- * to cause different files to be encrypted differently.
+ * encrypted file usually in a hidden extended attribute, or along with an extent.
+ * It contains the fields from the fscrypt_policy, in order to identify the
+ * encryption algorithm and key with which the file or extent is encrypted. It
+ * also contains a nonce that was randomly generated by fscrypt itself; this is
+ * used as KDF input or as a tweak to cause different files to be encrypted
+ * differently.
*/
union fscrypt_context {
u8 version;
@@ -189,11 +190,19 @@ struct fscrypt_prepared_key {
};
/*
- * fscrypt_info - the "encryption key" for an inode
+ * fscrypt_info - the "encryption key" for an object (inode or extent)
*
- * When an encrypted file's key is made available, an instance of this struct is
- * allocated and stored in ->i_crypt_info. Once created, it remains until the
- * inode is evicted.
+ * For filesystems using inode-based encryption, or non-regular files for
+ * filesystems with extent-based encryption: when an encrypted file's key is
+ * made available, an instance of this struct is allocated and stored in
+ * ->i_crypt_info. Once created, it remains until the inode is evicted.
+ *
+ * For filesystems using extent-based encryption, for regular files: when
+ * a file is opened, a pointer to the parent directory's fscrypt_info is stored
+ * in the inode's ->i_crypt_info. When an extent's key is made available, an
+ * instance of this struct is allocated and should be stored with the extent.
+ * It is freed when the filesystem decides to drop the extent, or when the key
+ * needs to be removed.
*/
struct fscrypt_info {
@@ -205,33 +214,33 @@ struct fscrypt_info {
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
/*
- * True if this inode will use inline encryption (blk-crypto) instead of
+ * True if this info will use inline encryption (blk-crypto) instead of
* the traditional filesystem-layer encryption.
*/
bool ci_inlinecrypt;
#endif
/*
- * Encryption mode used for this inode. It corresponds to either the
+ * Encryption mode for this info. It corresponds to either the
* contents or filenames encryption mode, depending on the inode type.
*/
struct fscrypt_mode *ci_mode;
- /* Back-pointer to the inode */
+ /* Back-pointer to the inode, for infos owned by a specific inode */
struct inode *ci_inode;
/* The superblock of the filesystem to which this fscrypt_info pertains */
struct super_block *ci_sb;
/*
- * The master key with which this inode was unlocked (decrypted). This
+ * The master key with which this info was unlocked (decrypted). This
* will be NULL if the master key was found in a process-subscribed
* keyring rather than in the filesystem-level keyring.
*/
struct fscrypt_master_key *ci_master_key;
/*
- * Link in list of inodes that were unlocked with the master key.
+ * Link in list of infos that were unlocked with the master key.
* Only used when ->ci_master_key is set.
*/
struct list_head ci_master_key_link;
@@ -243,20 +252,20 @@ struct fscrypt_info {
struct fscrypt_direct_key *ci_direct_key;
/*
- * This inode's hash key for filenames. This is a 128-bit SipHash-2-4
+ * This infos' hash key for filenames. This is a 128-bit SipHash-2-4
* key. This is only set for directories that use a keyed dirhash over
* the plaintext filenames -- currently just casefolded directories.
*/
siphash_key_t ci_dirhash_key;
bool ci_dirhash_key_initialized;
- /* The encryption policy used by this inode */
+ /* The encryption policy used by this info */
union fscrypt_policy ci_policy;
- /* This inode's nonce, copied from the fscrypt_context */
+ /* This info's nonce, copied from the fscrypt_context */
u8 ci_nonce[FSCRYPT_FILE_NONCE_SIZE];
- /* Hashed inode number. Only set for IV_INO_LBLK_32 */
+ /* Hashed object number. Only set for IV_INO_LBLK_32 */
u32 ci_hashed_ino;
};
@@ -271,7 +280,7 @@ typedef enum {
*
* @param inode the inode in question
*
- * Return: true if the inode uses per-extent encryption infos, false otherwise
+ * Return: true if the inode uses per-extent fscrypt_infos, false otherwise
*/
static inline bool fscrypt_uses_extent_encryption(const struct inode *inode)
{
@@ -350,10 +359,10 @@ fscrypt_msg(const struct inode *inode, const char *level, const char *fmt, ...);
union fscrypt_iv {
struct {
- /* logical block number within the file */
+ /* logical block number within the owning object */
__le64 lblk_num;
- /* per-file nonce; only set in DIRECT_KEY mode */
+ /* per-object nonce; only set in DIRECT_KEY mode */
u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
};
u8 raw[FSCRYPT_MAX_IV_SIZE];
@@ -684,9 +693,9 @@ int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported);
/**
* fscrypt_require_key() - require an inode's encryption key
- * @inode: the inode we need the key for
*
- * If the inode is encrypted, set up its encryption key if not already done.
+ * @inode: the inode we need the key for
+ * * If the inode is encrypted, set up its encryption key if not already done.
* Then require that the key be present and return -ENOKEY otherwise.
*
* No locks are needed, and the key will live as long as the struct inode --- so
@@ -344,8 +344,9 @@ EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh);
* fscrypt_set_bio_crypt_ctx() must have already been called on the bio.
*
* This function isn't required in cases where crypto-mergeability is ensured in
- * another way, such as I/O targeting only a single file (and thus a single key)
- * combined with fscrypt_limit_io_blocks() to ensure DUN contiguity.
+ * another way, such as I/O targeting only a single file combined with
+ * fscrypt_limit_io_blocks() to ensure DUN contiguity (which also ensures,
+ * for extent-based encryption, that the I/O doesn't span extents).
*
* Return: true iff the I/O is mergeable
*/
@@ -458,7 +459,9 @@ EXPORT_SYMBOL_GPL(fscrypt_dio_supported);
* DUN to wrap around within logically contiguous blocks, and that wraparound
* will occur. If this happens, a value less than @nr_blocks will be returned
* so that the wraparound doesn't occur in the middle of a bio, which would
- * cause encryption/decryption to produce wrong results.
+ * cause encryption/decryption to produce wrong results. Similarly, the
+ * filesystem could be using extent-based encryption, which will return a value
+ * less than @nr_blocks if needed to prevent spanning multiple extents.
*
* Return: the actual number of blocks that can be submitted
*/
@@ -876,7 +876,7 @@ static void shrink_dcache_inode(struct inode *inode)
d_prune_aliases(inode);
}
-static void evict_dentries_for_decrypted_inodes(struct fscrypt_master_key *mk)
+static void evict_dentries_for_decrypted_objects(struct fscrypt_master_key *mk)
{
struct fscrypt_info *ci;
struct inode *inode;
@@ -970,12 +970,14 @@ static int try_to_lock_encrypted_files(struct super_block *sb,
* Inodes are pinned by their dentries, so we have to evict their
* dentries. shrink_dcache_sb() would suffice, but would be overkill
* and inappropriate for use by unprivileged users. So instead go
- * through the inodes' alias lists and try to evict each dentry.
+ * through the inodes' alias lists and try to evict each dentry. Also,
+ * for extent-based encryption, notify the filesystem that it must free
+ * all the infos for extents using this key.
*/
- evict_dentries_for_decrypted_inodes(mk);
+ evict_dentries_for_decrypted_objects(mk);
/*
- * evict_dentries_for_decrypted_inodes() already iput() each inode in
+ * evict_dentries_for_decrypted_objects() already iput() each inode in
* the list; any inodes for which that dropped the last reference will
* have been evicted due to fscrypt_drop_inode() detecting the key
* removal and telling the VFS to evict the inode. So to finish, we
@@ -995,14 +997,14 @@ static int try_to_lock_encrypted_files(struct super_block *sb,
* key itself.
*
* To "remove the key itself", first we wipe the actual master key secret, so
- * that no more inodes can be unlocked with it. Then we try to evict all cached
- * inodes that had been unlocked with the key.
+ * that nothing else can be unlocked with it. Then we try to evict all cached
+ * inodes and extents that had been unlocked with the key.
*
- * If all inodes were evicted, then we unlink the fscrypt_master_key from the
- * keyring. Otherwise it remains in the keyring in the "incompletely removed"
- * state (without the actual secret key) where it tracks the list of remaining
- * inodes. Userspace can execute the ioctl again later to retry eviction, or
- * alternatively can re-add the secret key again.
+ * If all were evicted, then we unlink the fscrypt_master_key from the keyring.
+ * Otherwise it remains in the keyring in the "incompletely removed" state
+ * (without the actual secret key) where it tracks the list of remaining inodes
+ * and extents. Userspace can execute the ioctl again later to retry eviction,
+ * or alternatively can re-add the secret key again.
*
* For more details, see the "Removing keys" section of
* Documentation/filesystems/fscrypt.rst.
@@ -334,9 +334,9 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci,
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
/*
* IV_INO_LBLK_64: encryption keys are derived from (master_key,
- * mode_num, filesystem_uuid), and inode number is included in
- * the IVs. This format is optimized for use with inline
- * encryption hardware compliant with the UFS standard.
+ * mode_num, filesystem_uuid), and inode/extent number is
+ * included in the IVs. This format is optimized for use with
+ * inline encryption hardware compliant with the UFS standard.
*/
err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_64_keys,
HKDF_CONTEXT_IV_INO_LBLK_64_KEY,
There are a bunch of comments that need updating to refer to any sort of owning object, be it inode or extent, and they don't really fit anywhere else. So do it. Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me> --- fs/crypto/fscrypt_private.h | 57 +++++++++++++++++++++---------------- fs/crypto/inline_crypt.c | 9 ++++-- fs/crypto/keyring.c | 24 +++++++++------- fs/crypto/keysetup.c | 6 ++-- 4 files changed, 55 insertions(+), 41 deletions(-)