From patchwork Fri Dec 1 22:10:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476489 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="Fr5k1ZuA" Received: from mail-yw1-x112a.google.com (mail-yw1-x112a.google.com [IPv6:2607:f8b0:4864:20::112a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0F313D63 for ; Fri, 1 Dec 2023 14:12:00 -0800 (PST) Received: by mail-yw1-x112a.google.com with SMTP id 00721157ae682-5d4f71f7e9fso10514587b3.0 for ; Fri, 01 Dec 2023 14:12:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468719; x=1702073519; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=ohptYzYgHlOumuqXZ0mAmMVKlzKLSW+TQdF6edwaJZU=; b=Fr5k1ZuAqESTCONSjsVERae+8KTWvY1B/QUYkt2ZggzTK8QgglJFRTJliZBCcOZNCj rBrJY3xHcKwcnAIvh7ys1CCJuZMzpTSH45pBwSNd4o6TplYnojD/2JMonw4fEN+ZNanF bz1EWuc2GznipJe3D4IWDzm3I9UrR818y9Z3a++H0QJZ4xSYJYZfzPkVREBCGF+w07ye 2tR1o0CRLsRaBqY9sCnxO/Vu1kPwQxf17do9qqhEMi2nE+zjn7pkNv8uFgKcOYsr0Ic1 rnXmOLztE7HMAyECUZaqYZKDeYvPtcRL1iuYCu1Bz1c6c18TTG8yoUrzpaJc0z3rGV6W tlnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468719; x=1702073519; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ohptYzYgHlOumuqXZ0mAmMVKlzKLSW+TQdF6edwaJZU=; b=WSXBz2HhNpSZ3MJfB6YYpcKT6lBIv4Q9VKLhAefIErVly6q2YZE6W+6xKxA/oMVfSl Up7eYwyplgiqxo9o+GrQyiVaPOIhvTvYf/wr4gbEcymt6hcAyP2opMCYxNbQbwt+WcXl Xjm+XVq1O5OTZxKRlv2UzvaQxWL/NQL61e0SdSns+iAsWzn6dK+0AJGPuaGce7Eja1cH EJKFAE39e3Q29M7N+YzYlcEizlsrcmvzuOTolqE11e4qk6bcWE7WlFlWuYnoANCsU6H1 m7mjk/LcMIgFQ6+NGVzM4ygRaf/K+Gu4b4kZ+A/ng2YT3lneQnsoiARnw8+iZDvcelX1 a2zg== X-Gm-Message-State: AOJu0Yx6eR9/Va7XolqoOTrG8qWpJ/Vp9FR7WABz+2MHva0bpaeSqaWd xKB+p1v+IA40QSfcbJ2tdIkndrST57DjL1XK7S4CXg== X-Google-Smtp-Source: AGHT+IH557m518u3E1N6COVxegrdWL0VhOBMCiONVniKH6nlej8tgN3H5VGUfENJ4eyTMWGrStjVWw== X-Received: by 2002:a81:794f:0:b0:5d2:1b58:174 with SMTP id u76-20020a81794f000000b005d21b580174mr356847ywc.25.1701468719151; Fri, 01 Dec 2023 14:11:59 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id o125-20020a817383000000b005d39a1ae8b3sm1157032ywc.1.2023.12.01.14.11.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:11:58 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 01/46] fs: move fscrypt keyring destruction to after ->put_super Date: Fri, 1 Dec 2023 17:10:58 -0500 Message-ID: <122a3db06dbf6ac1ece5660895a69039fe45f50d.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 btrfs has a variety of asynchronous things we do with inodes that can potentially last until ->put_super, when we shut everything down and clean up all of our async work. Due to this we need to move fscrypt_destroy_keyring() to after ->put_super, otherwise we get warnings about still having active references on the master key. Signed-off-by: Josef Bacik --- fs/super.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/super.c b/fs/super.c index 076392396e72..faf7d248145d 100644 --- a/fs/super.c +++ b/fs/super.c @@ -681,12 +681,6 @@ void generic_shutdown_super(struct super_block *sb) fsnotify_sb_delete(sb); security_sb_delete(sb); - /* - * Now that all potentially-encrypted inodes have been evicted, - * the fscrypt keyring can be destroyed. - */ - fscrypt_destroy_keyring(sb); - if (sb->s_dio_done_wq) { destroy_workqueue(sb->s_dio_done_wq); sb->s_dio_done_wq = NULL; @@ -695,6 +689,12 @@ void generic_shutdown_super(struct super_block *sb) if (sop->put_super) sop->put_super(sb); + /* + * Now that all potentially-encrypted inodes have been evicted, + * the fscrypt keyring can be destroyed. + */ + fscrypt_destroy_keyring(sb); + if (CHECK_DATA_CORRUPTION(!list_empty(&sb->s_inodes), "VFS: Busy inodes after unmount of %s (%s)", sb->s_id, sb->s_type->name)) { From patchwork Fri Dec 1 22:10:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476492 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="EMgJv7Rz" Received: from mail-yb1-xb42.google.com (mail-yb1-xb42.google.com [IPv6:2607:f8b0:4864:20::b42]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5F01510D0 for ; Fri, 1 Dec 2023 14:12:01 -0800 (PST) Received: by mail-yb1-xb42.google.com with SMTP id 3f1490d57ef6-db54611b920so979721276.3 for ; Fri, 01 Dec 2023 14:12:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468720; x=1702073520; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=Jr0WOCD8JTyY6NQSzSjvqDgXCX9+Pc+RemopiYnHZ9s=; b=EMgJv7RzWOkaW3V5gqpp7Av0u6QB5HG7wx8XrM+OXHRy1/gzLvkS40uFssA+pe5IkF 6spHRD63oz8EIe06sKF5Itw0fk6cpLGRXk4DwIvWxPWWoYJ8ubyVOgAfOV+s3eWPLcjm s1WRGUjgFWly54xpb3ereD0jb8BHTNcPqiTbCkCwT1kgCACSOJAlHpAPbzC7P0VqZS9z iYyZ01cuhJ8Zh7ydg6VAdU7XF+bmbwPVd1JUIccb6BRuS6hSQ6xtQEuR28Dk6oHEnDzw 15omEsVEDHqw/MLKbq42V+O/ccz56/lMrnia5zNbrmH996ncDz6qZza6eghgl3SoQc1R Y1rA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468720; x=1702073520; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Jr0WOCD8JTyY6NQSzSjvqDgXCX9+Pc+RemopiYnHZ9s=; b=lOPX4IrO/ZBtcuXTAxXseaggSmTixRlDNLTB6cXT4DfryQwqZ+A7XsGt54nKvSgzIu RJyYtrrbDK1tEMg1V+Cb+tzJPq87bs0jlu1TOuNcDhPz1bzIHGOnaCssrkIHTBspY9S6 NhxJI5LtWG7/EmVWZnBfdrm4PJWu3Po9zK6p+S/9mi0BGXCW3QVr5iv6r2SzLD0d3nfv 9KYXMYzL10Ow2K5aO2uMj43EDcCoH8exx94om4GcadVLImnefDNaqObyyHA7dhtAnTvB Pa78ci7z5R5vkn0tDpVm+i2kREcJKmGxVqRT2a7+EofeXUu1enZ5KFAmr1xNEctsbSGg 9bow== X-Gm-Message-State: AOJu0YyosFLioqHjOZe/te6lbPI6B2m+/CeT06zQwJS9xIfC7+PsKlbD bpq1lYq390uVeoW3wxXhMVtdVi1UG9+xOT0OCbklJ5Wy X-Google-Smtp-Source: AGHT+IEhrHy7Tm5uPu9BILnThmfOm6bm7iEQn0TQEskZgEeU7s3T8VFTvmzODLDzyQYWIWVxEUCcVQ== X-Received: by 2002:a25:df4f:0:b0:db7:dacf:2f2b with SMTP id w76-20020a25df4f000000b00db7dacf2f2bmr166641ybg.114.1701468720183; Fri, 01 Dec 2023 14:12:00 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id h9-20020a259749000000b00d677aec54ffsm607827ybo.60.2023.12.01.14.11.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:11:59 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 02/46] fscrypt: add per-extent encryption support Date: Fri, 1 Dec 2023 17:10:59 -0500 Message-ID: <5e91532d4f6ddb10af8aac7f306186d6f1b9e917.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This adds the code necessary for per-extent encryption. We will store a nonce for every extent we create, and then use the inode's policy and the extents nonce to derive a per-extent key. This is meant to be flexible, if we choose to expand the on-disk extent information in the future we have a version number we can use to change what exists on disk. The file system indicates it wants to use per-extent encryption by setting s_cop->set_extent_context. This also requires the use of inline block encryption. The support is relatively straightforward, the only "extra" bit is we're deriving a per-extent key to use for the encryption, the inode still controls the policy and access to the master key. Since extent based encryption uses a lot of keys, we're requiring the use of inline block crypto if you use extent-based encryption. This enables us to take advantage of the built in pooling and reclamation of the crypto structures that underpin all of the encryption. The different encryption related options for fscrypt are too numerous to support for extent based encryption. Support for a few of these options could possibly be added, but since they're niche options simply reject them for file systems using extent based encryption. Signed-off-by: Josef Bacik --- fs/crypto/crypto.c | 10 ++- fs/crypto/fscrypt_private.h | 44 ++++++++++ fs/crypto/inline_crypt.c | 84 +++++++++++++++++++ fs/crypto/keysetup.c | 155 ++++++++++++++++++++++++++++++++++++ fs/crypto/policy.c | 59 ++++++++++++++ include/linux/fscrypt.h | 71 +++++++++++++++++ 6 files changed, 422 insertions(+), 1 deletion(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 328470d40dec..18bd96b9db4e 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -40,6 +40,7 @@ static struct workqueue_struct *fscrypt_read_workqueue; static DEFINE_MUTEX(fscrypt_init_mutex); struct kmem_cache *fscrypt_inode_info_cachep; +struct kmem_cache *fscrypt_extent_info_cachep; void fscrypt_enqueue_decrypt_work(struct work_struct *work) { @@ -414,12 +415,19 @@ static int __init fscrypt_init(void) if (!fscrypt_inode_info_cachep) goto fail_free_queue; + fscrypt_extent_info_cachep = KMEM_CACHE(fscrypt_extent_info, + SLAB_RECLAIM_ACCOUNT); + if (!fscrypt_extent_info_cachep) + goto fail_free_inode_info; + err = fscrypt_init_keyring(); if (err) - goto fail_free_inode_info; + goto fail_free_extent_info; return 0; +fail_free_extent_info: + kmem_cache_destroy(fscrypt_extent_info_cachep); fail_free_inode_info: kmem_cache_destroy(fscrypt_inode_info_cachep); fail_free_queue: diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 1892356cf924..03c006e5c47d 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -30,6 +30,8 @@ #define FSCRYPT_CONTEXT_V1 1 #define FSCRYPT_CONTEXT_V2 2 +#define FSCRYPT_EXTENT_CONTEXT_V1 1 + /* Keep this in sync with include/uapi/linux/fscrypt.h */ #define FSCRYPT_MODE_MAX FSCRYPT_MODE_AES_256_HCTR2 @@ -53,6 +55,28 @@ struct fscrypt_context_v2 { u8 nonce[FSCRYPT_FILE_NONCE_SIZE]; }; +/* + * fscrypt_extent_context - the encryption context of an extent + * + * This is the on-disk information stored for an extent. The policy and + * relevante information is stored in the inode, the per-extent information is + * simply the nonce that's used in as KDF input in conjunction with the inode + * context to derive a per-extent key for encryption. + * + * At this point the master_key_identifier exists only for possible future + * expansion. This will allow for an inode to have extents with multiple master + * keys, although sharing the same encryption mode. This would be for re-keying + * or for reflinking between two differently encrypted inodes. For now the + * master_key_descriptor must match the inode's, and we'll be using the inode's + * for all key derivation. + */ +struct fscrypt_extent_context { + u8 version; /* FSCRYPT_EXTENT_CONTEXT_V2 */ + u8 encryption_mode; + u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; + u8 nonce[FSCRYPT_FILE_NONCE_SIZE]; +}; + /* * fscrypt_context - the encryption context of an inode * @@ -288,6 +312,25 @@ struct fscrypt_inode_info { u32 ci_hashed_ino; }; +/* + * fscrypt_extent_info - the "encryption key" for an extent. + * + * This contains the dervied key for the given extent and the nonce for the + * extent. + */ +struct fscrypt_extent_info { + refcount_t refs; + + /* The derived key for this extent. */ + struct fscrypt_prepared_key prep_key; + + /* The super block that this extent belongs to. */ + struct super_block *sb; + + /* This is the extents nonce, loaded from the fscrypt_extent_context */ + u8 nonce[FSCRYPT_FILE_NONCE_SIZE]; +}; + typedef enum { FS_DECRYPT = 0, FS_ENCRYPT, @@ -295,6 +338,7 @@ typedef enum { /* crypto.c */ extern struct kmem_cache *fscrypt_inode_info_cachep; +extern struct kmem_cache *fscrypt_extent_info_cachep; int fscrypt_initialize(struct super_block *sb); int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci, fscrypt_direction_t rw, u64 index, diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c index b4002aea7cdb..4eeb75410ba8 100644 --- a/fs/crypto/inline_crypt.c +++ b/fs/crypto/inline_crypt.c @@ -279,6 +279,40 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, } EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx); +/** + * fscrypt_set_bio_crypt_ctx() - prepare a file contents bio for inline crypto + * @bio: a bio which will eventually be submitted to the file + * @inode: the file's inode + * @ei: the extent's crypto info + * @first_lblk: the first file logical block number in the I/O + * @gfp_mask: memory allocation flags - these must be a waiting mask so that + * bio_crypt_set_ctx can't fail. + * + * If the contents of the file should be encrypted (or decrypted) with inline + * encryption, then assign the appropriate encryption context to the bio. + * + * Normally the bio should be newly allocated (i.e. no pages added yet), as + * otherwise fscrypt_mergeable_bio() won't work as intended. + * + * The encryption context will be freed automatically when the bio is freed. + */ +void fscrypt_set_bio_crypt_ctx_from_extent(struct bio *bio, + const struct inode *inode, + const struct fscrypt_extent_info *ei, + u64 first_lblk, gfp_t gfp_mask) +{ + const struct fscrypt_inode_info *ci; + u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; + + if (!fscrypt_inode_uses_inline_crypto(inode)) + return; + ci = inode->i_crypt_info; + + fscrypt_generate_dun(ci, first_lblk, dun); + bio_crypt_set_ctx(bio, ei->prep_key.blk_key, dun, gfp_mask); +} +EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_from_extent); + /* Extract the inode and logical block number from a buffer_head. */ static bool bh_get_inode_and_lblk_num(const struct buffer_head *bh, const struct inode **inode_ret, @@ -370,6 +404,56 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode, } EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio); +/** + * fscrypt_mergeable_extent_bio() - test whether data can be added to a bio + * @bio: the bio being built up + * @inode: the inode for the next part of the I/O + * @ei: the fscrypt_extent_info for this extent + * @next_lblk: the next file logical block number in the I/O + * + * When building a bio which may contain data which should undergo inline + * encryption (or decryption) via fscrypt, filesystems should call this function + * to ensure that the resulting bio contains only contiguous data unit numbers. + * This will return false if the next part of the I/O cannot be merged with the + * bio because either the encryption key would be different or the encryption + * data unit numbers would be discontiguous. + * + * fscrypt_set_bio_crypt_ctx_from_extent() 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. + * + * Return: true iff the I/O is mergeable + */ +bool fscrypt_mergeable_extent_bio(struct bio *bio, const struct inode *inode, + const struct fscrypt_extent_info *ei, + u64 next_lblk) +{ + const struct bio_crypt_ctx *bc = bio->bi_crypt_context; + u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; + + if (!ei) + return true; + if (!!bc != fscrypt_inode_uses_inline_crypto(inode)) + return false; + if (!bc) + return true; + + /* + * Comparing the key pointers is good enough, as all I/O for each key + * uses the same pointer. I.e., there's currently no need to support + * merging requests where the keys are the same but the pointers differ. + */ + if (bc->bc_key != ei->prep_key.blk_key) + return false; + + fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun); + return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun); +} +EXPORT_SYMBOL_GPL(fscrypt_mergeable_extent_bio); + /** * fscrypt_mergeable_bio_bh() - test whether data can be added to a bio * @bio: the bio being built up diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index d71f7c799e79..c19bf6239dcd 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -812,3 +812,158 @@ int fscrypt_drop_inode(struct inode *inode) return !READ_ONCE(ci->ci_master_key->mk_present); } EXPORT_SYMBOL_GPL(fscrypt_drop_inode); + +static struct fscrypt_extent_info * +setup_extent_info(struct inode *inode, const u8 nonce[FSCRYPT_FILE_NONCE_SIZE]) +{ + struct fscrypt_extent_info *ei; + struct fscrypt_inode_info *ci; + struct fscrypt_master_key *mk; + u8 derived_key[FSCRYPT_MAX_KEY_SIZE]; + int err; + + ci = inode->i_crypt_info; + mk = ci->ci_master_key; + if (!mk) + return ERR_PTR(-ENOKEY); + + ei = kmem_cache_zalloc(fscrypt_extent_info_cachep, GFP_KERNEL); + if (!ei) + return ERR_PTR(-ENOMEM); + + refcount_set(&ei->refs, 1); + memcpy(ei->nonce, nonce, FSCRYPT_FILE_NONCE_SIZE); + ei->sb = inode->i_sb; + + down_read(&mk->mk_sem); + /* + * We specifically don't do is_master_key_secret_present() here because + * if the inode is open and has a reference on the master key then it + * should be available for us to use. + */ + + err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, + HKDF_CONTEXT_PER_FILE_ENC_KEY, ei->nonce, + FSCRYPT_FILE_NONCE_SIZE, derived_key, + ci->ci_mode->keysize); + if (err) + goto out_free; + + err = fscrypt_prepare_inline_crypt_key(&ei->prep_key, derived_key, ci); + memzero_explicit(derived_key, ci->ci_mode->keysize); + if (err) + goto out_free; + up_read(&mk->mk_sem); + return ei; +out_free: + up_read(&mk->mk_sem); + memzero_explicit(ei, sizeof(*ei)); + kmem_cache_free(fscrypt_extent_info_cachep, ei); + return ERR_PTR(err); +} + +/** + * fscrypt_prepare_new_extent() - prepare to create a new extent for a file + * @inode: the possibly-encrypted inode + * + * If the inode is encrypted, setup the fscrypt_extent_info for a new extent. + * This will include the nonce and the derived key necessary for the extent to + * be encrypted. This is only meant to be used with inline crypto. + * + * This doesn't persist the new extents encryption context, this is done later + * by calling fscrypt_set_extent_context(). + * + * Return: The newly allocated fscrypt_extent_info on success, -EOPNOTSUPP if + * we're not encrypted, or another -errno code + */ +struct fscrypt_extent_info *fscrypt_prepare_new_extent(struct inode *inode) +{ + u8 nonce[FSCRYPT_FILE_NONCE_SIZE]; + + if (!fscrypt_inode_uses_inline_crypto(inode)) + return ERR_PTR(-EOPNOTSUPP); + + get_random_bytes(nonce, FSCRYPT_FILE_NONCE_SIZE); + return setup_extent_info(inode, nonce); +} +EXPORT_SYMBOL_GPL(fscrypt_prepare_new_extent); + +/** + * fscrypt_load_extent_info() - create an fscrypt_extent_info from the context + * @inode: the inode + * @ctx: the context buffer + * @ctx_size: the size of the context buffer + * + * Create the file_extent_info and derive the key based on the + * fscrypt_extent_context buffer that is probided. + * + * Return: The newly allocated fscrypt_extent_info on success, -EOPNOTSUPP if + * we're not encrypted, or another -errno code + */ +struct fscrypt_extent_info *fscrypt_load_extent_info(struct inode *inode, + u8 *ctx, size_t ctx_size) +{ + struct fscrypt_extent_context extent_ctx; + const struct fscrypt_inode_info *ci = inode->i_crypt_info; + const struct fscrypt_policy_v2 *policy = &ci->ci_policy.v2; + + if (!fscrypt_inode_uses_inline_crypto(inode)) + return ERR_PTR(-EOPNOTSUPP); + if (ctx_size < sizeof(extent_ctx)) + return ERR_PTR(-EINVAL); + + memcpy(&extent_ctx, ctx, sizeof(extent_ctx)); + + /* + * For now we need to validate that the master key for the inode matches + * the extent. + */ + if (memcmp(extent_ctx.master_key_identifier, + policy->master_key_identifier, + sizeof(extent_ctx.master_key_identifier))) + return ERR_PTR(-EINVAL); + + return setup_extent_info(inode, extent_ctx.nonce); +} +EXPORT_SYMBOL(fscrypt_load_extent_info); + +/** + * fscrypt_put_extent_info() - free the extent_info fscrypt data + * @ei: the extent_info being evicted + * + * Drop a reference and possibly free the fscrypt_extent_info. + * + * Note this will unload the key from the block layer, which takes the crypto + * profile semaphore to unload the key. Make sure you're not dropping this in a + * context that can't sleep. + */ +void fscrypt_put_extent_info(struct fscrypt_extent_info *ei) +{ + if (!ei) + return; + + if (!refcount_dec_and_test(&ei->refs)) + return; + + fscrypt_destroy_prepared_key(ei->sb, &ei->prep_key); + memzero_explicit(ei, sizeof(*ei)); + kmem_cache_free(fscrypt_extent_info_cachep, ei); +} +EXPORT_SYMBOL_GPL(fscrypt_put_extent_info); + +/** + * fscrypt_get_extent_info() - get a ref on the fscrypt extent info + * @ei: the extent_info to get. + * + * Get a reference on the fscrypt_extent_info. + * + * Return: the ei with an extra ref, NULL if there was no ei passed in. + */ +struct fscrypt_extent_info *fscrypt_get_extent_info(struct fscrypt_extent_info *ei) +{ + if (!ei) + return NULL; + refcount_inc(&ei->refs); + return ei; +} +EXPORT_SYMBOL_GPL(fscrypt_get_extent_info); diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 701259991277..75a69f02f11d 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -209,6 +209,12 @@ static bool fscrypt_supported_v1_policy(const struct fscrypt_policy_v1 *policy, return false; } + if (inode->i_sb->s_cop->has_per_extent_encryption) { + fscrypt_warn(inode, + "v1 policies can't be used on file systems that use extent encryption"); + return false; + } + return true; } @@ -269,6 +275,12 @@ static bool fscrypt_supported_v2_policy(const struct fscrypt_policy_v2 *policy, } } + if ((inode->i_sb->s_cop->has_per_extent_encryption) && count) { + fscrypt_warn(inode, + "Encryption flags aren't supported on file systems that use extent encryption"); + return false; + } + if ((policy->flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) && !supported_direct_key_modes(inode, policy->contents_encryption_mode, policy->filenames_encryption_mode)) @@ -789,6 +801,53 @@ int fscrypt_set_context(struct inode *inode, void *fs_data) } EXPORT_SYMBOL_GPL(fscrypt_set_context); +/** + * fscrypt_set_extent_context() - Set the fscrypt extent context of a new extent + * @inode: the inode this extent belongs to + * @ei: the fscrypt_extent_info for the given extent + * @buf: the buffer to copy the fscrypt extent context into + * + * This should be called after fscrypt_prepare_new_extent(), using the + * fscrypt_extent_info that was created at that point. + * + * Return: the size of the fscrypt_extent_context, errno if the inode has the + * wrong policy version. + */ +ssize_t fscrypt_set_extent_context(struct inode *inode, + struct fscrypt_extent_info *ei, u8 *buf) +{ + struct fscrypt_extent_context *ctx = (struct fscrypt_extent_context *)buf; + const struct fscrypt_inode_info *ci = inode->i_crypt_info; + + if (ci->ci_policy.version != 2) + return -EINVAL; + + ctx->version = 1; + memcpy(ctx->master_key_identifier, + ci->ci_policy.v2.master_key_identifier, + sizeof(ctx->master_key_identifier)); + memcpy(ctx->nonce, ei->nonce, FSCRYPT_FILE_NONCE_SIZE); + return sizeof(struct fscrypt_extent_context); +} +EXPORT_SYMBOL_GPL(fscrypt_set_extent_context); + +/** + * fscrypt_extent_context_size() - Return the size of the on-disk extent context + * @inode: the inode this extent belongs to. + * + * Return the size of the extent context for this inode. Since there is only + * one extent context version currently this is just the size of the extent + * context if the inode is encrypted. + */ +size_t fscrypt_extent_context_size(struct inode *inode) +{ + if (!IS_ENCRYPTED(inode)) + return 0; + + return sizeof(struct fscrypt_extent_context); +} +EXPORT_SYMBOL_GPL(fscrypt_extent_context_size); + /** * fscrypt_parse_test_dummy_encryption() - parse the test_dummy_encryption mount option * @param: the mount option diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 12f9e455d569..ea8fdc6f3b83 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -32,6 +32,7 @@ union fscrypt_policy; struct fscrypt_inode_info; +struct fscrypt_extent_info; struct fs_parameter; struct seq_file; @@ -97,6 +98,14 @@ struct fscrypt_operations { */ unsigned int supports_subblock_data_units : 1; + /* + * If set then extent based encryption will be used for this file + * system, and fs/crypto/ will enforce limits on the policies that are + * allowed to be chosen. Currently this means only plain v2 policies + * are supported. + */ + unsigned int has_per_extent_encryption : 1; + /* * This field exists only for backwards compatibility reasons and should * only be set by the filesystems that are setting it already. It @@ -308,6 +317,11 @@ int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg); int fscrypt_has_permitted_context(struct inode *parent, struct inode *child); int fscrypt_context_for_new_inode(void *ctx, struct inode *inode); int fscrypt_set_context(struct inode *inode, void *fs_data); +ssize_t fscrypt_set_extent_context(struct inode *inode, + struct fscrypt_extent_info *ei, u8 *buf); +struct fscrypt_extent_info *fscrypt_load_extent_info(struct inode *inode, + u8 *ctx, size_t ctx_size); +size_t fscrypt_extent_context_size(struct inode *inode); struct fscrypt_dummy_policy { const union fscrypt_policy *policy; @@ -344,6 +358,9 @@ int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode, void fscrypt_put_encryption_info(struct inode *inode); void fscrypt_free_inode(struct inode *inode); int fscrypt_drop_inode(struct inode *inode); +struct fscrypt_extent_info *fscrypt_prepare_new_extent(struct inode *inode); +void fscrypt_put_extent_info(struct fscrypt_extent_info *ei); +struct fscrypt_extent_info *fscrypt_get_extent_info(struct fscrypt_extent_info *ei); /* fname.c */ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, @@ -555,6 +572,24 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy) { } +static inline ssize_t +fscrypt_set_extent_context(struct inode *inode, struct fscrypt_extent_info *ei, + u8 *buf) +{ + return -EOPNOTSUPP; +} + +static inline struct fscrypt_extent_info * +fscrypt_load_extent_info(struct inode *inode, u8 *ctx, size_t ctx_size) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline size_t fscrypt_extent_context_size(struct inode *inode) +{ + return 0; +} + /* keyring.c */ static inline void fscrypt_destroy_keyring(struct super_block *sb) { @@ -607,6 +642,20 @@ static inline int fscrypt_drop_inode(struct inode *inode) return 0; } +static inline struct fscrypt_extent_info * +fscrypt_prepare_new_extent(struct inode *inode) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline void fscrypt_put_extent_info(struct fscrypt_extent_info *ei) { } + +static inline struct fscrypt_extent_info * +fscrypt_get_extent_info(struct fscrypt_extent_info *ei) +{ + return ei; +} + /* fname.c */ static inline int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, @@ -788,6 +837,11 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, u64 first_lblk, gfp_t gfp_mask); +void fscrypt_set_bio_crypt_ctx_from_extent(struct bio *bio, + const struct inode *inode, + const struct fscrypt_extent_info *ei, + u64 first_lblk, gfp_t gfp_mask); + void fscrypt_set_bio_crypt_ctx_bh(struct bio *bio, const struct buffer_head *first_bh, gfp_t gfp_mask); @@ -798,6 +852,10 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode, bool fscrypt_mergeable_bio_bh(struct bio *bio, const struct buffer_head *next_bh); +bool fscrypt_mergeable_extent_bio(struct bio *bio, const struct inode *inode, + const struct fscrypt_extent_info *ei, + u64 next_lblk); + bool fscrypt_dio_supported(struct inode *inode); u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks); @@ -813,6 +871,11 @@ static inline void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, u64 first_lblk, gfp_t gfp_mask) { } +static inline void fscrypt_set_bio_crypt_ctx_from_extent(struct bio *bio, + const struct inode *inode, + const struct fscrypt_extent_info *ei, + u64 first_lblk, gfp_t gfp_mask) { } + static inline void fscrypt_set_bio_crypt_ctx_bh( struct bio *bio, const struct buffer_head *first_bh, @@ -825,6 +888,14 @@ static inline bool fscrypt_mergeable_bio(struct bio *bio, return true; } +static inline bool fscrypt_mergeable_extent_bio(struct bio *bio, + const struct inode *inode, + const struct fscrypt_extent_info *ei, + u64 next_lblk) +{ + return true; +} + static inline bool fscrypt_mergeable_bio_bh(struct bio *bio, const struct buffer_head *next_bh) { From patchwork Fri Dec 1 22:11:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476491 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="1Fbb68g2" Received: from mail-yb1-xb30.google.com (mail-yb1-xb30.google.com [IPv6:2607:f8b0:4864:20::b30]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 28AA010EA for ; Fri, 1 Dec 2023 14:12:02 -0800 (PST) Received: by mail-yb1-xb30.google.com with SMTP id 3f1490d57ef6-da37522a363so995983276.0 for ; Fri, 01 Dec 2023 14:12:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468721; x=1702073521; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=xwoVDhRbNBRkYLjWJpaZS8VmmPHrTCz3YWuznD6d90A=; b=1Fbb68g2rALCA+u+VaOrTPdT6I94aoM4QO3mdhydrgNMXOz3smH00mdojY9HRp20e6 Youf7z46eBOvoTQ6UoHbQPc0/0TG60FqtLL6/qguBVHLiR/ir/QHgUnVSiKoB/nVpzFE rFCjBmd6UsixIcbjwAT06h6VTZP4/YMufvQMqp6JoofhN4DPxHhQc3MK771lhhIppcmr UE40K4DQ6oh4p/g1mzmGNcCarHR+FJzcft4zEJoZZ+x/xaq/bU/bFNaAbgnX/Xm2//qb pIj9k+yRdaQhNKsjDtYEMudMuy0jl0/WY1TkwhwhK6VxPZAr5y75BJpV0gFefgmEKdgT Fsmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468721; x=1702073521; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=xwoVDhRbNBRkYLjWJpaZS8VmmPHrTCz3YWuznD6d90A=; b=F3UJ2vOLHPzr1GzxvqLN2e0AHI3K3+e7U2mFqOFkFzKMH0vu2imJrc1bpnyaeSNwhQ A5cT8cYiDWcuBuORuCV6KKXVfjNcwcUwaxkj7M310DViXV95wkIkvcc88/kKOE4BQCjH hLuXugbNqHcE7y/VAuUI4wa1UXpMpPRoaXnf3YfpA1p9keioeeU32KtpbYsUnTdDqAcU dm1KttMaFidMAAg1wT6qucEUzi8E1+J7vnhG7ABPah0O3cXrOkySuyGVom5yqCziBpgg ySf5r9YOEqW20wPz9PY9lyK1dOs2kPDVQVwcyUQzDvvM9IG4+W9UU/ZCGVFRpOojlHQK yTqA== X-Gm-Message-State: AOJu0YxH6GGS3BuxA28Zn/f2I9SC6BjJqvY7UNMPv+oCT+sCyISFClDo NE+gjUGeRBSty26AzUyYxwkSJQ+aDu7TDwnYbHYkZQ== X-Google-Smtp-Source: AGHT+IEJ3EQBPtAFn6BnCE8kiC40QB1fpP9rsoaSP46Wc/lWnA6QfnAPzO35R0ZT819y9uyx1NP7jw== X-Received: by 2002:a25:44:0:b0:db5:4764:acad with SMTP id 65-20020a250044000000b00db54764acadmr316235yba.9.1701468721217; Fri, 01 Dec 2023 14:12:01 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id u5-20020a25f805000000b00db4d3bf8df5sm633614ybd.27.2023.12.01.14.12.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:00 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 03/46] fscrypt: add a fscrypt_inode_open helper Date: Fri, 1 Dec 2023 17:11:00 -0500 Message-ID: <32beea11211858a998ba2de88d01471c31004f2d.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We have fscrypt_file_open() which is meant to be called on files being opened so that their key is loaded when we start reading data from them. However for btrfs send we are opening the inode directly without a filp, so we need a different helper to make sure we can load the fscrypt context for the inode before reading its contents. We need a different helper as opposed to simply using fscrypt_has_permitted_context() directly because of '-o test_dummy_encryption', which allows for encrypted files to be created with !IS_ENCRYPTED set on the directory (the root directory in this case). fscrypt_file_open() already does the appropriate check where it simply doesn't call fscrypt_has_permitted_context() if the parent directory isn't marked with IS_ENCRYPTED in order to facilitate this invariant when using '-o test_dummy_encryption'. Signed-off-by: Josef Bacik --- fs/crypto/hooks.c | 42 +++++++++++++++++++++++++++++++++++++++++ include/linux/fscrypt.h | 8 ++++++++ 2 files changed, 50 insertions(+) diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c index 52504dd478d3..a391a987c58f 100644 --- a/fs/crypto/hooks.c +++ b/fs/crypto/hooks.c @@ -49,6 +49,48 @@ int fscrypt_file_open(struct inode *inode, struct file *filp) } EXPORT_SYMBOL_GPL(fscrypt_file_open); +/** + * fscrypt_inode_open() - prepare to open a possibly-encrypted regular file + * @dir: the directory that contains this inode + * @inode: the inode being opened + * + * Currently, an encrypted regular file can only be opened if its encryption key + * is available; access to the raw encrypted contents is not supported. + * Therefore, we first set up the inode's encryption key (if not already done) + * and return an error if it's unavailable. + * + * We also verify that if the parent directory is encrypted, then the inode + * being opened uses the same encryption policy. This is needed as part of the + * enforcement that all files in an encrypted directory tree use the same + * encryption policy, as a protection against certain types of offline attacks. + * Note that this check is needed even when opening an *unencrypted* file, since + * it's forbidden to have an unencrypted file in an encrypted directory. + * + * File systems should be using fscrypt_file_open in their open callback. This + * is for file systems that may need to open inodes outside of the normal file + * open path, btrfs send for example. + * + * Return: 0 on success, -ENOKEY if the key is missing, or another -errno code + */ +int fscrypt_inode_open(struct inode *dir, struct inode *inode) +{ + int err; + + err = fscrypt_require_key(inode); + if (err) + return err; + + if (IS_ENCRYPTED(dir) && + !fscrypt_has_permitted_context(dir, inode)) { + fscrypt_warn(inode, + "Inconsistent encryption context (parent directory: %lu)", + dir->i_ino); + err = -EPERM; + } + return err; +} +EXPORT_SYMBOL_GPL(fscrypt_inode_open); + int __fscrypt_prepare_link(struct inode *inode, struct inode *dir, struct dentry *dentry) { diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index ea8fdc6f3b83..756f23fc3e83 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -394,6 +394,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, /* hooks.c */ int fscrypt_file_open(struct inode *inode, struct file *filp); +int fscrypt_inode_open(struct inode *dir, struct inode *inode); int __fscrypt_prepare_link(struct inode *inode, struct inode *dir, struct dentry *dentry); int __fscrypt_prepare_rename(struct inode *old_dir, struct dentry *old_dentry, @@ -738,6 +739,13 @@ static inline int fscrypt_file_open(struct inode *inode, struct file *filp) return 0; } +static inline int fscrypt_inode_open(struct inode *dir, struct inode *inode) +{ + if (IS_ENCRYPTED(inode)) + return -EOPNOTSUPP; + return 0; +} + static inline int __fscrypt_prepare_link(struct inode *inode, struct inode *dir, struct dentry *dentry) { From patchwork Fri Dec 1 22:11:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476490 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="tWUm+ixJ" Received: from mail-yw1-x1132.google.com (mail-yw1-x1132.google.com [IPv6:2607:f8b0:4864:20::1132]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2327F128 for ; Fri, 1 Dec 2023 14:12:03 -0800 (PST) Received: by mail-yw1-x1132.google.com with SMTP id 00721157ae682-5cfa3a1fb58so29162477b3.2 for ; Fri, 01 Dec 2023 14:12:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468722; x=1702073522; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=z9dqjoMSn+7T+gtB15gD5H7naTL8GFoazbK/o6+nI2Y=; b=tWUm+ixJzR31GeEU6o3MB6vjOMV5yqYTM5BwV2mExjnjC5LufAugRG31qEFuYh6sWB nP6X2m1/LWKcpN3mPoen8dZRYSBjMPdmEhBUQ9NK6p5o7PGogvbjx0dseO7ikkpteoh+ h6vcqeC21ZaAsmvdd7gzDLmwAJOevGlac7kDazpQm/roemyOWsoIZTuv/04BtN469ePW cFp4yx0hlTLm1Uk57Cb9yCnFvAZ6vnNZp2CxZ5T+Y80eHqO29Yuz6CTsU8aY7m2mmtOX +a6t4ZaJFnuIKm9bGQZ3Vf4XxzzK/pXz+f3LncEG+CInoAsToeR7lbRgSOZwSIaul34o wiYw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468722; x=1702073522; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=z9dqjoMSn+7T+gtB15gD5H7naTL8GFoazbK/o6+nI2Y=; b=NP4KaS8lnRZWeUs6JCOliIoFHF6BpT55PJN9VrBHJQWngVV5wY7FawNvCH9mdEPBvi /zfUUfSne2hxEPe98SgwjiUtbVJg34gSv9N8nhDdJlw9vMfqxYLxq8B4UTNWDnNGzP6O T5Bi42WZLi/SAKKLsb6azj4AENIkpIabzjGDWL/V0ui6zLK938/IO+0dOcJgxZnO0+UP GYKKGbyFQ3z/VEG54J0UNjJwj+qmhMFRfa9Tc5HpxOss6FDIjCC2Mw77mFM2hE5WhIR1 ILHtPYp3lip26O9fcZ3nugr0GUhperqQ/HEXqAqyx8GFQLfc6d5ERXndz0gTCXevjOcg ylNw== X-Gm-Message-State: AOJu0YzoHwvEcuazQV76jWiUSbUQqIFdwzVDaoWGL0JO8KpMQEB3LKVc WIcqcTT6DUzzjI8F1VhaxLKePudzzI+oKpl4Ixo+SQ== X-Google-Smtp-Source: AGHT+IGIFd5zXUDquyZwsbeCwiMuEZ5On3tjMOHUai6QDKOsufIrQo2vGp86UI1c5VSB+ddOD4hfIg== X-Received: by 2002:a81:ac56:0:b0:5d3:464d:18d9 with SMTP id z22-20020a81ac56000000b005d3464d18d9mr243622ywj.21.1701468722170; Fri, 01 Dec 2023 14:12:02 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id x191-20020a0dd5c8000000b005ca99793930sm1027998ywd.20.2023.12.01.14.12.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:01 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 04/46] fscrypt: conditionally don't wipe mk secret until the last active user is done Date: Fri, 1 Dec 2023 17:11:01 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Previously we were wiping the master key secret when we do FS_IOC_REMOVE_ENCRYPTION_KEY, and then using the fact that it was cleared as the mechanism from keeping new users from being setup. This works with inode based encryption, as the per-inode key is derived at setup time, so the secret disappearing doesn't affect any currently open files from being able to continue working. However for extent based encryption we do our key derivation at page writeout and readpage time, which means we need the master key secret to be available while we still have our file open. Since the master key lifetime is controlled by a flag, move the clearing of the secret to the mk_active_users cleanup stage if we have extent based encryption enabled on this super block. This counter represents the actively open files that still exist on the file system, and thus should still be able to operate normally. Once the last user is closed we can clear the secret. Until then no new users are allowed, and this allows currently open files to continue to operate until they're closed. Signed-off-by: Josef Bacik --- fs/crypto/keyring.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index f34a9b0b9e92..acf5e7b3196d 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -105,6 +105,14 @@ void fscrypt_put_master_key_activeref(struct super_block *sb, WARN_ON_ONCE(mk->mk_present); WARN_ON_ONCE(!list_empty(&mk->mk_decrypted_inodes)); + /* We can't wipe the master key secret until the last activeref is + * dropped on the master key with per-extent encryption since the key + * derivation continues to happen as long as there are active refs. + * Wipe it here now that we're done using it. + */ + if (sb->s_cop->has_per_extent_encryption) + wipe_master_key_secret(&mk->mk_secret); + for (i = 0; i <= FSCRYPT_MODE_MAX; i++) { fscrypt_destroy_prepared_key( sb, &mk->mk_direct_keys[i]); @@ -129,7 +137,15 @@ static void fscrypt_initiate_key_removal(struct super_block *sb, struct fscrypt_master_key *mk) { WRITE_ONCE(mk->mk_present, false); - wipe_master_key_secret(&mk->mk_secret); + + /* + * Per-extent encryption requires the master key to stick around until + * writeout has completed as we derive the per-extent keys at writeout + * time. Once the activeref drops to 0 we'll wipe the master secret + * key. + */ + if (!sb->s_cop->has_per_extent_encryption) + wipe_master_key_secret(&mk->mk_secret); fscrypt_put_master_key_activeref(sb, mk); } From patchwork Fri Dec 1 22:11:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476493 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="IVV0/RQU" Received: from mail-yw1-x112f.google.com (mail-yw1-x112f.google.com [IPv6:2607:f8b0:4864:20::112f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0ED3810F1 for ; Fri, 1 Dec 2023 14:12:04 -0800 (PST) Received: by mail-yw1-x112f.google.com with SMTP id 00721157ae682-5d3644d3d67so22348377b3.2 for ; Fri, 01 Dec 2023 14:12:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468723; x=1702073523; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=/160CoL5kD8MZgjTeYrjsK44d+IUTjQMGeYoRwthpu4=; b=IVV0/RQUpq6PfW2vzpKtnTuTqS48i4XIvC1SS53Yfm3A8oIPgb6qnkY0t8Vrnkl3Km GxwE9OOHAvIXffjjKfiYDqVHVQm4ixgesmQFKtjEeMHXJSmfNMjTdddltU65UOA0i8AB OPvP29cAm7cWTpHtCDyPBhb5MjqlAizE61dQ0wE5SrpxGOw0oT+JGT00dloMntcBUZdc Lo6jY5Q/taFeCk4ElaIPeQiS5neuS+7u+bxejTIrkSurNqb+qNEoARfnGdJULLLI011b kkUwYbaiWYJ3txdJhHWK6/sUK6PrClhjgypi3x6OHEQXAtZatEDaEm8g0j7fq0Q8poCh PrAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468723; x=1702073523; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/160CoL5kD8MZgjTeYrjsK44d+IUTjQMGeYoRwthpu4=; b=gDcWDMYeDkQdEqwOL52kuH3gu7ICvdHgucqK8h2XG0WCalGwoDDWADy82WNguvshT4 HUiDVy3egdladw5b9HlipR22p2krT/F0hIy88uFQcP0aXUgSpeIaDJDAnSCufQlrI6+X 3cTGZZelDNY3n4R3UHR+Rd9mD3Tsz4nxUy30GkqfO8QEfYVaWEnXb7ZvFS2qSw/4Upqe YVdga/mYh2Gms2xvdwIa0Rnc+hc7Kex7bV/vs49iFJR2QRewuVc1sMoWEjx/i+3KbDoa 3+Bh15+hjvHF77wGy7YmCdEvWDD3ATbjcJar5etGDiTc++BMf+CVWW72l3DF2hoDyJht H/6A== X-Gm-Message-State: AOJu0Yyk0GxtYvSOHTpPa8/zruA7UKjJ49kyRMhAzEWS1JQ8VGYhmJly srasbBXcamrUzB+GFt+4EqcifDskrjjz+F0MKE1+wA== X-Google-Smtp-Source: AGHT+IHUIHxJntBti8gl1XBwAdsUkLD3yqGZmVWvvs3bS5g0mp5rWZ1bRaXHVtJ80mRQ23tlAhtV0g== X-Received: by 2002:a81:ad52:0:b0:5d7:1940:8de2 with SMTP id l18-20020a81ad52000000b005d719408de2mr165456ywk.73.1701468723074; Fri, 01 Dec 2023 14:12:03 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id o125-20020a817383000000b005d39a1ae8b3sm1157083ywc.1.2023.12.01.14.12.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:02 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 05/46] blk-crypto: add a process bio callback Date: Fri, 1 Dec 2023 17:11:02 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Btrfs does checksumming, and the checksums need to match the bytes on disk. In order to facilitate this add a process bio callback for the blk-crypto layer. This allows the file system to specify a callback and then can process the encrypted bio as necessary. For btrfs, writes will have the checksums calculated and saved into our relevant data structures for storage once the write completes. For reads we will validate the checksums match what is on disk and error out if there is a mismatch. This is incompatible with native encryption obviously, so make sure we don't use native encryption if this callback is set. Signed-off-by: Josef Bacik --- block/blk-crypto-fallback.c | 40 +++++++++++++++++++++++++++++++++++++ block/blk-crypto-internal.h | 8 ++++++++ block/blk-crypto-profile.c | 2 ++ block/blk-crypto.c | 6 +++++- fs/crypto/inline_crypt.c | 3 ++- include/linux/blk-crypto.h | 9 +++++++-- include/linux/fscrypt.h | 14 +++++++++++++ 7 files changed, 78 insertions(+), 4 deletions(-) diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c index e6468eab2681..1254fed9ffeb 100644 --- a/block/blk-crypto-fallback.c +++ b/block/blk-crypto-fallback.c @@ -346,6 +346,15 @@ static bool blk_crypto_fallback_encrypt_bio(struct bio **bio_ptr) } } + /* Process the encrypted bio before we submit it. */ + if (bc->bc_key->crypto_cfg.process_bio) { + blk_st = bc->bc_key->crypto_cfg.process_bio(src_bio, enc_bio); + if (blk_st != BLK_STS_OK) { + src_bio->bi_status = blk_st; + goto out_free_bounce_pages; + } + } + enc_bio->bi_private = src_bio; enc_bio->bi_end_io = blk_crypto_fallback_encrypt_endio; *bio_ptr = enc_bio; @@ -391,6 +400,24 @@ static void blk_crypto_fallback_decrypt_bio(struct work_struct *work) unsigned int i; blk_status_t blk_st; + /* + * Process the bio first before trying to decrypt. + * + * NOTE: btrfs expects that this bio is the same that was submitted. If + * at any point this changes we will need to update process_bio to take + * f_ctx->crypt_iter in order to make sure we can iterate the pages for + * checksumming. We're currently saving this in our btrfs_bio, so this + * works, but if at any point in the future we start allocating a bounce + * bio or something we need to update this callback. + */ + if (bc->bc_key->crypto_cfg.process_bio) { + blk_st = bc->bc_key->crypto_cfg.process_bio(bio, bio); + if (blk_st != BLK_STS_OK) { + bio->bi_status = blk_st; + goto out_no_keyslot; + } + } + /* * Get a blk-crypto-fallback keyslot that contains a crypto_skcipher for * this bio's algorithm and key. @@ -440,6 +467,19 @@ static void blk_crypto_fallback_decrypt_bio(struct work_struct *work) bio_endio(bio); } +/** + * blk_crypto_cfg_supports_process_bio - check if this config supports + * process_bio + * @profile: the profile we're checking + * + * This is just a quick check to make sure @profile is the fallback profile, as + * no other offload implementations support process_bio. + */ +bool blk_crypto_cfg_supports_process_bio(struct blk_crypto_profile *profile) +{ + return profile == blk_crypto_fallback_profile; +} + /** * blk_crypto_fallback_decrypt_endio - queue bio for fallback decryption * diff --git a/block/blk-crypto-internal.h b/block/blk-crypto-internal.h index 93a141979694..6664a04cb6ad 100644 --- a/block/blk-crypto-internal.h +++ b/block/blk-crypto-internal.h @@ -213,6 +213,8 @@ bool blk_crypto_fallback_bio_prep(struct bio **bio_ptr); int blk_crypto_fallback_evict_key(const struct blk_crypto_key *key); +bool blk_crypto_cfg_supports_process_bio(struct blk_crypto_profile *profile); + #else /* CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK */ static inline int @@ -235,6 +237,12 @@ blk_crypto_fallback_evict_key(const struct blk_crypto_key *key) return 0; } +static inline bool +blk_crypto_cfg_supports_process_bio(struct blk_crypto_profile *profile) +{ + return false; +} + #endif /* CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK */ #endif /* __LINUX_BLK_CRYPTO_INTERNAL_H */ diff --git a/block/blk-crypto-profile.c b/block/blk-crypto-profile.c index 7fabc883e39f..5d26d49d9372 100644 --- a/block/blk-crypto-profile.c +++ b/block/blk-crypto-profile.c @@ -352,6 +352,8 @@ bool __blk_crypto_cfg_supported(struct blk_crypto_profile *profile, return false; if (profile->max_dun_bytes_supported < cfg->dun_bytes) return false; + if (cfg->process_bio && !blk_crypto_cfg_supports_process_bio(profile)) + return false; return true; } diff --git a/block/blk-crypto.c b/block/blk-crypto.c index 4d760b092deb..50556952df19 100644 --- a/block/blk-crypto.c +++ b/block/blk-crypto.c @@ -321,6 +321,8 @@ int __blk_crypto_rq_bio_prep(struct request *rq, struct bio *bio, * @dun_bytes: number of bytes that will be used to specify the DUN when this * key is used * @data_unit_size: the data unit size to use for en/decryption + * @process_bio: the call back if the upper layer needs to process the encrypted + * bio * * Return: 0 on success, -errno on failure. The caller is responsible for * zeroizing both blk_key and raw_key when done with them. @@ -328,7 +330,8 @@ int __blk_crypto_rq_bio_prep(struct request *rq, struct bio *bio, int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key, enum blk_crypto_mode_num crypto_mode, unsigned int dun_bytes, - unsigned int data_unit_size) + unsigned int data_unit_size, + blk_crypto_process_bio_t process_bio) { const struct blk_crypto_mode *mode; @@ -350,6 +353,7 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key, blk_key->crypto_cfg.crypto_mode = crypto_mode; blk_key->crypto_cfg.dun_bytes = dun_bytes; blk_key->crypto_cfg.data_unit_size = data_unit_size; + blk_key->crypto_cfg.process_bio = process_bio; blk_key->data_unit_size_bits = ilog2(data_unit_size); blk_key->size = mode->keysize; memcpy(blk_key->raw, raw_key, mode->keysize); diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c index 4eeb75410ba8..57776c548a06 100644 --- a/fs/crypto/inline_crypt.c +++ b/fs/crypto/inline_crypt.c @@ -168,7 +168,8 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, err = blk_crypto_init_key(blk_key, raw_key, crypto_mode, fscrypt_get_dun_bytes(ci), - 1U << ci->ci_data_unit_bits); + 1U << ci->ci_data_unit_bits, + sb->s_cop->process_bio); if (err) { fscrypt_err(inode, "error %d initializing blk-crypto key", err); goto fail; diff --git a/include/linux/blk-crypto.h b/include/linux/blk-crypto.h index 5e5822c18ee4..194c1d727013 100644 --- a/include/linux/blk-crypto.h +++ b/include/linux/blk-crypto.h @@ -6,7 +6,7 @@ #ifndef __LINUX_BLK_CRYPTO_H #define __LINUX_BLK_CRYPTO_H -#include +#include enum blk_crypto_mode_num { BLK_ENCRYPTION_MODE_INVALID, @@ -17,6 +17,9 @@ enum blk_crypto_mode_num { BLK_ENCRYPTION_MODE_MAX, }; +typedef blk_status_t (blk_crypto_process_bio_t)(struct bio *orig_bio, + struct bio *enc_bio); + #define BLK_CRYPTO_MAX_KEY_SIZE 64 /** * struct blk_crypto_config - an inline encryption key's crypto configuration @@ -31,6 +34,7 @@ struct blk_crypto_config { enum blk_crypto_mode_num crypto_mode; unsigned int data_unit_size; unsigned int dun_bytes; + blk_crypto_process_bio_t *process_bio; }; /** @@ -90,7 +94,8 @@ bool bio_crypt_dun_is_contiguous(const struct bio_crypt_ctx *bc, int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key, enum blk_crypto_mode_num crypto_mode, unsigned int dun_bytes, - unsigned int data_unit_size); + unsigned int data_unit_size, + blk_crypto_process_bio_t process_bio); int blk_crypto_start_using_key(struct block_device *bdev, const struct blk_crypto_key *key); diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 756f23fc3e83..5f5efb472fc9 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -16,6 +16,7 @@ #include #include #include +#include #include /* @@ -199,6 +200,19 @@ struct fscrypt_operations { */ struct block_device **(*get_devices)(struct super_block *sb, unsigned int *num_devs); + + /* + * A callback if the file system requires the ability to process the + * encrypted bio. + * + * @orig_bio: the original bio submitted. + * @enc_bio: the encrypted bio. + * + * For writes the enc_bio will be different from the orig_bio, for reads + * they will be the same. For reads we get the bio before it is + * decrypted, for writes we get the bio before it is submitted. + */ + blk_crypto_process_bio_t *process_bio; }; static inline struct fscrypt_inode_info * From patchwork Fri Dec 1 22:11:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476494 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="gXJKgLbr" Received: from mail-oi1-x244.google.com (mail-oi1-x244.google.com [IPv6:2607:f8b0:4864:20::244]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 195F5D63 for ; Fri, 1 Dec 2023 14:12:05 -0800 (PST) Received: by mail-oi1-x244.google.com with SMTP id 5614622812f47-3b894f5a7f3so695338b6e.2 for ; Fri, 01 Dec 2023 14:12:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468724; x=1702073524; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=QbK7VG5ffcr9w9iDFpEuegAUmWGv6iIQ9NZY4MUBNCA=; b=gXJKgLbrFnt4XhFNd7GTwJIGSbax/HPNdtM+0SXahwwlLyCRXX9JZ3rgL9Gm//vNRz GDafGoLD2GBS7tnUrapIXPXE6Pu4sgqa+tevdZHnTawMAF71QEQ99p1+14STEdBqMWOR KRrfVFr8lWNb21yq5a014ytaV/reZW0PJPgE+ctmQLGrogUM9jNaaZBNpvL1QT1SCSyx Ihb8sDb+5//ihSBSJUX3490HQyFeVn0QgbW65H12LSQfnF+slI5fZoiYFEWgN/vyVHUu xxZQ2nv6NFO+TIgcrgosqwQzXA0T76UC5OZ8WvklSmX0qZqqY73pCmajfE8K8GQxvoX5 kpPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468724; x=1702073524; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=QbK7VG5ffcr9w9iDFpEuegAUmWGv6iIQ9NZY4MUBNCA=; b=SRoPP5OXepi93Sp/yYPcRjF5B7rFo5aO3i5sjA/NHhqPz882X0gDiACkt6ColbDffa Jx6VjNwfC7hC6/JHkWq8i4ouLSYmwz24yup/j9UnliK155vDlurvlMbiRKwBm1FAxJGB aGYJdWG7yMZGgLeDWHsHgVaqRpC5uSdbtGnC75gm7+Nm5n5TmTqlmzU0Z2h3B4HUF9i3 XVoTsEf9Sv/r7Un07i7XhPNV+helPioIjL+bGFkEqmf8ObkFp0E1LFf9eZXm9+rjaFxJ f4HiMd/W/qLHuMmza/hcLRnIG2MONNlHcojyDfPjjVnZWPCkQC4bZ0cXpqM9Vg7Ysm+5 q7Gw== X-Gm-Message-State: AOJu0Ywbe4q5vaZY+XBcLxWTtD06zY/WeJIBfJeOwMLbBW22PaFMbWvx 8eI7BThqVTBJnNWP1/ykVnAq5zASZBxAVolmHH0U9Gpe X-Google-Smtp-Source: AGHT+IEka+r2md7elXRlJE+Y2d8ogbSxONATBF2oEHfJN76X221SjvolUGB1Vtnh/yM+qCQa6N0xig== X-Received: by 2002:a54:4710:0:b0:3b8:b063:a1e1 with SMTP id k16-20020a544710000000b003b8b063a1e1mr218349oik.107.1701468724240; Fri, 01 Dec 2023 14:12:04 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id y14-20020a5b0d0e000000b00da10d9e96cesm618601ybp.35.2023.12.01.14.12.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:03 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Omar Sandoval , Sweet Tea Dorminy Subject: [PATCH v4 06/46] fscrypt: expose fscrypt_nokey_name Date: Fri, 1 Dec 2023 17:11:03 -0500 Message-ID: <5e180dc6cef80ab6997d5f4827ac1583123a5074.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Omar Sandoval btrfs stores its data structures, including filenames in directories, in its own buffer implementation, struct extent_buffer, composed of several non-contiguous pages. We could copy filenames into a temporary buffer and use fscrypt_match_name() against that buffer, such extensive memcpying would be expensive. Instead, exposing fscrypt_nokey_name as in this change allows btrfs to recapitulate fscrypt_match_name() using methods on struct extent_buffer instead of dealing with a raw byte array. Signed-off-by: Omar Sandoval Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/crypto/fname.c | 39 +-------------------------------------- include/linux/fscrypt.h | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 7b3fc189593a..5607ee52703e 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include "fscrypt_private.h" @@ -26,43 +25,7 @@ #define FSCRYPT_FNAME_MIN_MSG_LEN 16 /* - * struct fscrypt_nokey_name - identifier for directory entry when key is absent - * - * When userspace lists an encrypted directory without access to the key, the - * filesystem must present a unique "no-key name" for each filename that allows - * it to find the directory entry again if requested. Naively, that would just - * mean using the ciphertext filenames. However, since the ciphertext filenames - * can contain illegal characters ('\0' and '/'), they must be encoded in some - * way. We use base64url. But that can cause names to exceed NAME_MAX (255 - * bytes), so we also need to use a strong hash to abbreviate long names. - * - * The filesystem may also need another kind of hash, the "dirhash", to quickly - * find the directory entry. Since filesystems normally compute the dirhash - * over the on-disk filename (i.e. the ciphertext), it's not computable from - * no-key names that abbreviate the ciphertext using the strong hash to fit in - * NAME_MAX. It's also not computable if it's a keyed hash taken over the - * plaintext (but it may still be available in the on-disk directory entry); - * casefolded directories use this type of dirhash. At least in these cases, - * each no-key name must include the name's dirhash too. - * - * To meet all these requirements, we base64url-encode the following - * variable-length structure. It contains the dirhash, or 0's if the filesystem - * didn't provide one; up to 149 bytes of the ciphertext name; and for - * ciphertexts longer than 149 bytes, also the SHA-256 of the remaining bytes. - * - * This ensures that each no-key name contains everything needed to find the - * directory entry again, contains only legal characters, doesn't exceed - * NAME_MAX, is unambiguous unless there's a SHA-256 collision, and that we only - * take the performance hit of SHA-256 on very long filenames (which are rare). - */ -struct fscrypt_nokey_name { - u32 dirhash[2]; - u8 bytes[149]; - u8 sha256[SHA256_DIGEST_SIZE]; -}; /* 189 bytes => 252 bytes base64url-encoded, which is <= NAME_MAX (255) */ - -/* - * Decoded size of max-size no-key name, i.e. a name that was abbreviated using + * Decoded size of max-size nokey name, i.e. a name that was abbreviated using * the strong hash and thus includes the 'sha256' field. This isn't simply * sizeof(struct fscrypt_nokey_name), as the padding at the end isn't included. */ diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 5f5efb472fc9..f57601b40e18 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -17,6 +17,7 @@ #include #include #include +#include #include /* @@ -56,6 +57,42 @@ struct fscrypt_name { #define fname_name(p) ((p)->disk_name.name) #define fname_len(p) ((p)->disk_name.len) +/* + * struct fscrypt_nokey_name - identifier for directory entry when key is absent + * + * When userspace lists an encrypted directory without access to the key, the + * filesystem must present a unique "no-key name" for each filename that allows + * it to find the directory entry again if requested. Naively, that would just + * mean using the ciphertext filenames. However, since the ciphertext filenames + * can contain illegal characters ('\0' and '/'), they must be encoded in some + * way. We use base64url. But that can cause names to exceed NAME_MAX (255 + * bytes), so we also need to use a strong hash to abbreviate long names. + * + * The filesystem may also need another kind of hash, the "dirhash", to quickly + * find the directory entry. Since filesystems normally compute the dirhash + * over the on-disk filename (i.e. the ciphertext), it's not computable from + * no-key names that abbreviate the ciphertext using the strong hash to fit in + * NAME_MAX. It's also not computable if it's a keyed hash taken over the + * plaintext (but it may still be available in the on-disk directory entry); + * casefolded directories use this type of dirhash. At least in these cases, + * each no-key name must include the name's dirhash too. + * + * To meet all these requirements, we base64url-encode the following + * variable-length structure. It contains the dirhash, or 0's if the filesystem + * didn't provide one; up to 149 bytes of the ciphertext name; and for + * ciphertexts longer than 149 bytes, also the SHA-256 of the remaining bytes. + * + * This ensures that each no-key name contains everything needed to find the + * directory entry again, contains only legal characters, doesn't exceed + * NAME_MAX, is unambiguous unless there's a SHA-256 collision, and that we only + * take the performance hit of SHA-256 on very long filenames (which are rare). + */ +struct fscrypt_nokey_name { + u32 dirhash[2]; + u8 bytes[149]; + u8 sha256[SHA256_DIGEST_SIZE]; +}; /* 189 bytes => 252 bytes base64url-encoded, which is <= NAME_MAX (255) */ + /* Maximum value for the third parameter of fscrypt_operations.set_context(). */ #define FSCRYPT_SET_CONTEXT_MAX_SIZE 40 From patchwork Fri Dec 1 22:11:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476495 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="VbhRIX+p" Received: from mail-yb1-xb42.google.com (mail-yb1-xb42.google.com [IPv6:2607:f8b0:4864:20::b42]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5305610D for ; Fri, 1 Dec 2023 14:12:06 -0800 (PST) Received: by mail-yb1-xb42.google.com with SMTP id 3f1490d57ef6-d9beb865a40so990089276.1 for ; Fri, 01 Dec 2023 14:12:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468725; x=1702073525; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=YYVHSmz3QYock1Rn/5GLr5Ch+VJ6Y1Sc8gFeLki2OwI=; b=VbhRIX+p8/VzHYAegVuLG0ibnIxAbt4ECU0t1HI0eQRLhHH83TAY02BzCYYUWiPDiz EeOmR7VTu+/JWiSJtP+BTbJzEBbubh1dVk3sbn3kfa7GR8593wCjuevEgrlb1sz/eNJ1 UhhK96/lxL16UFI8Ji2e3WuSEImAwvEis3uS77RWJqj+LlxZqwboLu65jKMgzPKmyLkX SpfDadWx0EEnEoh2MSkCk55u/qFMYzkHO9tdqdfvpC9mmVgRbCmTKqwrSIt12HNLXVi2 c2Dy11aoBoeZO3RfQKaNGUw1kL02Uf7NVYfw/HWTM9u7s2nvp3ix5NqTXCfQIG1PU5f2 4fbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468725; x=1702073525; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=YYVHSmz3QYock1Rn/5GLr5Ch+VJ6Y1Sc8gFeLki2OwI=; b=CSNT9f3o6JsPqMxJxrKhQffvVnVxpMgKSIHgcOJSzUO90Wh0LcUqDHB0+FU5x4YQwp 4EqTzHUg4N4F0mkXiUNBCeCGsR2ORtHVVwm2ingHJIgP9Va2zOCCQKjBeazkFZ9jW8Zf xBq6eA7Gnrc8jtgM22XTVyOW1RmXDIscWyP8LInWQ1IG/HXnvtVZLQtoAlv5pHs5BXrv 44awPyOMwZFFXyIuuqVU67wgj4oAl39zxc9NXBBIPXLZXH01NnUYyMZP91T/kJaft0F9 9DRExTq77e4zStUp7WSn+TlEujlrJ2IATNZHwQBLQzW9P94Do+i5suZKPXjC3Qw1/LOj dbHw== X-Gm-Message-State: AOJu0YxOD4Lh2Cj4b5n5Dn0F2CPRzWSz+q/Qxpoy8icWy8Hg+JqovfCW dQcG84xe0hQL+3nvNJ3xQPXa0J/lpCU+tbXwO0a2QF4+ X-Google-Smtp-Source: AGHT+IEu1m3fKOVowcAxkrEKVQ5KZJ3yqxWd+Rrq4rW9myeJmiMuLaCUlVbaG1Ul38DPuL6e5FjUfQ== X-Received: by 2002:a5b:4c1:0:b0:db7:dacf:3f9e with SMTP id u1-20020a5b04c1000000b00db7dacf3f9emr157668ybp.75.1701468725242; Fri, 01 Dec 2023 14:12:05 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id 196-20020a2504cd000000b00d995a8b956csm639877ybe.51.2023.12.01.14.12.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:04 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 07/46] fscrypt: add documentation about extent encryption Date: Fri, 1 Dec 2023 17:11:04 -0500 Message-ID: <16939187c6d8ae790a2a02e8326660cdcaf978c5.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add a couple of sections to the fscrypt documentation about per-extent encryption. Signed-off-by: Josef Bacik --- Documentation/filesystems/fscrypt.rst | 41 +++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst index 1b84f818e574..dc8bf04484ba 100644 --- a/Documentation/filesystems/fscrypt.rst +++ b/Documentation/filesystems/fscrypt.rst @@ -256,6 +256,21 @@ alternative master keys or to support rotating master keys. Instead, the master keys may be wrapped in userspace, e.g. as is done by the `fscrypt `_ tool. +Per-extent encryption keys +-------------------------- + +For certain file systems, such as btrfs, it's desired to derive a +per-extent encryption key. This is to enable features such as snapshots +and reflink, where you could have different inodes pointing at the same +extent. When a new extent is created fscrypt randomly generates a +16-byte nonce and the file system stores it along side the extent. +Then, it uses a KDF (as described in `Key derivation function`_) to +derive the extent's key from the master key and nonce. + +Currently the inode's master key and encryption policy must match the +extent, so you cannot share extents between inodes that were encrypted +differently. + DIRECT_KEY policies ------------------- @@ -1394,6 +1409,27 @@ by the kernel and is used as KDF input or as a tweak to cause different files to be encrypted differently; see `Per-file encryption keys`_ and `DIRECT_KEY policies`_. +Extent encryption context +------------------------- + +The extent encryption context mirrors the important parts of the above +`Encryption context`_, with a few ommisions. The struct is defined as +follows:: + + struct fscrypt_extent_context { + u8 version; + u8 encryption_mode; + u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]; + u8 nonce[FSCRYPT_FILE_NONCE_SIZE]; + }; + +Currently all fields much match the containing inode's encryption +context, with the exception of the nonce. + +Additionally extent encryption is only supported with +FSCRYPT_EXTENT_CONTEXT_V2 using the standard policy, all other policies +are disallowed. + Data path changes ----------------- @@ -1417,6 +1453,11 @@ buffer. Some filesystems, such as UBIFS, already use temporary buffers regardless of encryption. Other filesystems, such as ext4 and F2FS, have to allocate bounce pages specially for encryption. +Inline encryption is not optional for extent encryption based file +systems, the amount of objects required to be kept around is too much. +Inline encryption handles the object lifetime details which results in a +cleaner implementation. + Filename hashing and encoding ----------------------------- From patchwork Fri Dec 1 22:11:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476496 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="FOeEoXdB" Received: from mail-yw1-x112c.google.com (mail-yw1-x112c.google.com [IPv6:2607:f8b0:4864:20::112c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AA683D6C for ; Fri, 1 Dec 2023 14:12:07 -0800 (PST) Received: by mail-yw1-x112c.google.com with SMTP id 00721157ae682-5cd81e76164so29416277b3.1 for ; Fri, 01 Dec 2023 14:12:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468727; x=1702073527; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=rRbP9jVi3V5fXBhoYCeWMR54boR3Ggluqw/tdmkCHt8=; b=FOeEoXdBUcQcUQhTHvg4lPlfvCc2NZFGERqTONBj2ZCsuBFFzp1MBUvbK95ZPoKsUZ 1sujR3Z9lvq2lgtCtMYswPK8R9/j9sbg1hv0qlQQTXtBgteQMzQ+puzto9TnvNkIGyC8 jTh3nV/cunbRtSwJ1UZWuhWTqkHApF1YkvrxPabaLLsTVNY8vfJKn+luOvqXgymHwg3O 43xU0P5mclLIpODC2qqV3uB6XZHZEXoR33qz58Rqa/yTL7w4mzm2wE1g5O4wPIVLdzo5 0Q+sZVQa6Sv3I4BbuOMmuNefNWAW4ev6ETrLpLv8K7cK5njyhBt2KaoueuNlEdr7pDIL gD4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468727; x=1702073527; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=rRbP9jVi3V5fXBhoYCeWMR54boR3Ggluqw/tdmkCHt8=; b=UhCbZTaqo9fUKtJcXeXL84Yyt2/OKY/6ND5MFPw+80QAJsg/OZfubUHAwACiUjevDA FoajBPc2FvKiN9TVzd0pOZIFHdGYWc9c+RwxF2SOgBvUZfKD8wQRHn4GJakhri9ZFJ1f yJgpm7Jor9KeuuI8qMYviUVFLcHDAew3Ok7uJxkmiHp5GwmD8xPaSkqwdHIdP10OgpBc Iy6e600NmWanACIf6n78gu0z14ijpyWoG3c4HauuQuPjUBE05uVCrJL8uz6xYL9H7Yhc ZGQaP31SLYbrWgFWNW9sSMjxjb40fBKoyV6Ywvb7DCDdn6ONFAfUB+hB89UwwEG5TM62 ci8g== X-Gm-Message-State: AOJu0YxueHLUeDa26j9B7PDGiFG86VeCtwG1tktIXRt3h0TGB/QwFrp1 GcNKOV54Q2xDX/0jJ1zyPH9fK+of77OpK+DdSixYIQ== X-Google-Smtp-Source: AGHT+IEonFB4vJNrURhy4u8oG0ufEWKbxLiQ4StU7oLAaK2if3peCC8nEoAmo+Y2x2OLNC6hVzBdRg== X-Received: by 2002:a05:690c:3509:b0:5d7:a3f:fce3 with SMTP id fq9-20020a05690c350900b005d70a3ffce3mr593515ywb.8.1701468726712; Fri, 01 Dec 2023 14:12:06 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id t6-20020a81c246000000b005845e6f9b50sm1367552ywg.113.2023.12.01.14.12.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:06 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 08/46] btrfs: add infrastructure for safe em freeing Date: Fri, 1 Dec 2023 17:11:05 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 When we add fscrypt support we're going to have fscrypt objects hanging off of extent_maps. This includes a block key, which if we're the last one freeing the key we may have to unregister it from the block layer. This requires taking a semaphore in the block layer, which means we can't free em's under the extent map tree lock. Thankfully we only do this in two places, one where we're dropping a range of extent maps, and when we're freeing logged extents. Add a free_extent_map_safe() which will add the em to a list in the em_tree if we free'd the object. Currently this is unconditional but will be changed to conditional on the fscrypt object we will add in a later patch. To process these delayed objects add a free_pending_extent_maps() that is called after the lock has been dropped on the em_tree. This will process the extent maps on the freed list and do the appropriate freeing work in a safe manner. Signed-off-by: Josef Bacik --- fs/btrfs/extent_map.c | 69 +++++++++++++++++++++++++++++++++++++++++-- fs/btrfs/extent_map.h | 10 +++++++ fs/btrfs/tree-log.c | 6 ++-- 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index c956b1ced69f..20d347fa6f8a 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -35,7 +35,9 @@ void __cold extent_map_exit(void) void extent_map_tree_init(struct extent_map_tree *tree) { tree->map = RB_ROOT_CACHED; + tree->flags = 0; INIT_LIST_HEAD(&tree->modified_extents); + INIT_LIST_HEAD(&tree->freed_extents); rwlock_init(&tree->lock); } @@ -53,6 +55,7 @@ struct extent_map *alloc_extent_map(void) em->compress_type = BTRFS_COMPRESS_NONE; refcount_set(&em->refs, 1); INIT_LIST_HEAD(&em->list); + INIT_LIST_HEAD(&em->free_list); return em; } @@ -71,6 +74,65 @@ void free_extent_map(struct extent_map *em) } } +/* + * Drop a ref for the extent map in the given tree. + * + * @tree: tree that the em is a part of. + * @em: the em to drop the reference to. + * + * Drop the reference count on @em by one, if the reference count hits 0 and + * there is an object on the em that can't be safely freed in the current + * context (if we are holding the extent_map_tree->lock for example), then add + * it to the freed_extents list on the extent_map_tree for later processing. + * + * This must be followed by a free_pending_extent_maps() to clear the pending + * frees. + */ +void free_extent_map_safe(struct extent_map_tree *tree, + struct extent_map *em) +{ + lockdep_assert_held_write(&tree->lock); + + if (!em) + return; + + if (refcount_dec_and_test(&em->refs)) { + WARN_ON(extent_map_in_tree(em)); + WARN_ON(!list_empty(&em->list)); + list_add_tail(&em->free_list, &tree->freed_extents); + set_bit(EXTENT_MAP_TREE_PENDING_FREES, &tree->flags); + } +} + +/* + * Free the em objects that exist on the em tree + * + * @tree: the tree to free the objects from. + * + * If there are any objects on the em->freed_extents list go ahead and free them + * here in a safe way. This is to be coupled with any uses of + * free_extent_map_safe(). + */ +void free_pending_extent_maps(struct extent_map_tree *tree) +{ + struct extent_map *em; + + /* Avoid taking the write lock if we don't have any pending frees. */ + if (!test_and_clear_bit(EXTENT_MAP_TREE_PENDING_FREES, &tree->flags)) + return; + + write_lock(&tree->lock); + while ((em = list_first_entry_or_null(&tree->freed_extents, + struct extent_map, free_list))) { + list_del_init(&em->free_list); + write_unlock(&tree->lock); + __free_extent_map(em); + cond_resched(); + write_lock(&tree->lock); + } + write_unlock(&tree->lock); +} + /* Do the math around the end of an extent, handling wrapping. */ static u64 range_end(u64 start, u64 len) { @@ -645,10 +707,12 @@ static void drop_all_extent_maps_fast(struct extent_map_tree *tree) clear_bit(EXTENT_FLAG_PINNED, &em->flags); clear_bit(EXTENT_FLAG_LOGGING, &em->flags); remove_extent_mapping(tree, em); - free_extent_map(em); + free_extent_map_safe(tree, em); cond_resched_rwlock_write(&tree->lock); } write_unlock(&tree->lock); + + free_pending_extent_maps(tree); } /* @@ -869,13 +933,14 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, free_extent_map(em); next: /* Once for us (for our lookup reference). */ - free_extent_map(em); + free_extent_map_safe(em_tree, em); em = next_em; } write_unlock(&em_tree->lock); + free_pending_extent_maps(em_tree); free_extent_map(split); free_extent_map(split2); } diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index bae14af197ef..fb8905f88f7c 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h @@ -51,11 +51,18 @@ struct extent_map { refcount_t refs; unsigned int compress_type; struct list_head list; + struct list_head free_list; +}; + +enum extent_map_flags { + EXTENT_MAP_TREE_PENDING_FREES, }; struct extent_map_tree { struct rb_root_cached map; + unsigned long flags; struct list_head modified_extents; + struct list_head freed_extents; rwlock_t lock; }; @@ -84,6 +91,9 @@ int split_extent_map(struct btrfs_inode *inode, u64 start, u64 len, u64 pre, struct extent_map *alloc_extent_map(void); void free_extent_map(struct extent_map *em); +void free_extent_map_safe(struct extent_map_tree *tree, + struct extent_map *em); +void free_pending_extent_maps(struct extent_map_tree *tree); int __init extent_map_init(void); void __cold extent_map_exit(void); int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen); diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 7d6729d9fd2f..00b6f0c71e1d 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -4883,7 +4883,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, */ if (ret) { clear_em_logging(tree, em); - free_extent_map(em); + free_extent_map_safe(tree, em); continue; } @@ -4892,11 +4892,13 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, ret = log_one_extent(trans, inode, em, path, ctx); write_lock(&tree->lock); clear_em_logging(tree, em); - free_extent_map(em); + free_extent_map_safe(tree, em); } WARN_ON(!list_empty(&extents)); write_unlock(&tree->lock); + free_pending_extent_maps(tree); + if (!ret) ret = btrfs_log_prealloc_extents(trans, inode, path); if (ret) From patchwork Fri Dec 1 22:11:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476497 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="c5flg0IY" Received: from mail-yw1-x1134.google.com (mail-yw1-x1134.google.com [IPv6:2607:f8b0:4864:20::1134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DBC8510DB for ; Fri, 1 Dec 2023 14:12:08 -0800 (PST) Received: by mail-yw1-x1134.google.com with SMTP id 00721157ae682-5d35a952943so24392317b3.3 for ; Fri, 01 Dec 2023 14:12:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468728; x=1702073528; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7zekUBEhgbNi0HfwU098E6XmEani+U8g9YV01dVhfdc=; b=c5flg0IYHONBK1uHnwwDIrSM5tsq5WqkLnNyOeyDZdw4Cek/S8XI1NRW/OH0Z7hmKI q2ecoQIh0dImJIihzHPV5bcsrVbwgxhJVF9iCvSoIIN5c1BwdDZB0hSHMc00zldH3USm pB2xbEb/h1frpmX/X+Pc1dP0soFnGP/XgUUdprFoDT60Iixn2OYQesTVAvAS/1boN1TI FuKw4y6c2IZJrV6jiSfcKA58tLoN1pyspfywI5nOZ92rf/QiDMqjoAc6e5eWtuoCxYYW 1CseaUPjurqy9/kCyYc+iAuBnVr9v1WzQo1CWBiwPSrZCdYUXGvHQ5EfVkr9v3DjnnIw /fPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468728; x=1702073528; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7zekUBEhgbNi0HfwU098E6XmEani+U8g9YV01dVhfdc=; b=NLOOcQxB94XldxsLooKUc3oweK63Qb9uYgwz6IAw4y4lRb6UIH92EZDRFC1K9FfWo+ RTHcqcePr79lTyk2bLCSul+KkJ1MwAIZJg1PJet6oYzWYvQKTkMwXuTnOdBO3MZY26sO 1rSQ3RYenHGitzyvkBgUTHLfGk00haZ+0j3XICzprUutVv0hndS6ZMNms/JEoT6OTZqf 2ekxfAEcG8c8p36ppv9gtI21AukEceObk1/LjZBxOKUD+3EqreqDy3yMIzQa7AKSyWJR qGff3DfxkWp2wbXTc10CvMySLvIpimX6Uad0XvzucyVUN5kgiig7M4Aseo6moYqYOPMc JAzg== X-Gm-Message-State: AOJu0Yxyl2wdvmPWe5X/XveoO1w+5GBCP8tBZ5A6QE5wECSPT3JHse8g ZkMcmm7BXY+Mku3O1wHRyP4YuqL9hmNjaeSTLzvLww== X-Google-Smtp-Source: AGHT+IHdXU2/Jh3qAQldWEuZBxSlRBsjxJbIlZeUKBhMVnmgxxxL+0vhQT6tfNT26G7KvrcvZ+lgNw== X-Received: by 2002:a81:d549:0:b0:5c9:9097:6427 with SMTP id l9-20020a81d549000000b005c990976427mr221928ywj.44.1701468727997; Fri, 01 Dec 2023 14:12:07 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id w20-20020a81a214000000b005d40a826831sm754821ywg.115.2023.12.01.14.12.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:07 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Omar Sandoval , Sweet Tea Dorminy Subject: [PATCH v4 09/46] btrfs: disable various operations on encrypted inodes Date: Fri, 1 Dec 2023 17:11:06 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Omar Sandoval Initially, only normal data extents will be encrypted. This change forbids various other bits: - allows reflinking only if both inodes have the same encryption status - disable inline data on encrypted inodes Signed-off-by: Omar Sandoval Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 3 ++- fs/btrfs/reflink.c | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f8647d8271b7..108804a5ba82 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -639,7 +639,8 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 size, * compressed) data fits in a leaf and the configured maximum inline * size. */ - if (size < i_size_read(&inode->vfs_inode) || + if (IS_ENCRYPTED(&inode->vfs_inode) || + size < i_size_read(&inode->vfs_inode) || size > fs_info->sectorsize || data_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info) || data_len > fs_info->max_inline) diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c index f88b0c2ac3fe..c39de2a43a00 100644 --- a/fs/btrfs/reflink.c +++ b/fs/btrfs/reflink.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include "ctree.h" #include "fs.h" @@ -809,6 +810,12 @@ static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in, ASSERT(inode_in->i_sb == inode_out->i_sb); } + /* + * Can only reflink encrypted files if both files are encrypted. + */ + if (IS_ENCRYPTED(inode_in) != IS_ENCRYPTED(inode_out)) + return -EINVAL; + /* Don't make the dst file partly checksummed */ if ((BTRFS_I(inode_in)->flags & BTRFS_INODE_NODATASUM) != (BTRFS_I(inode_out)->flags & BTRFS_INODE_NODATASUM)) { From patchwork Fri Dec 1 22:11:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476498 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="P2IBZhi4" Received: from mail-yw1-x1130.google.com (mail-yw1-x1130.google.com [IPv6:2607:f8b0:4864:20::1130]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 195A2D50 for ; Fri, 1 Dec 2023 14:12:10 -0800 (PST) Received: by mail-yw1-x1130.google.com with SMTP id 00721157ae682-5d2d0661a8dso29235137b3.2 for ; Fri, 01 Dec 2023 14:12:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468729; x=1702073529; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1X/0Zt7z+oOh2YdMAkIlfw4aC9CST8nDgU19CDUdTeo=; b=P2IBZhi4s6FWT6EmTiRkmZ5vcRCji05d+/WMHHRxQbe4LzoupmN19stc4uLSe3iZHN sCN5EHh9Yd8ov5VdVJgJUWumvpppkmT4Mzxc/Yh3hX8ZyxDCYLSGV+G6GAoI6q/mW/dS seHknQP7B+O7Cq20UmzxeyesvqoY9f4qoddz8fOgtbNw1vpO+mOPh0DZgQmLrOw9M6rq qUazgl8K//1CAt/7dA27EWlUX4E6pv/JHIiO4vh4PuP1+Suu5Nzuzk875XMIaegGmcmS p9bu6jyBhJ7FnlMuRoY9zevZ8Qt3yAC0012BrVKL0cjMg1F9b2Hb5rqSXqHrb5WNQtUs LRnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468729; x=1702073529; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1X/0Zt7z+oOh2YdMAkIlfw4aC9CST8nDgU19CDUdTeo=; b=jkCoZXtwZj4GH0Ci6m9dkQ8ceTy2WaRito7ElT0eoJIqrsFcIcwxXbA+LoAPs7reDx mbAf9qRRTqA4DDjgkMoPMejyrmzvzh5wjmg7s/pNzlBeEOOLnjD88rrWJBt7SVAasEyP oS0npjbAmh0Iq0G43xqCJFJ+BjJEUScbG3SOTDAjjzPYPUPGnySU81jK2aJncf09Wyli VAhe2E+0LZmr5Rpea5qur3QZfGbqUCSfBl30rhsKl3OPxZhXpk7kIPtyU5IylsprGClS MGjb6VykbD5J3f+8uqT71l18kSypAsNoWUfd9Yy9IMPWRm6ivQhXrT2YmJZb+eCQkbkk RMiw== X-Gm-Message-State: AOJu0YzOYHYUdo4wWRD+B4RMa5wxwgaugq+b2JbLrQRzB/mu3RpQ+zD3 d/RyJfC4mEw9XtChtPgJL1rsdxSscjaiTZJaEoSpGg== X-Google-Smtp-Source: AGHT+IHG4M1CczGHQ7bOVowaE9o2KJMn/AsrysW3l+8fn2dOGNuZYQus1HIZpuOo6/3GSY/TlGFAGg== X-Received: by 2002:a81:8645:0:b0:5ca:c8ad:1717 with SMTP id w66-20020a818645000000b005cac8ad1717mr26506701ywf.44.1701468729173; Fri, 01 Dec 2023 14:12:09 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id n127-20020a0dcb85000000b005ccf7fc2197sm380679ywd.24.2023.12.01.14.12.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:08 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Sweet Tea Dorminy Subject: [PATCH v4 10/46] btrfs: disable verity on encrypted inodes Date: Fri, 1 Dec 2023 17:11:07 -0500 Message-ID: <9fbfdc5ea7ad2059ff0560ddf079bd1daecd971e.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Sweet Tea Dorminy Right now there isn't a way to encrypt things that aren't either filenames in directories or data on blocks on disk with extent encryption, so for now, disable verity usage with encryption on btrfs. Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/verity.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/btrfs/verity.c b/fs/btrfs/verity.c index 66e2270b0dae..92536913df04 100644 --- a/fs/btrfs/verity.c +++ b/fs/btrfs/verity.c @@ -588,6 +588,9 @@ static int btrfs_begin_enable_verity(struct file *filp) ASSERT(inode_is_locked(file_inode(filp))); + if (IS_ENCRYPTED(&inode->vfs_inode)) + return -EINVAL; + if (test_bit(BTRFS_INODE_VERITY_IN_PROGRESS, &inode->runtime_flags)) return -EBUSY; From patchwork Fri Dec 1 22:11:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476499 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="Bg28QWhG" Received: from mail-yw1-x1143.google.com (mail-yw1-x1143.google.com [IPv6:2607:f8b0:4864:20::1143]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 39930128 for ; Fri, 1 Dec 2023 14:12:11 -0800 (PST) Received: by mail-yw1-x1143.google.com with SMTP id 00721157ae682-5d3687a6574so24793487b3.2 for ; Fri, 01 Dec 2023 14:12:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468730; x=1702073530; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gcY48GCn2BRWEm6ZB48bnvgy0TA+0TJfTrsQvMmYHkE=; b=Bg28QWhGRLx0KxwC+7I56Nzp2kWcDDfOpcBIWBSZJ0Exc8345H8ib5xI4UFft5GT1u bQy3n83Aeo0xxXGcuWumhBBdaG6TC/hKUKDVv9SSkpUGCKzT6ab9y8iBSrP8hGkEUkId CEt/2yyGrEGXQPCOoizwXXeJha0jgF9rovRDGmQQQuEvTYs7gMJ9V4xgg4/4+T8XIcTX i8ttSa05nw98UbqioM2afNmoFpHmm+TbZpUwMHkTGbs4J8jKfffk+a7yLaGYz1i17sdz 1JLUvYEcq8TZ32uFCYtzknAJGu5C8DV7jCFInUU2soTQefc10DHZwNt5YYjlcAEvZLy2 z76Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468730; x=1702073530; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gcY48GCn2BRWEm6ZB48bnvgy0TA+0TJfTrsQvMmYHkE=; b=N5WFm3bOzW+idjDZ6tX21CzI7cyIkKIqfKuAGouw1IZGUUygrBmig12twgIIH9+Wbs VjY/of/TGXhtg0xv1HWExtj/IaTirwTDi7bR/zmjL9hX11H8I+u4VGq/jPo6QjDMyGT7 r1+iEsB4S9OTth/xJt4XltOoa8FKszX4j+pfsoOCY5sHxvXTuCCeyzudrGrDRpT4a+kh V23NvVC/4m5B3+uj2z+CReFYoRWHOHUMqKbrMhX2bT1odiWCkLKb8sE7fNbSCiB/nsWf kzHM15CkUFrklBo4ttaIwaUzQTZ11Ck7hwojTNzCsAL/7We1Iu0rRzG+YSxmayk7l/1s KwDg== X-Gm-Message-State: AOJu0YzeDqRkZ/q52h1vRwEAFtUUmBQgbTs5TYHpOnNjjjzEOxX6xviD GJLJz3KoPZubRjmcmoHFDbsr7OlIDisAJZJGOg7bCSQ0 X-Google-Smtp-Source: AGHT+IE8+jfgP5N2DxCg0UCxwa7U/6rgU2ahSK4ZrdRnWqxvdRnEJhiOxN6YmMmhvzQjK2EvJ/mdMA== X-Received: by 2002:a81:9a15:0:b0:5d7:1940:7d90 with SMTP id r21-20020a819a15000000b005d719407d90mr185941ywg.103.1701468730227; Fri, 01 Dec 2023 14:12:10 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id z14-20020a814c0e000000b005d14e254367sm1382386ywa.80.2023.12.01.14.12.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:09 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Omar Sandoval , Sweet Tea Dorminy Subject: [PATCH v4 11/46] btrfs: start using fscrypt hooks Date: Fri, 1 Dec 2023 17:11:08 -0500 Message-ID: <91c61882ff591623e858414376d3a2c7a3474611.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Omar Sandoval In order to appropriately encrypt, create, open, rename, and various symlink operations must call fscrypt hooks. These determine whether the inode should be encrypted and do other preparatory actions. The superblock must have fscrypt operations registered, so implement the minimal set also, and introduce the new fscrypt.[ch] files to hold the fscrypt-specific functionality. Signed-off-by: Omar Sandoval Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/Makefile | 1 + fs/btrfs/btrfs_inode.h | 1 + fs/btrfs/file.c | 3 ++ fs/btrfs/fscrypt.c | 7 +++ fs/btrfs/fscrypt.h | 10 ++++ fs/btrfs/inode.c | 110 ++++++++++++++++++++++++++++++++++------- fs/btrfs/super.c | 2 + 7 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 fs/btrfs/fscrypt.c create mode 100644 fs/btrfs/fscrypt.h diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index 525af975f61c..6e51d054c17a 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile @@ -39,6 +39,7 @@ btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o btrfs-$(CONFIG_BTRFS_FS_REF_VERIFY) += ref-verify.o btrfs-$(CONFIG_BLK_DEV_ZONED) += zoned.o btrfs-$(CONFIG_FS_VERITY) += verity.o +btrfs-$(CONFIG_FS_ENCRYPTION) += fscrypt.o btrfs-$(CONFIG_BTRFS_FS_RUN_SANITY_TESTS) += tests/free-space-tests.o \ tests/extent-buffer-tests.o tests/btrfs-tests.o \ diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index de9f71743b6b..048eb211b54a 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -457,6 +457,7 @@ struct btrfs_new_inode_args { struct posix_acl *default_acl; struct posix_acl *acl; struct fscrypt_name fname; + bool encrypt; }; int btrfs_new_inode_prepare(struct btrfs_new_inode_args *args, diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index e9c4b947a5aa..b4a503731e79 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -3711,6 +3711,9 @@ static int btrfs_file_open(struct inode *inode, struct file *filp) filp->f_mode |= FMODE_NOWAIT | FMODE_BUF_RASYNC | FMODE_BUF_WASYNC | FMODE_CAN_ODIRECT; + ret = fscrypt_file_open(inode, filp); + if (ret) + return ret; ret = fsverity_file_open(inode, filp); if (ret) diff --git a/fs/btrfs/fscrypt.c b/fs/btrfs/fscrypt.c new file mode 100644 index 000000000000..48ab99dfe48d --- /dev/null +++ b/fs/btrfs/fscrypt.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "ctree.h" +#include "fscrypt.h" + +const struct fscrypt_operations btrfs_fscrypt_ops = { +}; diff --git a/fs/btrfs/fscrypt.h b/fs/btrfs/fscrypt.h new file mode 100644 index 000000000000..7f4e6888bd43 --- /dev/null +++ b/fs/btrfs/fscrypt.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef BTRFS_FSCRYPT_H +#define BTRFS_FSCRYPT_H + +#include + +extern const struct fscrypt_operations btrfs_fscrypt_ops; + +#endif /* BTRFS_FSCRYPT_H */ diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 108804a5ba82..d58003eb447d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5058,6 +5058,10 @@ static int btrfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, if (err) return err; + err = fscrypt_prepare_setattr(dentry, attr); + if (err) + return err; + if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { err = btrfs_setsize(inode, attr); if (err) @@ -5212,11 +5216,8 @@ void btrfs_evict_inode(struct inode *inode) trace_btrfs_inode_evict(inode); - if (!root) { - fsverity_cleanup_inode(inode); - clear_inode(inode); - return; - } + if (!root) + goto cleanup; evict_inode_truncate_pages(inode); @@ -5316,6 +5317,9 @@ void btrfs_evict_inode(struct inode *inode) * to retry these periodically in the future. */ btrfs_remove_delayed_node(BTRFS_I(inode)); + +cleanup: + fscrypt_put_encryption_info(inode); fsverity_cleanup_inode(inode); clear_inode(inode); } @@ -6106,6 +6110,12 @@ int btrfs_new_inode_prepare(struct btrfs_new_inode_args *args, return ret; } + ret = fscrypt_prepare_new_inode(dir, inode, &args->encrypt); + if (ret) { + fscrypt_free_filename(&args->fname); + return ret; + } + /* 1 to add inode item */ *trans_num_items = 1; /* 1 to add compression property */ @@ -6587,9 +6597,13 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, if (inode->i_nlink >= BTRFS_LINK_MAX) return -EMLINK; + err = fscrypt_prepare_link(old_dentry, dir, dentry); + if (err) + return err; + err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &fname); if (err) - goto fail; + return err; err = btrfs_set_inode_index(BTRFS_I(dir), &index); if (err) @@ -8550,6 +8564,7 @@ void btrfs_test_destroy_inode(struct inode *inode) void btrfs_free_inode(struct inode *inode) { + fscrypt_free_inode(inode); kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode)); } @@ -8620,8 +8635,7 @@ int btrfs_drop_inode(struct inode *inode) /* the snap/subvol tree is on deleting */ if (btrfs_root_refs(&root->root_item) == 0) return 1; - else - return generic_drop_inode(inode); + return generic_drop_inode(inode) || fscrypt_drop_inode(inode); } static void init_once(void *foo) @@ -9201,6 +9215,11 @@ static int btrfs_rename2(struct mnt_idmap *idmap, struct inode *old_dir, if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) return -EINVAL; + ret = fscrypt_prepare_rename(old_dir, old_dentry, new_dir, new_dentry, + flags); + if (ret) + return ret; + if (flags & RENAME_EXCHANGE) ret = btrfs_rename_exchange(old_dir, old_dentry, new_dir, new_dentry); @@ -9415,15 +9434,31 @@ static int btrfs_symlink(struct mnt_idmap *idmap, struct inode *dir, }; unsigned int trans_num_items; int err; - int name_len; int datasize; unsigned long ptr; struct btrfs_file_extent_item *ei; struct extent_buffer *leaf; + struct fscrypt_str disk_link; + size_t max_len; + u32 name_len = strlen(symname); - name_len = strlen(symname); - if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info)) - return -ENAMETOOLONG; + /* + * BTRFS_MAX_INLINE_DATA_SIZE() isn't actually telling the truth, we + * actually limit inline data extents to + * min(BTRFS_MAX_INLINE_DATA_SIZE(), sectorsize), so adjust max_len + * given this wonderful bit of inconsistency. + */ + max_len = min_t(size_t, BTRFS_MAX_INLINE_DATA_SIZE(fs_info), + fs_info->sectorsize); + + /* + * fscrypt sets disk_link.len to be len + 1, including a NUL terminator, but we + * don't store that '\0' character. + */ + err = fscrypt_prepare_symlink(dir, symname, name_len, max_len + 1, + &disk_link); + if (err) + return err; inode = new_inode(dir->i_sb); if (!inode) @@ -9432,8 +9467,8 @@ static int btrfs_symlink(struct mnt_idmap *idmap, struct inode *dir, inode->i_op = &btrfs_symlink_inode_operations; inode_nohighmem(inode); inode->i_mapping->a_ops = &btrfs_aops; - btrfs_i_size_write(BTRFS_I(inode), name_len); - inode_set_bytes(inode, name_len); + btrfs_i_size_write(BTRFS_I(inode), disk_link.len - 1); + inode_set_bytes(inode, disk_link.len - 1); new_inode_args.inode = inode; err = btrfs_new_inode_prepare(&new_inode_args, &trans_num_items); @@ -9460,10 +9495,23 @@ static int btrfs_symlink(struct mnt_idmap *idmap, struct inode *dir, inode = NULL; goto out; } + + if (IS_ENCRYPTED(inode)) { + err = fscrypt_encrypt_symlink(inode, symname, name_len, + &disk_link); + if (err) { + btrfs_abort_transaction(trans, err); + btrfs_free_path(path); + discard_new_inode(inode); + inode = NULL; + goto out; + } + } + key.objectid = btrfs_ino(BTRFS_I(inode)); key.offset = 0; key.type = BTRFS_EXTENT_DATA_KEY; - datasize = btrfs_file_extent_calc_inline_size(name_len); + datasize = btrfs_file_extent_calc_inline_size(disk_link.len - 1); err = btrfs_insert_empty_item(trans, root, path, &key, datasize); if (err) { @@ -9482,10 +9530,10 @@ static int btrfs_symlink(struct mnt_idmap *idmap, struct inode *dir, btrfs_set_file_extent_encryption(leaf, ei, 0); btrfs_set_file_extent_compression(leaf, ei, 0); btrfs_set_file_extent_other_encoding(leaf, ei, 0); - btrfs_set_file_extent_ram_bytes(leaf, ei, name_len); + btrfs_set_file_extent_ram_bytes(leaf, ei, disk_link.len - 1); ptr = btrfs_file_extent_inline_start(ei); - write_extent_buffer(leaf, symname, ptr, name_len); + write_extent_buffer(leaf, disk_link.name, ptr, disk_link.len - 1); btrfs_mark_buffer_dirty(trans, leaf); btrfs_free_path(path); @@ -9502,6 +9550,29 @@ static int btrfs_symlink(struct mnt_idmap *idmap, struct inode *dir, return err; } +static const char *btrfs_get_link(struct dentry *dentry, struct inode *inode, + struct delayed_call *done) +{ + struct page *cpage; + const char *paddr; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); + + if (!IS_ENCRYPTED(inode)) + return page_get_link(dentry, inode, done); + + if (!dentry) + return ERR_PTR(-ECHILD); + + cpage = read_mapping_page(inode->i_mapping, 0, NULL); + if (IS_ERR(cpage)) + return ERR_CAST(cpage); + + paddr = fscrypt_get_symlink(inode, page_address(cpage), + BTRFS_MAX_INLINE_DATA_SIZE(fs_info), done); + put_page(cpage); + return paddr; +} + static struct btrfs_trans_handle *insert_prealloc_file_extent( struct btrfs_trans_handle *trans_in, struct btrfs_inode *inode, @@ -10983,7 +11054,7 @@ static const struct inode_operations btrfs_special_inode_operations = { .update_time = btrfs_update_time, }; static const struct inode_operations btrfs_symlink_inode_operations = { - .get_link = page_get_link, + .get_link = btrfs_get_link, .getattr = btrfs_getattr, .setattr = btrfs_setattr, .permission = btrfs_permission, @@ -10993,4 +11064,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = { const struct dentry_operations btrfs_dentry_operations = { .d_delete = btrfs_dentry_delete, +#ifdef CONFIG_FS_ENCRYPTION + .d_revalidate = fscrypt_d_revalidate, +#endif }; diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 63dcb7f7b42c..4b92d6ffde5e 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -50,6 +50,7 @@ #include "tests/btrfs-tests.h" #include "block-group.h" #include "discard.h" +#include "fscrypt.h" #include "qgroup.h" #include "raid56.h" #include "fs.h" @@ -929,6 +930,7 @@ static int btrfs_fill_super(struct super_block *sb, sb->s_vop = &btrfs_verityops; #endif sb->s_xattr = btrfs_xattr_handlers; + fscrypt_set_ops(sb, &btrfs_fscrypt_ops); sb->s_time_gran = 1; sb->s_iflags |= SB_I_CGROUPWB; From patchwork Fri Dec 1 22:11:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476500 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="ZM+UGWoy" Received: from mail-yw1-x1144.google.com (mail-yw1-x1144.google.com [IPv6:2607:f8b0:4864:20::1144]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E48310DB for ; Fri, 1 Dec 2023 14:12:12 -0800 (PST) Received: by mail-yw1-x1144.google.com with SMTP id 00721157ae682-5d3efc071e2so15433407b3.0 for ; Fri, 01 Dec 2023 14:12:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468731; x=1702073531; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=W0tWS38XcnmMR7VGAy0uVnMkYJ45EykUF4R6j1t1BIQ=; b=ZM+UGWoyA9aTDt6SGxzSez3f8+sgBYQBVomLEWfcalRIiSQgKEZ0Bya4i7/qewp3Bh XYo3xfAJWLyCC4MiN9GH492OHzjDTXecueFgtBntsZ3U8EDr1hJ/P5WifRH2KB0azNbl gT+S5PsFnCI5RIBZ6O9SUHNRNKAASqqpGfIos7FB6/dFs0azENE4v9+E8ekizWFQ3UTw A0GNv9/bJpO1+Fjxolzy17Uj1Y11hi17DH/nSXRcg7Jwv4wxGG103czc+TAjl1Mca/C6 YQ4NedcgHolujm3L27GYoucXUWsWAg4uHRKaU9DrE6jvPcVlCd475HIch5Nqu3TWGeTe 1NYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468731; x=1702073531; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=W0tWS38XcnmMR7VGAy0uVnMkYJ45EykUF4R6j1t1BIQ=; b=d9UUOBIir17Jhkv13Gmmkc22jYUSwU7YTGUPukRHbMYGwER+CG+6yLNYJIY/Ejgzte RUlvTbz0tFxSF6PQwIx9uyXJESMoW2GwruGvED0WVhiEQeOO/41hYu6mWP7cSWQXd2QM LayykacUtWYxHa9PM+Z5ZO89EpKj/cqLPQjEAiTp+0DwAJmQ2AjMyOuDbwxvmriD8sBs 4Ex1ZQ4t4jKfPNVbq/PVtm69NSajrUKta1ZEUEBqHlgqOjPIx/kNsvIPe+4m66twn1nW Zr/UK2x56gMym/TNrQKImNn0r4/Q6R7na4vH8w7AvG/cQV+ATTvpXH1pc4Nh7E/UgfDj YIjQ== X-Gm-Message-State: AOJu0YzvNz3SyaLL9eeevLO6iJ0l4rEREHWXdXWIA/6JVs200QU5jqmX 2x3dxM1PoOPmkaRzoeA9q+PNG3MEhmrQ78GJt7RJJJHc X-Google-Smtp-Source: AGHT+IHwfEvNLPEbU2jtltEpM9fV9zJKCYHiV7gxgUXId0lavqCc6LNACBO7YLgZ1SzpKXad81RQQA== X-Received: by 2002:a81:af44:0:b0:5d7:1941:2c1f with SMTP id x4-20020a81af44000000b005d719412c1fmr173828ywj.76.1701468731203; Fri, 01 Dec 2023 14:12:11 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id g187-20020a0dddc4000000b005d3555d7b9fsm1333347ywe.44.2023.12.01.14.12.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:10 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Omar Sandoval , Sweet Tea Dorminy Subject: [PATCH v4 12/46] btrfs: add inode encryption contexts Date: Fri, 1 Dec 2023 17:11:09 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Omar Sandoval In order to store encryption information for directories, symlinks, etc., fscrypt stores a context item with each encrypted non-regular inode. fscrypt provides an arbitrary blob for the filesystem to store, and it does not clearly fit into an existing structure, so this goes in a new item type. Signed-off-by: Omar Sandoval Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/fscrypt.c | 117 ++++++++++++++++++++++++++++++++ fs/btrfs/fscrypt.h | 2 + fs/btrfs/inode.c | 19 ++++++ fs/btrfs/ioctl.c | 8 ++- include/uapi/linux/btrfs_tree.h | 10 +++ 5 files changed, 154 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/fscrypt.c b/fs/btrfs/fscrypt.c index 48ab99dfe48d..0e4011d6b1cd 100644 --- a/fs/btrfs/fscrypt.c +++ b/fs/btrfs/fscrypt.c @@ -1,7 +1,124 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include "ctree.h" +#include "accessors.h" +#include "btrfs_inode.h" +#include "disk-io.h" +#include "fs.h" #include "fscrypt.h" +#include "ioctl.h" +#include "messages.h" +#include "transaction.h" +#include "xattr.h" + +static int btrfs_fscrypt_get_context(struct inode *inode, void *ctx, size_t len) +{ + struct btrfs_key key = { + .objectid = btrfs_ino(BTRFS_I(inode)), + .type = BTRFS_FSCRYPT_CTX_ITEM_KEY, + .offset = 0, + }; + struct btrfs_path *path; + struct extent_buffer *leaf; + unsigned long ptr; + int ret; + + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + + ret = btrfs_search_slot(NULL, BTRFS_I(inode)->root, &key, path, 0, 0); + if (ret) { + len = -ENOENT; + goto out; + } + + leaf = path->nodes[0]; + ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); + /* fscrypt provides max context length, but it could be less */ + len = min_t(size_t, len, btrfs_item_size(leaf, path->slots[0])); + read_extent_buffer(leaf, ctx, ptr, len); + +out: + btrfs_free_path(path); + return len; +} + +static int btrfs_fscrypt_set_context(struct inode *inode, const void *ctx, + size_t len, void *fs_data) +{ + struct btrfs_trans_handle *trans = fs_data; + struct btrfs_key key = { + .objectid = btrfs_ino(BTRFS_I(inode)), + .type = BTRFS_FSCRYPT_CTX_ITEM_KEY, + .offset = 0, + }; + struct btrfs_path *path = NULL; + struct extent_buffer *leaf; + unsigned long ptr; + int ret; + + if (!trans) + trans = btrfs_start_transaction(BTRFS_I(inode)->root, 2); + if (IS_ERR(trans)) + return PTR_ERR(trans); + + path = btrfs_alloc_path(); + if (!path) { + ret = -ENOMEM; + goto out_err; + } + + ret = btrfs_search_slot(trans, BTRFS_I(inode)->root, &key, path, 0, 1); + if (ret < 0) + goto out_err; + + if (ret > 0) { + btrfs_release_path(path); + ret = btrfs_insert_empty_item(trans, BTRFS_I(inode)->root, path, &key, len); + if (ret) + goto out_err; + } + + leaf = path->nodes[0]; + ptr = btrfs_item_ptr_offset(leaf, path->slots[0]); + + len = min_t(size_t, len, btrfs_item_size(leaf, path->slots[0])); + write_extent_buffer(leaf, ctx, ptr, len); + btrfs_mark_buffer_dirty(trans, leaf); + btrfs_release_path(path); + + if (fs_data) + return ret; + + BTRFS_I(inode)->flags |= BTRFS_INODE_ENCRYPT; + btrfs_sync_inode_flags_to_i_flags(inode); + inode_inc_iversion(inode); + inode_set_ctime_current(inode); + ret = btrfs_update_inode(trans, BTRFS_I(inode)); + if (ret) + goto out_abort; + btrfs_free_path(path); + btrfs_end_transaction(trans); + return 0; +out_abort: + btrfs_abort_transaction(trans, ret); +out_err: + if (!fs_data) + btrfs_end_transaction(trans); + btrfs_free_path(path); + return ret; +} + +static bool btrfs_fscrypt_empty_dir(struct inode *inode) +{ + return inode->i_size == BTRFS_EMPTY_DIR_SIZE; +} const struct fscrypt_operations btrfs_fscrypt_ops = { + .get_context = btrfs_fscrypt_get_context, + .set_context = btrfs_fscrypt_set_context, + .empty_dir = btrfs_fscrypt_empty_dir, }; diff --git a/fs/btrfs/fscrypt.h b/fs/btrfs/fscrypt.h index 7f4e6888bd43..80adb7e56826 100644 --- a/fs/btrfs/fscrypt.h +++ b/fs/btrfs/fscrypt.h @@ -5,6 +5,8 @@ #include +#include "fs.h" + extern const struct fscrypt_operations btrfs_fscrypt_ops; #endif /* BTRFS_FSCRYPT_H */ diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d58003eb447d..cc52af10a520 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -62,6 +62,7 @@ #include "defrag.h" #include "dir-item.h" #include "file-item.h" +#include "fscrypt.h" #include "uuid-tree.h" #include "ioctl.h" #include "file.h" @@ -6097,6 +6098,9 @@ int btrfs_new_inode_prepare(struct btrfs_new_inode_args *args, struct inode *inode = args->inode; int ret; + if (fscrypt_is_nokey_name(args->dentry)) + return -ENOKEY; + if (!args->orphan) { ret = fscrypt_setup_filename(dir, &args->dentry->d_name, 0, &args->fname); @@ -6132,6 +6136,9 @@ int btrfs_new_inode_prepare(struct btrfs_new_inode_args *args, if (dir->i_security) (*trans_num_items)++; #endif + /* 1 to add fscrypt item */ + if (args->encrypt) + (*trans_num_items)++; if (args->orphan) { /* 1 to add orphan item */ (*trans_num_items)++; @@ -6317,6 +6324,11 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans, BTRFS_I(inode)->i_otime_sec = ts.tv_sec; BTRFS_I(inode)->i_otime_nsec = ts.tv_nsec; + if (args->encrypt) { + BTRFS_I(inode)->flags |= BTRFS_INODE_ENCRYPT; + btrfs_sync_inode_flags_to_i_flags(inode); + } + /* * We're going to fill the inode item now, so at this point the inode * must be fully initialized. @@ -6391,6 +6403,13 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans, goto discard; } } + if (args->encrypt) { + ret = fscrypt_set_context(inode, trans); + if (ret) { + btrfs_abort_transaction(trans, ret); + goto discard; + } + } inode_tree_add(BTRFS_I(inode)); diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index dfe257e1845b..6acf898f693e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -156,6 +156,8 @@ static unsigned int btrfs_inode_flags_to_fsflags(struct btrfs_inode *binode) iflags |= FS_DIRSYNC_FL; if (flags & BTRFS_INODE_NODATACOW) iflags |= FS_NOCOW_FL; + if (flags & BTRFS_INODE_ENCRYPT) + iflags |= FS_ENCRYPT_FL; if (ro_flags & BTRFS_INODE_RO_VERITY) iflags |= FS_VERITY_FL; @@ -185,12 +187,14 @@ void btrfs_sync_inode_flags_to_i_flags(struct inode *inode) new_fl |= S_NOATIME; if (binode->flags & BTRFS_INODE_DIRSYNC) new_fl |= S_DIRSYNC; + if (binode->flags & BTRFS_INODE_ENCRYPT) + new_fl |= S_ENCRYPTED; if (binode->ro_flags & BTRFS_INODE_RO_VERITY) new_fl |= S_VERITY; set_mask_bits(&inode->i_flags, S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME | S_DIRSYNC | - S_VERITY, new_fl); + S_VERITY | S_ENCRYPTED, new_fl); } /* @@ -203,7 +207,7 @@ static int check_fsflags(unsigned int old_flags, unsigned int flags) FS_NOATIME_FL | FS_NODUMP_FL | \ FS_SYNC_FL | FS_DIRSYNC_FL | \ FS_NOCOMP_FL | FS_COMPR_FL | - FS_NOCOW_FL)) + FS_NOCOW_FL | FS_ENCRYPT_FL)) return -EOPNOTSUPP; /* COMPR and NOCOMP on new/old are valid */ diff --git a/include/uapi/linux/btrfs_tree.h b/include/uapi/linux/btrfs_tree.h index d24e8e121507..08f561da33cd 100644 --- a/include/uapi/linux/btrfs_tree.h +++ b/include/uapi/linux/btrfs_tree.h @@ -164,6 +164,8 @@ #define BTRFS_VERITY_DESC_ITEM_KEY 36 #define BTRFS_VERITY_MERKLE_ITEM_KEY 37 +#define BTRFS_FSCRYPT_CTX_ITEM_KEY 41 + #define BTRFS_ORPHAN_ITEM_KEY 48 /* reserve 2-15 close to the inode for later flexibility */ @@ -424,6 +426,7 @@ static inline __u8 btrfs_dir_flags_to_ftype(__u8 flags) #define BTRFS_INODE_NOATIME (1U << 9) #define BTRFS_INODE_DIRSYNC (1U << 10) #define BTRFS_INODE_COMPRESS (1U << 11) +#define BTRFS_INODE_ENCRYPT (1U << 12) #define BTRFS_INODE_ROOT_ITEM_INIT (1U << 31) @@ -440,6 +443,7 @@ static inline __u8 btrfs_dir_flags_to_ftype(__u8 flags) BTRFS_INODE_NOATIME | \ BTRFS_INODE_DIRSYNC | \ BTRFS_INODE_COMPRESS | \ + BTRFS_INODE_ENCRYPT | \ BTRFS_INODE_ROOT_ITEM_INIT) #define BTRFS_INODE_RO_VERITY (1U << 0) @@ -1069,6 +1073,12 @@ enum { BTRFS_NR_FILE_EXTENT_TYPES = 3, }; +enum { + BTRFS_ENCRYPTION_NONE, + BTRFS_ENCRYPTION_FSCRYPT, + BTRFS_NR_ENCRYPTION_TYPES, +}; + struct btrfs_file_extent_item { /* * transaction id that created this extent From patchwork Fri Dec 1 22:11:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476501 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="iRWsKR0B" Received: from mail-yb1-xb31.google.com (mail-yb1-xb31.google.com [IPv6:2607:f8b0:4864:20::b31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 66AE710D0 for ; Fri, 1 Dec 2023 14:12:13 -0800 (PST) Received: by mail-yb1-xb31.google.com with SMTP id 3f1490d57ef6-dae7cc31151so987486276.3 for ; Fri, 01 Dec 2023 14:12:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468732; x=1702073532; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=EVbb9Vde1QaPim8O9By/4uOtcs6MazfrO+ctrzAYQaM=; b=iRWsKR0BRtLF42T/03oB3nUmUJewNrHTm2Fo08LZe+QdfNLdHwp7/BlhZcgKloEnU8 yPxn0fVkm3zMnuTe4b9CRQNImGXRE1FuoCHZY3c6ci107MCB6ImkLhki1OnDfcyHxFqY gb9LvWijXSMaLqKkbt3moSJjZ7gRKTb1HUk1W6BK/AwkJBSZvWUFuvzpvD4px8DdAUFm d3pI6eP7hSlE6Cdfrvrwz46X2iKo0+2zg8OhiFtwwEl3E2vF5xUAQdJglx5P3+LwNCNU ooFaLMY0hgF1HTOdwM+EitSP3pgHQ/Ai19fBREbxivsJ/Srviwx6ZgoMjIWT/PQZLYtX uVVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468732; x=1702073532; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=EVbb9Vde1QaPim8O9By/4uOtcs6MazfrO+ctrzAYQaM=; b=PAkH2tZcJCHDwFzz1ZEWqOuR7HNX9DSfWlhQEdCVTu4L2OX8ZMC8oKSzfi+OYrD1/X wctn4CIDucuFjAKd1ZJ0kE4tGemYWtYlEGXTIsVHGzpAELtKjZ6ihfc3Vy5OchlB9LaX DFJy0wKweDK8bycjb5ME33kyb2R8Nsg5964phChs9j29bkuSUQ5w9Wvfo1tjxWTpRcr7 kKERDHk8vo3rLeDijPtrzU7w0/qnoDIgFOfdAqH6HgB43b4Aycyp/kCWYmYU/Mru+kWn 4IwGXrVurDd0+xM/hvtECwcin6aIsE8kbm0Wvvqh9w4cM2mDcGnoidrjGt7FxcXlgxTK RnVg== X-Gm-Message-State: AOJu0YxqgQOXExH/VW6OpvKQZeGyu8Rpjx2Mztg6fu/cWDeBfuWdM+ZR 4mQ8bZPE50F65y0ozQ0TuGv+fuH6TMfihfV14ngWHg== X-Google-Smtp-Source: AGHT+IEUXLDvWblHxjdvikmsg5VbVCLTqQIJ7qFAdJhdH3YM5s8f+qZUOtghC28xBsykapqU1GZHGA== X-Received: by 2002:a81:ac42:0:b0:5d7:1940:f3dd with SMTP id z2-20020a81ac42000000b005d71940f3ddmr152061ywj.69.1701468732326; Fri, 01 Dec 2023 14:12:12 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id u204-20020a8160d5000000b005d29344e625sm1384159ywb.114.2023.12.01.14.12.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:11 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Omar Sandoval , Sweet Tea Dorminy Subject: [PATCH v4 13/46] btrfs: add new FEATURE_INCOMPAT_ENCRYPT flag Date: Fri, 1 Dec 2023 17:11:10 -0500 Message-ID: <7e42047ce1c87e4181a65347362c7860d5fd05ed.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Omar Sandoval As encrypted files will be incompatible with older filesystem versions, new filesystems should be created with an incompat flag for fscrypt, which will gate access to the encryption ioctls. Signed-off-by: Omar Sandoval Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/fs.h | 3 ++- fs/btrfs/super.c | 5 +++++ fs/btrfs/sysfs.c | 6 ++++++ include/uapi/linux/btrfs.h | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h index f8bb73d6ab68..1340e71d026c 100644 --- a/fs/btrfs/fs.h +++ b/fs/btrfs/fs.h @@ -232,7 +232,8 @@ enum { #define BTRFS_FEATURE_INCOMPAT_SUPP \ (BTRFS_FEATURE_INCOMPAT_SUPP_STABLE | \ BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE | \ - BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2) + BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2 | \ + BTRFS_FEATURE_INCOMPAT_ENCRYPT) #else diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 4b92d6ffde5e..39a338e92115 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -2445,6 +2445,11 @@ static int __init btrfs_print_mod_info(void) ", fsverity=yes" #else ", fsverity=no" +#endif +#ifdef CONFIG_FS_ENCRYPTION + ", fscrypt=yes" +#else + ", fscrypt=no" #endif ; pr_info("Btrfs loaded%s\n", options); diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index e6b51fb3ddc1..4ece703d9d5f 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -304,6 +304,9 @@ BTRFS_FEAT_ATTR_INCOMPAT(raid_stripe_tree, RAID_STRIPE_TREE); #ifdef CONFIG_FS_VERITY BTRFS_FEAT_ATTR_COMPAT_RO(verity, VERITY); #endif +#ifdef CONFIG_FS_ENCRYPTION +BTRFS_FEAT_ATTR_INCOMPAT(encryption, ENCRYPT); +#endif /* CONFIG_FS_ENCRYPTION */ /* * Features which depend on feature bits and may differ between each fs. @@ -336,6 +339,9 @@ static struct attribute *btrfs_supported_feature_attrs[] = { #ifdef CONFIG_FS_VERITY BTRFS_FEAT_ATTR_PTR(verity), #endif +#ifdef CONFIG_FS_ENCRYPTION + BTRFS_FEAT_ATTR_PTR(encryption), +#endif /* CONFIG_FS_ENCRYPTION */ NULL }; diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index 7c29d82db9ee..6a0f4c0e4096 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -334,6 +334,7 @@ struct btrfs_ioctl_fs_info_args { #define BTRFS_FEATURE_INCOMPAT_ZONED (1ULL << 12) #define BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2 (1ULL << 13) #define BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE (1ULL << 14) +#define BTRFS_FEATURE_INCOMPAT_ENCRYPT (1ULL << 15) #define BTRFS_FEATURE_INCOMPAT_SIMPLE_QUOTA (1ULL << 16) struct btrfs_ioctl_feature_flags { From patchwork Fri Dec 1 22:11:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476502 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="ULVDIzQn" Received: from mail-yb1-xb44.google.com (mail-yb1-xb44.google.com [IPv6:2607:f8b0:4864:20::b44]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C9BAB10EF for ; Fri, 1 Dec 2023 14:12:14 -0800 (PST) Received: by mail-yb1-xb44.google.com with SMTP id 3f1490d57ef6-db510605572so1015924276.0 for ; Fri, 01 Dec 2023 14:12:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468734; x=1702073534; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jtjXqMNlaBmyOOL3U1MQOg+Vp+iCizcCPJxYmixAVVo=; b=ULVDIzQnm1xISx4qtYwUFqFRvzy/Jc0l5nYH8TsJ9GUZ/vty3mSrLe49vtUr73O+4t kB3z5oyYTNudokJDn3SPalpfI4wY+IObZa0nq7hWkwlVoVRlKEzQ8Ttp8MHXxwIWxNYd EyRwvnXRA5yhsz6luvfPkbT67WdgBGAxyCBIcVdntS1s6OBRA67DU27Km2j0RIgUulUY jW7qRlk6QOvXXV5MbwvwFen2jRmCegyq+BKRb05Z1lCkki/88Xv6pdVyL3hKWyXwi43o EeMPGAwp30aDUPAeNtb9/GSO0udUJMpI6LyxJ+5tyQq3Vsvrt8Vlkyed3dnzajQyOLDt c3Xg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468734; x=1702073534; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jtjXqMNlaBmyOOL3U1MQOg+Vp+iCizcCPJxYmixAVVo=; b=c/Uk3cpGVMn+yCmjp36mmLd/VwB25B9Kw3XXmSfrEd5q1OKdbAfrC9DaNz28wEU/O+ P3QfFDRdCKsrBMcrrjbLN/GADOS102ob8E4WsFrpW5cSWHLSB98HVQwqRpO66ibj2zqE aIIXm38Z16e2/sPpK+6VPjpjCjWYH7ewIpFAkB2FGBlgU0UHoN/4cCHvrfLWbG7/SgJU iEC71218wzbjccImlHovvHlWF01bmuwcbX9XLjEMWKfDEwvd0vY1XarZ/kxyUzeeScUo OvyNmwqv2iqYNZfhWEiD2mmrpWknmPbbd2VH4q4Nnygr54tmangXanfzp92O7Iy2K3VY vkwA== X-Gm-Message-State: AOJu0YycBlkE65xtWNktaTHCSP37Oou8zG9hQbODYublfix8GIWEPmqs oYndckUO41BOgwuJhybWVunrKdsdm0no91USnxHtLE7s X-Google-Smtp-Source: AGHT+IEZicVEWZ5ULFuSVCPD6sjRbm9yy+a3Ndhr8ZRjYiBZp0rEy5FDTsRc+GzCDmW5SeDAye6tKQ== X-Received: by 2002:a25:8a91:0:b0:db4:b740:1cb9 with SMTP id h17-20020a258a91000000b00db4b7401cb9mr17766698ybl.16.1701468733585; Fri, 01 Dec 2023 14:12:13 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id x202-20020a25ced3000000b00daf198ef6fbsm640908ybe.21.2023.12.01.14.12.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:13 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Omar Sandoval , Sweet Tea Dorminy Subject: [PATCH v4 14/46] btrfs: adapt readdir for encrypted and nokey names Date: Fri, 1 Dec 2023 17:11:11 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Omar Sandoval Deleting an encrypted file must always be permitted, even if the user does not have the appropriate key. Therefore, for listing an encrypted directory, so-called 'nokey' names are provided, and these nokey names must be sufficient to look up and delete the appropriate encrypted files. See 'struct fscrypt_nokey_name' for more information on the format of these names. The first part of supporting nokey names is allowing lookups by nokey name. Only a few entry points need to support these: deleting a directory, file, or subvolume -- each of these call fscrypt_setup_filename() with a '1' argument, indicating that the key is not required and therefore a nokey name may be provided. If a nokey name is provided, the fscrypt_name returned by fscrypt_setup_filename() will not have its disk_name field populated, but will have various other fields set. This change alters the relevant codepaths to pass a complete fscrypt_name anywhere that it might contain a nokey name. When it does contain a nokey name, the first time the name is successfully matched to a stored name populates the disk name field of the fscrypt_name, allowing the caller to use the normal disk name codepaths afterward. Otherwise, the matching functionality is in close analogue to the function fscrypt_match_name(). Functions where most callers are providing a fscrypt_str are duplicated and adapted for a fscrypt_name, and functions where most callers are providing a fscrypt_name are changed to so require at all callsites. Signed-off-by: Omar Sandoval Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/btrfs_inode.h | 2 +- fs/btrfs/delayed-inode.c | 29 ++++++- fs/btrfs/delayed-inode.h | 6 +- fs/btrfs/dir-item.c | 77 ++++++++++++++++--- fs/btrfs/dir-item.h | 11 ++- fs/btrfs/extent_io.c | 38 ++++++++++ fs/btrfs/extent_io.h | 3 + fs/btrfs/fscrypt.c | 34 +++++++++ fs/btrfs/fscrypt.h | 19 +++++ fs/btrfs/inode.c | 158 ++++++++++++++++++++++++++------------- fs/btrfs/root-tree.c | 8 +- fs/btrfs/root-tree.h | 2 +- fs/btrfs/tree-log.c | 3 +- 13 files changed, 317 insertions(+), 73 deletions(-) diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 048eb211b54a..a6a5b3146777 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -430,7 +430,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry); int btrfs_set_inode_index(struct btrfs_inode *dir, u64 *index); int btrfs_unlink_inode(struct btrfs_trans_handle *trans, struct btrfs_inode *dir, struct btrfs_inode *inode, - const struct fscrypt_str *name); + struct fscrypt_name *name); int btrfs_add_link(struct btrfs_trans_handle *trans, struct btrfs_inode *parent_inode, struct btrfs_inode *inode, const struct fscrypt_str *name, int add_backref, u64 index); diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 91159dd7355b..0c36a0e06c12 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -1765,7 +1765,9 @@ int btrfs_should_delete_dir_index(struct list_head *del_list, /* * Read dir info stored in the delayed tree. */ -int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, +int btrfs_readdir_delayed_dir_index(struct inode *inode, + struct fscrypt_str *fstr, + struct dir_context *ctx, struct list_head *ins_list) { struct btrfs_dir_item *di; @@ -1775,6 +1777,7 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, int name_len; int over = 0; unsigned char d_type; + size_t fstr_len = fstr->len; /* * Changing the data of the delayed item is impossible. So @@ -1799,8 +1802,28 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, d_type = fs_ftype_to_dtype(btrfs_dir_flags_to_ftype(di->type)); btrfs_disk_key_to_cpu(&location, &di->location); - over = !dir_emit(ctx, name, name_len, - location.objectid, d_type); + if (di->type & BTRFS_FT_ENCRYPTED) { + int ret; + struct fscrypt_str iname = FSTR_INIT(name, name_len); + + fstr->len = fstr_len; + /* + * The hash is only used when the encryption key is not + * available. But if we have delayed insertions, then we + * must have the encryption key available or we wouldn't + * have been able to create entries in the directory. + * So, we don't calculate the hash. + */ + ret = fscrypt_fname_disk_to_usr(inode, 0, 0, &iname, + fstr); + if (ret) + return ret; + over = !dir_emit(ctx, fstr->name, fstr->len, + location.objectid, d_type); + } else { + over = !dir_emit(ctx, name, name_len, location.objectid, + d_type); + } if (refcount_dec_and_test(&curr->refs)) kfree(curr); diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index 5cceb31bbd16..d369f6997df7 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -16,6 +16,8 @@ #include #include "ctree.h" +struct fscrypt_str; + enum btrfs_delayed_item_type { BTRFS_DELAYED_INSERTION_ITEM, BTRFS_DELAYED_DELETION_ITEM @@ -155,7 +157,9 @@ void btrfs_readdir_put_delayed_items(struct inode *inode, struct list_head *del_list); int btrfs_should_delete_dir_index(struct list_head *del_list, u64 index); -int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, +int btrfs_readdir_delayed_dir_index(struct inode *inode, + struct fscrypt_str *fstr, + struct dir_context *ctx, struct list_head *ins_list); /* Used during directory logging. */ diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 9c07d5c3e5ad..a64cfddff7f0 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c @@ -6,6 +6,7 @@ #include "messages.h" #include "ctree.h" #include "disk-io.h" +#include "fscrypt.h" #include "transaction.h" #include "accessors.h" #include "dir-item.h" @@ -230,6 +231,47 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, return di; } +/* + * Lookup for a directory item by fscrypt_name. + * + * @trans: The transaction handle to use. + * @root: The root of the target tree. + * @path: Path to use for the search. + * @dir: The inode number (objectid) of the directory. + * @name: The fscrypt_name associated to the directory entry + * @mod: Used to indicate if the tree search is meant for a read only + * lookup or for a deletion lookup, so its value should be 0 or + * -1, respectively. + * + * Returns: NULL if the dir item does not exists, an error pointer if an error + * happened, or a pointer to a dir item if a dir item exists for the given name. + */ +struct btrfs_dir_item *btrfs_lookup_dir_item_fname(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, u64 dir, + struct fscrypt_name *name, int mod) +{ + struct btrfs_key key; + struct btrfs_dir_item *di = NULL; + int ret = 0; + + key.objectid = dir; + key.type = BTRFS_DIR_ITEM_KEY; + key.offset = btrfs_name_hash(name->disk_name.name, name->disk_name.len); + /* XXX get the right hash for no-key names */ + + ret = btrfs_search_slot(trans, root, &key, path, mod, -mod); + if (ret == 0) + di = btrfs_match_dir_item_fname(root->fs_info, path, name); + + if (ret == -ENOENT || (di && IS_ERR(di) && PTR_ERR(di) == -ENOENT)) + return NULL; + if (ret < 0) + di = ERR_PTR(ret); + + return di; +} + int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir, const struct fscrypt_str *name) { @@ -287,9 +329,9 @@ int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir, } /* - * Lookup for a directory index item by name and index number. + * Lookup for a directory index item by fscrypt_name and index number. * - * @trans: The transaction handle to use. Can be NULL if @mod is 0. + * @trans: The transaction handle to use. * @root: The root of the target tree. * @path: Path to use for the search. * @dir: The inode number (objectid) of the directory. @@ -327,7 +369,7 @@ btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, struct btrfs_dir_item * btrfs_search_dir_index_item(struct btrfs_root *root, struct btrfs_path *path, - u64 dirid, const struct fscrypt_str *name) + u64 dirid, struct fscrypt_name *name) { struct btrfs_dir_item *di; struct btrfs_key key; @@ -340,9 +382,7 @@ btrfs_search_dir_index_item(struct btrfs_root *root, struct btrfs_path *path, btrfs_for_each_slot(root, &key, &key, path, ret) { if (key.objectid != dirid || key.type != BTRFS_DIR_INDEX_KEY) break; - - di = btrfs_match_dir_item_name(root->fs_info, path, - name->name, name->len); + di = btrfs_match_dir_item_fname(root->fs_info, path, name); if (di) return di; } @@ -378,9 +418,9 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, * this walks through all the entries in a dir item and finds one * for a specific name. */ -struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_fs_info *fs_info, - struct btrfs_path *path, - const char *name, int name_len) +struct btrfs_dir_item *btrfs_match_dir_item_fname(struct btrfs_fs_info *fs_info, + struct btrfs_path *path, + struct fscrypt_name *name) { struct btrfs_dir_item *dir_item; unsigned long name_ptr; @@ -399,8 +439,8 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_fs_info *fs_info, btrfs_dir_data_len(leaf, dir_item); name_ptr = (unsigned long)(dir_item + 1); - if (btrfs_dir_name_len(leaf, dir_item) == name_len && - memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0) + if (btrfs_fscrypt_match_name(name, leaf, name_ptr, + btrfs_dir_name_len(leaf, dir_item))) return dir_item; cur += this_len; @@ -410,6 +450,21 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_fs_info *fs_info, return NULL; } +/* + * helper function to look at the directory item pointed to by 'path' + * this walks through all the entries in a dir item and finds one + * for a specific name. + */ +struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_fs_info *fs_info, + struct btrfs_path *path, + const char *name, int name_len) +{ + struct fscrypt_name fname = { + .disk_name = FSTR_INIT((char *) name, name_len) + }; + return btrfs_match_dir_item_fname(fs_info, path, &fname); +} + /* * given a pointer into a directory item, delete it. This * handles items that have more than one entry in them. diff --git a/fs/btrfs/dir-item.h b/fs/btrfs/dir-item.h index e40a226373d7..1d6ab8c3b879 100644 --- a/fs/btrfs/dir-item.h +++ b/fs/btrfs/dir-item.h @@ -6,6 +6,7 @@ #include struct fscrypt_str; +struct fscrypt_name; int btrfs_check_dir_item_collision(struct btrfs_root *root, u64 dir, const struct fscrypt_str *name); @@ -16,6 +17,11 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, u64 dir, const struct fscrypt_str *name, int mod); +struct btrfs_dir_item *btrfs_lookup_dir_item_fname( + struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, u64 dir, + struct fscrypt_name *name, int mod); struct btrfs_dir_item *btrfs_lookup_dir_index_item( struct btrfs_trans_handle *trans, struct btrfs_root *root, @@ -23,7 +29,7 @@ struct btrfs_dir_item *btrfs_lookup_dir_index_item( u64 index, const struct fscrypt_str *name, int mod); struct btrfs_dir_item *btrfs_search_dir_index_item(struct btrfs_root *root, struct btrfs_path *path, u64 dirid, - const struct fscrypt_str *name); + struct fscrypt_name *name); int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, @@ -42,6 +48,9 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_fs_info *fs_info, struct btrfs_path *path, const char *name, int name_len); +struct btrfs_dir_item *btrfs_match_dir_item_fname(struct btrfs_fs_info *fs_info, + struct btrfs_path *path, + struct fscrypt_name *name); static inline u64 btrfs_name_hash(const char *name, int len) { diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index f91a688abd3b..42544c0d9ee1 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -4159,6 +4159,44 @@ static void assert_eb_page_uptodate(const struct extent_buffer *eb, } } +/* Take a sha256 of a portion of an extent buffer. */ +void extent_buffer_sha256(const struct extent_buffer *eb, + unsigned long start, + unsigned long len, u8 *out) +{ + size_t cur; + size_t offset; + struct page *page; + char *kaddr; + unsigned long i = get_eb_page_index(start); + struct sha256_state sctx; + + if (check_eb_range(eb, start, len)) + return; + + offset = get_eb_offset_in_page(eb, start); + + /* + * TODO: This should maybe be using the crypto API, not the fallback, + * but fscrypt uses the fallback and this is only used in emulation of + * fscrypt's buffer sha256 method. + */ + sha256_init(&sctx); + while (len > 0) { + page = eb->pages[i]; + assert_eb_page_uptodate(eb, page); + + cur = min(len, PAGE_SIZE - offset); + kaddr = page_address(page); + sha256_update(&sctx, (u8 *)(kaddr + offset), cur); + + len -= cur; + offset = 0; + i++; + } + sha256_final(&sctx, out); +} + static void __write_extent_buffer(const struct extent_buffer *eb, const void *srcv, unsigned long start, unsigned long len, bool use_memmove) diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 785b0d07d741..7d35e7344386 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -244,6 +244,9 @@ static inline int extent_buffer_uptodate(const struct extent_buffer *eb) int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv, unsigned long start, unsigned long len); +void extent_buffer_sha256(const struct extent_buffer *eb, + unsigned long start, + unsigned long len, u8 *out); void read_extent_buffer(const struct extent_buffer *eb, void *dst, unsigned long start, unsigned long len); diff --git a/fs/btrfs/fscrypt.c b/fs/btrfs/fscrypt.c index 0e4011d6b1cd..6a4e4f63a660 100644 --- a/fs/btrfs/fscrypt.c +++ b/fs/btrfs/fscrypt.c @@ -5,13 +5,47 @@ #include "accessors.h" #include "btrfs_inode.h" #include "disk-io.h" +#include "ioctl.h" #include "fs.h" #include "fscrypt.h" #include "ioctl.h" #include "messages.h" +#include "root-tree.h" #include "transaction.h" #include "xattr.h" +/* + * This function is extremely similar to fscrypt_match_name() but uses an + * extent_buffer. + */ +bool btrfs_fscrypt_match_name(struct fscrypt_name *fname, + struct extent_buffer *leaf, unsigned long de_name, + u32 de_name_len) +{ + const struct fscrypt_nokey_name *nokey_name = + (const struct fscrypt_nokey_name *)fname->crypto_buf.name; + u8 digest[SHA256_DIGEST_SIZE]; + + if (likely(fname->disk_name.name)) { + if (de_name_len != fname->disk_name.len) + return false; + return !memcmp_extent_buffer(leaf, fname->disk_name.name, + de_name, de_name_len); + } + + if (de_name_len <= sizeof(nokey_name->bytes)) + return false; + + if (memcmp_extent_buffer(leaf, nokey_name->bytes, de_name, + sizeof(nokey_name->bytes))) + return false; + + extent_buffer_sha256(leaf, de_name + sizeof(nokey_name->bytes), + de_name_len - sizeof(nokey_name->bytes), digest); + + return !memcmp(digest, nokey_name->sha256, sizeof(digest)); +} + static int btrfs_fscrypt_get_context(struct inode *inode, void *ctx, size_t len) { struct btrfs_key key = { diff --git a/fs/btrfs/fscrypt.h b/fs/btrfs/fscrypt.h index 80adb7e56826..1647bbbcd609 100644 --- a/fs/btrfs/fscrypt.h +++ b/fs/btrfs/fscrypt.h @@ -4,9 +4,28 @@ #define BTRFS_FSCRYPT_H #include +#include "extent_io.h" #include "fs.h" +#ifdef CONFIG_FS_ENCRYPTION +bool btrfs_fscrypt_match_name(struct fscrypt_name *fname, + struct extent_buffer *leaf, + unsigned long de_name, u32 de_name_len); + +#else +static inline bool btrfs_fscrypt_match_name(struct fscrypt_name *fname, + struct extent_buffer *leaf, + unsigned long de_name, + u32 de_name_len) +{ + if (de_name_len != fname_len(fname)) + return false; + return !memcmp_extent_buffer(leaf, fname->disk_name.name, de_name, + de_name_len); +} +#endif /* CONFIG_FS_ENCRYPTION */ + extern const struct fscrypt_operations btrfs_fscrypt_ops; #endif /* BTRFS_FSCRYPT_H */ diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index cc52af10a520..60d1e93c2567 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4053,7 +4053,7 @@ int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans, struct btrfs_inode *dir, struct btrfs_inode *inode, - const struct fscrypt_str *name, + struct fscrypt_name *name, struct btrfs_rename_ctx *rename_ctx) { struct btrfs_root *root = dir->root; @@ -4071,7 +4071,7 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans, goto out; } - di = btrfs_lookup_dir_item(trans, root, path, dir_ino, name, -1); + di = btrfs_lookup_dir_item_fname(trans, root, path, dir_ino, name, -1); if (IS_ERR_OR_NULL(di)) { ret = di ? PTR_ERR(di) : -ENOENT; goto err; @@ -4099,11 +4099,14 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans, } } - ret = btrfs_del_inode_ref(trans, root, name, ino, dir_ino, &index); + ret = btrfs_del_inode_ref(trans, root, &name->disk_name, ino, dir_ino, + &index); if (ret) { + /* This should print a base-64 encoded name if relevant? */ btrfs_info(fs_info, "failed to delete reference to %.*s, inode %llu parent %llu", - name->len, name->name, ino, dir_ino); + name->disk_name.len, name->disk_name.name, ino, + dir_ino); btrfs_abort_transaction(trans, ret); goto err; } @@ -4124,8 +4127,10 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans, * operations on the log tree, increasing latency for applications. */ if (!rename_ctx) { - btrfs_del_inode_ref_in_log(trans, root, name, inode, dir_ino); - btrfs_del_dir_entries_in_log(trans, root, name, dir, index); + btrfs_del_inode_ref_in_log(trans, root, &name->disk_name, + inode, dir_ino); + btrfs_del_dir_entries_in_log(trans, root, &name->disk_name, + dir, index); } /* @@ -4143,7 +4148,7 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans, if (ret) goto out; - btrfs_i_size_write(dir, dir->vfs_inode.i_size - name->len * 2); + btrfs_i_size_write(dir, dir->vfs_inode.i_size - name->disk_name.len * 2); inode_inc_iversion(&inode->vfs_inode); inode_inc_iversion(&dir->vfs_inode); inode_set_mtime_to_ts(&dir->vfs_inode, inode_set_ctime_current(&dir->vfs_inode)); @@ -4154,7 +4159,7 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans, int btrfs_unlink_inode(struct btrfs_trans_handle *trans, struct btrfs_inode *dir, struct btrfs_inode *inode, - const struct fscrypt_str *name) + struct fscrypt_name *name) { int ret; @@ -4205,7 +4210,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) false); ret = btrfs_unlink_inode(trans, BTRFS_I(dir), BTRFS_I(d_inode(dentry)), - &fname.disk_name); + &fname); if (ret) goto end_trans; @@ -4242,8 +4247,6 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, if (ret) return ret; - /* This needs to handle no-key deletions later on */ - if (btrfs_ino(inode) == BTRFS_FIRST_FREE_OBJECTID) { objectid = inode->root->root_key.objectid; } else if (btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) { @@ -4260,8 +4263,8 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, goto out; } - di = btrfs_lookup_dir_item(trans, root, path, dir_ino, - &fname.disk_name, -1); + di = btrfs_lookup_dir_item_fname(trans, root, path, dir_ino, + &fname, -1); if (IS_ERR_OR_NULL(di)) { ret = di ? PTR_ERR(di) : -ENOENT; goto out; @@ -4287,7 +4290,7 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, * call btrfs_del_root_ref, and it _shouldn't_ fail. */ if (btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) { - di = btrfs_search_dir_index_item(root, path, dir_ino, &fname.disk_name); + di = btrfs_search_dir_index_item(root, path, dir_ino, &fname); if (IS_ERR_OR_NULL(di)) { if (!di) ret = -ENOENT; @@ -4304,7 +4307,7 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, } else { ret = btrfs_del_root_ref(trans, objectid, root->root_key.objectid, dir_ino, - &index, &fname.disk_name); + &index, &fname); if (ret) { btrfs_abort_transaction(trans, ret); goto out; @@ -4627,7 +4630,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) /* now the directory is empty */ err = btrfs_unlink_inode(trans, BTRFS_I(dir), BTRFS_I(d_inode(dentry)), - &fname.disk_name); + &fname); if (!err) { btrfs_i_size_write(BTRFS_I(inode), 0); /* @@ -5332,32 +5335,23 @@ void btrfs_evict_inode(struct inode *inode) * If no dir entries were found, returns -ENOENT. * If found a corrupted location in dir entry, returns -EUCLEAN. */ -static int btrfs_inode_by_name(struct btrfs_inode *dir, struct dentry *dentry, +static int btrfs_inode_by_name(struct btrfs_inode *dir, + struct fscrypt_name *fname, struct btrfs_key *location, u8 *type) { struct btrfs_dir_item *di; struct btrfs_path *path; struct btrfs_root *root = dir->root; int ret = 0; - struct fscrypt_name fname; path = btrfs_alloc_path(); if (!path) return -ENOMEM; - ret = fscrypt_setup_filename(&dir->vfs_inode, &dentry->d_name, 1, &fname); - if (ret < 0) - goto out; - /* - * fscrypt_setup_filename() should never return a positive value, but - * gcc on sparc/parisc thinks it can, so assert that doesn't happen. - */ - ASSERT(ret == 0); - /* This needs to handle no-key deletions later on */ - di = btrfs_lookup_dir_item(NULL, root, path, btrfs_ino(dir), - &fname.disk_name, 0); + di = btrfs_lookup_dir_item_fname(NULL, root, path, btrfs_ino(dir), + fname, 0); if (IS_ERR_OR_NULL(di)) { ret = di ? PTR_ERR(di) : -ENOENT; goto out; @@ -5369,13 +5363,13 @@ static int btrfs_inode_by_name(struct btrfs_inode *dir, struct dentry *dentry, ret = -EUCLEAN; btrfs_warn(root->fs_info, "%s gets something invalid in DIR_ITEM (name %s, directory ino %llu, location(%llu %u %llu))", - __func__, fname.disk_name.name, btrfs_ino(dir), - location->objectid, location->type, location->offset); + __func__, fname->usr_fname->name, + btrfs_ino(dir), location->objectid, + location->type, location->offset); } if (!ret) *type = btrfs_dir_ftype(path->nodes[0], di); out: - fscrypt_free_filename(&fname); btrfs_free_path(path); return ret; } @@ -5653,20 +5647,27 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) struct btrfs_root *root = BTRFS_I(dir)->root; struct btrfs_root *sub_root = root; struct btrfs_key location; + struct fscrypt_name fname; u8 di_type = 0; int ret = 0; if (dentry->d_name.len > BTRFS_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); - ret = btrfs_inode_by_name(BTRFS_I(dir), dentry, &location, &di_type); - if (ret < 0) + ret = fscrypt_prepare_lookup(dir, dentry, &fname); + if (ret) return ERR_PTR(ret); + ret = btrfs_inode_by_name(BTRFS_I(dir), &fname, &location, &di_type); + if (ret < 0) { + inode = ERR_PTR(ret); + goto cleanup; + } + if (location.type == BTRFS_INODE_ITEM_KEY) { inode = btrfs_iget(dir->i_sb, location.objectid, root); if (IS_ERR(inode)) - return inode; + goto cleanup; /* Do extra check against inode mode with di_type */ if (btrfs_inode_type(inode) != di_type) { @@ -5675,9 +5676,10 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) inode->i_mode, btrfs_inode_type(inode), di_type); iput(inode); - return ERR_PTR(-EUCLEAN); + inode = ERR_PTR(-EUCLEAN); + goto cleanup; } - return inode; + goto cleanup; } ret = fixup_tree_root_location(fs_info, BTRFS_I(dir), dentry, @@ -5692,7 +5694,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) btrfs_put_root(sub_root); if (IS_ERR(inode)) - return inode; + goto cleanup; down_read(&fs_info->cleanup_work_sem); if (!sb_rdonly(inode->i_sb)) @@ -5704,6 +5706,8 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) } } +cleanup: + fscrypt_free_filename(&fname); return inode; } @@ -5892,18 +5896,32 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) LIST_HEAD(del_list); int ret; char *name_ptr; - int name_len; + u32 name_len; int entries = 0; int total_len = 0; bool put = false; struct btrfs_key location; + struct fscrypt_str fstr = FSTR_INIT(NULL, 0); + u32 fstr_len = 0; if (!dir_emit_dots(file, ctx)) return 0; + if (BTRFS_I(inode)->flags & BTRFS_INODE_ENCRYPT) { + ret = fscrypt_prepare_readdir(inode); + if (ret) + return ret; + ret = fscrypt_fname_alloc_buffer(BTRFS_NAME_LEN, &fstr); + if (ret) + return ret; + fstr_len = fstr.len; + } + path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; + if (!path) { + ret = -ENOMEM; + goto err_fstr; + } addr = private->filldir_buf; path->reada = READA_FORWARD; @@ -5920,6 +5938,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) struct dir_entry *entry; struct extent_buffer *leaf = path->nodes[0]; u8 ftype; + u32 nokey_len; if (found_key.objectid != key.objectid) break; @@ -5933,8 +5952,13 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) continue; di = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); name_len = btrfs_dir_name_len(leaf, di); - if ((total_len + sizeof(struct dir_entry) + name_len) >= - PAGE_SIZE) { + nokey_len = DIV_ROUND_UP(name_len * 4, 3); + /* + * If name is encrypted, and we don't have the key, we could + * need up to 4/3rds the bytes to print it. + */ + if ((total_len + sizeof(struct dir_entry) + nokey_len) + >= PAGE_SIZE) { btrfs_release_path(path); ret = btrfs_filldir(private->filldir_buf, entries, ctx); if (ret) @@ -5948,8 +5972,36 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) ftype = btrfs_dir_flags_to_ftype(btrfs_dir_flags(leaf, di)); entry = addr; name_ptr = (char *)(entry + 1); - read_extent_buffer(leaf, name_ptr, - (unsigned long)(di + 1), name_len); + if (btrfs_dir_flags(leaf, di) & BTRFS_FT_ENCRYPTED) { + struct fscrypt_str oname = FSTR_INIT(name_ptr, + nokey_len); + u32 hash = 0, minor_hash = 0; + + read_extent_buffer(leaf, fstr.name, + (unsigned long)(di + 1), name_len); + fstr.len = name_len; + /* + * We're iterating through DIR_INDEX items, so we don't + * have the DIR_ITEM hash handy. Only compute it if + * we'll need it -- the nokey name stores it, so that + * we can look up the appropriate item by nokey name + * later on. + */ + if (!fscrypt_has_encryption_key(inode)) { + u64 name_hash = btrfs_name_hash(fstr.name, + fstr.len); + hash = name_hash; + minor_hash = name_hash >> 32; + } + ret = fscrypt_fname_disk_to_usr(inode, hash, minor_hash, + &fstr, &oname); + if (ret) + goto err; + name_len = oname.len; + } else { + read_extent_buffer(leaf, name_ptr, + (unsigned long)(di + 1), name_len); + } put_unaligned(name_len, &entry->name_len); put_unaligned(fs_ftype_to_dtype(ftype), &entry->type); btrfs_dir_item_key_to_cpu(leaf, di, &location); @@ -5969,7 +6021,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) if (ret) goto nopos; - ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list); + fstr.len = fstr_len; + ret = btrfs_readdir_delayed_dir_index(inode, &fstr, ctx, &ins_list); if (ret) goto nopos; @@ -6000,6 +6053,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx) if (put) btrfs_readdir_put_delayed_items(inode, &ins_list, &del_list); btrfs_free_path(path); +err_fstr: + fscrypt_fname_free_buffer(&fstr); return ret; } @@ -6458,6 +6513,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, struct btrfs_root *root = parent_inode->root; u64 ino = btrfs_ino(inode); u64 parent_ino = btrfs_ino(parent_inode); + struct fscrypt_name fname = { .disk_name = *name }; if (unlikely(ino == BTRFS_FIRST_FREE_OBJECTID)) { memcpy(&key, &inode->root->root_key, sizeof(key)); @@ -6513,7 +6569,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, int err; err = btrfs_del_root_ref(trans, key.objectid, root->root_key.objectid, parent_ino, - &local_index, name); + &local_index, &fname); if (err) btrfs_abort_transaction(trans, err); } else if (add_backref) { @@ -8894,7 +8950,7 @@ static int btrfs_rename_exchange(struct inode *old_dir, } else { /* src is an inode */ ret = __btrfs_unlink_inode(trans, BTRFS_I(old_dir), BTRFS_I(old_dentry->d_inode), - old_name, &old_rename_ctx); + &old_fname, &old_rename_ctx); if (!ret) ret = btrfs_update_inode(trans, BTRFS_I(old_inode)); } @@ -8909,7 +8965,7 @@ static int btrfs_rename_exchange(struct inode *old_dir, } else { /* dest is an inode */ ret = __btrfs_unlink_inode(trans, BTRFS_I(new_dir), BTRFS_I(new_dentry->d_inode), - new_name, &new_rename_ctx); + &new_fname, &new_rename_ctx); if (!ret) ret = btrfs_update_inode(trans, BTRFS_I(new_inode)); } @@ -9154,7 +9210,7 @@ static int btrfs_rename(struct mnt_idmap *idmap, } else { ret = __btrfs_unlink_inode(trans, BTRFS_I(old_dir), BTRFS_I(d_inode(old_dentry)), - &old_fname.disk_name, &rename_ctx); + &old_fname, &rename_ctx); if (!ret) ret = btrfs_update_inode(trans, BTRFS_I(old_inode)); } @@ -9172,7 +9228,7 @@ static int btrfs_rename(struct mnt_idmap *idmap, } else { ret = btrfs_unlink_inode(trans, BTRFS_I(new_dir), BTRFS_I(d_inode(new_dentry)), - &new_fname.disk_name); + &new_fname); } if (!ret && new_inode->i_nlink == 0) ret = btrfs_orphan_add(trans, diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 603ad1459368..d131934123f5 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -10,6 +10,7 @@ #include "messages.h" #include "transaction.h" #include "disk-io.h" +#include "fscrypt.h" #include "print-tree.h" #include "qgroup.h" #include "space-info.h" @@ -334,7 +335,7 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id, u64 ref_id, u64 dirid, u64 *sequence, - const struct fscrypt_str *name) + struct fscrypt_name *name) { struct btrfs_root *tree_root = trans->fs_info->tree_root; struct btrfs_path *path; @@ -356,13 +357,14 @@ int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id, if (ret < 0) { goto out; } else if (ret == 0) { + u32 name_len; leaf = path->nodes[0]; ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref); ptr = (unsigned long)(ref + 1); + name_len = btrfs_root_ref_name_len(leaf, ref); if ((btrfs_root_ref_dirid(leaf, ref) != dirid) || - (btrfs_root_ref_name_len(leaf, ref) != name->len) || - memcmp_extent_buffer(leaf, name->name, ptr, name->len)) { + !btrfs_fscrypt_match_name(name, leaf, ptr, name_len)) { ret = -ENOENT; goto out; } diff --git a/fs/btrfs/root-tree.h b/fs/btrfs/root-tree.h index 8b2c3859e464..5ba7b36cf826 100644 --- a/fs/btrfs/root-tree.h +++ b/fs/btrfs/root-tree.h @@ -15,7 +15,7 @@ int btrfs_add_root_ref(struct btrfs_trans_handle *trans, u64 root_id, const struct fscrypt_str *name); int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id, u64 ref_id, u64 dirid, u64 *sequence, - const struct fscrypt_str *name); + struct fscrypt_name *name); int btrfs_del_root(struct btrfs_trans_handle *trans, const struct btrfs_key *key); int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, const struct btrfs_key *key, diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 00b6f0c71e1d..89d3dc769b15 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -901,9 +901,10 @@ static int unlink_inode_for_log_replay(struct btrfs_trans_handle *trans, struct btrfs_inode *inode, const struct fscrypt_str *name) { + struct fscrypt_name fname = { .disk_name = *name, }; int ret; - ret = btrfs_unlink_inode(trans, dir, inode, name); + ret = btrfs_unlink_inode(trans, dir, inode, &fname); if (ret) return ret; /* From patchwork Fri Dec 1 22:11:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476505 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="ZGyKVaws" Received: from mail-yw1-x1141.google.com (mail-yw1-x1141.google.com [IPv6:2607:f8b0:4864:20::1141]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 90B14D63 for ; Fri, 1 Dec 2023 14:12:15 -0800 (PST) Received: by mail-yw1-x1141.google.com with SMTP id 00721157ae682-5c8c26cf056so29827507b3.1 for ; Fri, 01 Dec 2023 14:12:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468734; x=1702073534; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=nGaKZfQ8xEUtcj2BvoUGwcXV31Q0VFKb7VLEms82qyQ=; b=ZGyKVaws3S0GoOwsOzviq3RAPMFOGknLTSLTqBg3I6yBiytMNnautYq3Z6FGyhKx0W aezaykvutmCXEoCso83D7mJMR0Mrqg43s98XjrXttGG0O+0/ArUdg+S+jFhISMjcVOK/ 45E9AnBb3L1SzohKM6zuFxFuXy0WQKaeyjqYDEDDMuYHQ/2MEEjFa5o4PnwcWstFMKkx x3G08Y06VyNzmeo7/gwwIleESZwvuCUW2CJ6DSkXpyljgCJSYCPFhiYBvy4+iRlbNW8P DY9PrPVBP7YxP2j8XuWBbOkwzFOaYfXSV6+W6GVI62X8ZT6AsXrUAGyqAcvx2XXh8lgf RJ5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468734; x=1702073534; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=nGaKZfQ8xEUtcj2BvoUGwcXV31Q0VFKb7VLEms82qyQ=; b=F0t/vFa+pWm0udvMFAKtNuIHG7BDShYg/uiu3EJuy7Z3NkNIkUOd2YujP0moB4MnfU RY2N7TiZQNjyiHwUuJ5wgoEtxMRVHCcx2YMckKGbHKSXX0EfwLbDf+mYdXRd3nJjpUhw TIteg0eZx1+DYehoAQLZYNmJOUA3EyXjisx/KgJXrVOzEGhbB9ILQuDeQe4VW08FaBGr VTvtpPcg+wuNB0YM4lWq+bFiw86Fz06daY20nGXXDWiiMCRQQkFdwcVXksxZA6EvBt9n 4rRqrQBC7raDqcyMH2lo/qQH8fRsZrF86booJ3EbwkrNs1eFChNkRaEYpP244lvr9HlF QYUg== X-Gm-Message-State: AOJu0Yww8proSO9A8v7rWvlchVCNvSItDE1+NWffumIav7kK63E6pNWf ji5WnOHdCipjWvKLq+KsaPTDTWbvto4loBjiot4SFL+i X-Google-Smtp-Source: AGHT+IERfmiIIYpmihLJrdT1pqpTfZYUTDg0+VM8i/Q4h5RqR5xJgNcKO+1ZfO9c3q0JsRg6HDBCGg== X-Received: by 2002:a05:690c:3387:b0:5a8:874:bb3a with SMTP id fl7-20020a05690c338700b005a80874bb3amr279105ywb.31.1701468734628; Fri, 01 Dec 2023 14:12:14 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id w72-20020a81494b000000b005d70c0a85casm151282ywa.53.2023.12.01.14.12.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:14 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Sweet Tea Dorminy Subject: [PATCH v4 15/46] btrfs: handle nokey names. Date: Fri, 1 Dec 2023 17:11:12 -0500 Message-ID: <5729e533bb7e014a124cc48d793dec30507455b7.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Sweet Tea Dorminy For encrypted or unencrypted names, we calculate the offset for the dir item by hashing the name for the dir item. However, this doesn't work for a long nokey name, where we do not have the complete ciphertext. Instead, fscrypt stores the filesystem-provided hash in the nokey name, and we can extract it from the fscrypt_name structure in such a case. Additionally, for nokey names, if we find the nokey name on disk we can update the fscrypt_name with the disk name, so add that to searching for diritems. Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/dir-item.c | 37 +++++++++++++++++++++++++++++++++++-- fs/btrfs/fscrypt.c | 27 +++++++++++++++++++++++++++ fs/btrfs/fscrypt.h | 11 +++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index a64cfddff7f0..897fb5477369 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c @@ -231,6 +231,28 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, return di; } +/* + * If appropriate, populate the disk name for a fscrypt_name looked up without + * a key. + * + * @path: The path to the extent buffer in which the name was found. + * @di: The dir item corresponding. + * @fname: The fscrypt_name to perhaps populate. + * + * Returns: 0 if the name is already populated or the dir item doesn't exist + * or the name was successfully populated, else an error code. + */ +static int ensure_disk_name_from_dir_item(struct btrfs_path *path, + struct btrfs_dir_item *di, + struct fscrypt_name *name) +{ + if (name->disk_name.name || !di) + return 0; + + return btrfs_fscrypt_get_disk_name(path->nodes[0], di, + &name->disk_name); +} + /* * Lookup for a directory item by fscrypt_name. * @@ -257,8 +279,12 @@ struct btrfs_dir_item *btrfs_lookup_dir_item_fname(struct btrfs_trans_handle *tr key.objectid = dir; key.type = BTRFS_DIR_ITEM_KEY; - key.offset = btrfs_name_hash(name->disk_name.name, name->disk_name.len); - /* XXX get the right hash for no-key names */ + + if (!name->disk_name.name) + key.offset = name->hash | ((u64)name->minor_hash << 32); + else + key.offset = btrfs_name_hash(name->disk_name.name, + name->disk_name.len); ret = btrfs_search_slot(trans, root, &key, path, mod, -mod); if (ret == 0) @@ -266,6 +292,8 @@ struct btrfs_dir_item *btrfs_lookup_dir_item_fname(struct btrfs_trans_handle *tr if (ret == -ENOENT || (di && IS_ERR(di) && PTR_ERR(di) == -ENOENT)) return NULL; + if (ret == 0) + ret = ensure_disk_name_from_dir_item(path, di, name); if (ret < 0) di = ERR_PTR(ret); @@ -382,7 +410,12 @@ btrfs_search_dir_index_item(struct btrfs_root *root, struct btrfs_path *path, btrfs_for_each_slot(root, &key, &key, path, ret) { if (key.objectid != dirid || key.type != BTRFS_DIR_INDEX_KEY) break; + di = btrfs_match_dir_item_fname(root->fs_info, path, name); + if (di) + ret = ensure_disk_name_from_dir_item(path, di, name); + if (ret) + break; if (di) return di; } diff --git a/fs/btrfs/fscrypt.c b/fs/btrfs/fscrypt.c index 6a4e4f63a660..9103da28af7e 100644 --- a/fs/btrfs/fscrypt.c +++ b/fs/btrfs/fscrypt.c @@ -14,6 +14,33 @@ #include "transaction.h" #include "xattr.h" +/* + * From a given location in a leaf, read a name into a qstr (usually a + * fscrypt_name's disk_name), allocating the required buffer. Used for + * nokey names. + */ +int btrfs_fscrypt_get_disk_name(struct extent_buffer *leaf, + struct btrfs_dir_item *dir_item, + struct fscrypt_str *name) +{ + unsigned long de_name_len = btrfs_dir_name_len(leaf, dir_item); + unsigned long de_name = (unsigned long)(dir_item + 1); + /* + * For no-key names, we use this opportunity to find the disk + * name, so future searches don't need to deal with nokey names + * and we know what the encrypted size is. + */ + name->name = kmalloc(de_name_len, GFP_NOFS); + + if (!name->name) + return -ENOMEM; + + read_extent_buffer(leaf, name->name, de_name, de_name_len); + + name->len = de_name_len; + return 0; +} + /* * This function is extremely similar to fscrypt_match_name() but uses an * extent_buffer. diff --git a/fs/btrfs/fscrypt.h b/fs/btrfs/fscrypt.h index 1647bbbcd609..c08fd52c99b4 100644 --- a/fs/btrfs/fscrypt.h +++ b/fs/btrfs/fscrypt.h @@ -9,11 +9,22 @@ #include "fs.h" #ifdef CONFIG_FS_ENCRYPTION +int btrfs_fscrypt_get_disk_name(struct extent_buffer *leaf, + struct btrfs_dir_item *di, + struct fscrypt_str *qstr); + bool btrfs_fscrypt_match_name(struct fscrypt_name *fname, struct extent_buffer *leaf, unsigned long de_name, u32 de_name_len); #else +static inline int btrfs_fscrypt_get_disk_name(struct extent_buffer *leaf, + struct btrfs_dir_item *di, + struct fscrypt_str *qstr) +{ + return 0; +} + static inline bool btrfs_fscrypt_match_name(struct fscrypt_name *fname, struct extent_buffer *leaf, unsigned long de_name, From patchwork Fri Dec 1 22:11:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476503 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="TWxIjlLD" Received: from mail-yw1-x1129.google.com (mail-yw1-x1129.google.com [IPv6:2607:f8b0:4864:20::1129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B8B5B10DB for ; Fri, 1 Dec 2023 14:12:16 -0800 (PST) Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-5d3644d3d67so22349367b3.2 for ; Fri, 01 Dec 2023 14:12:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468736; x=1702073536; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=f7FY9F3PNpFwIYkm5ynwFuIi/6ljrtymCrqiOPVng78=; b=TWxIjlLDRpH9bgw3/lqRS57LZldUGEFBKrUu84va7NnIR+gdHXWpqeCUgqgGDy/Bth P/35qWiOFSKOO9RXAFndWFysZWXuhjN2SB+l18BuHtLrQnTZJvDZjF4SUfoFjsetAx15 oi1TbSldRiUzdW6psiti+SP/dE/6v3KBRWOkZmAKBloPPkpduL9JYI7QckHps6aGZ2PJ 1xyUVTu4K69+NQy+BvghbA/SttpjIlyp99gMU05ZtFSuabyjpDkLHlBu73nowKDX1U/9 dbxpj3xTRAxC6hBErmkjAXOL5f3t1NQnfOQPqSwIlABJ35Z0ocdXOkm0g8v9yLgW8+ok Wgqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468736; x=1702073536; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=f7FY9F3PNpFwIYkm5ynwFuIi/6ljrtymCrqiOPVng78=; b=bTOD6+qb1/DWhf0J/EeI0/hG9WeBCCBD/RhqSoY5CbUZpURwPD7oIzI2PKlRF7Hmsm a3aeVb5XnpUHGTRjojPEnZKqb0V9ljgxcN+i/UGHmDme3LpETVEG/hL3MCyBVD6d4Lmd tX9MmHZgMiyKIEgjMehjEFTkKaeCvIjV6XL/83+HxGyVUPPgQV1HN1XO/CcyltUQyEFB WvzH77zB9bnq1XRDOhmoIjjSEY9jcdUNI/ZXNP5tY/THvypa7oJm/GrNWlpfPogJP7dR pzxjyMvWM/eoFq2qtvudNrdDHdA1ehc8WZri9ymSH8tT5GIdQeAAfhn7I1YWNaryWSsJ t8ow== X-Gm-Message-State: AOJu0YziRO8tPoK/YY5jAYPLXJP6/rB7NgeUw/7KKwhiz5bBCJBNr7Zr vGZYK9M1PGjGUzXgRh7Lz4kTCveOPjYLAy1oVkRL2Q== X-Google-Smtp-Source: AGHT+IE/fapadgGWO7uKbXUjZX7CYQ/wtzItNgDJhEus4QLqw3fvL1mVDChh5SIzWPrBQwQT7yK8xA== X-Received: by 2002:a81:b049:0:b0:5d2:913a:640d with SMTP id x9-20020a81b049000000b005d2913a640dmr357620ywk.47.1701468735788; Fri, 01 Dec 2023 14:12:15 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id d19-20020a81ab53000000b005d336130ea3sm326221ywk.70.2023.12.01.14.12.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:15 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Omar Sandoval , Sweet Tea Dorminy Subject: [PATCH v4 16/46] btrfs: implement fscrypt ioctls Date: Fri, 1 Dec 2023 17:11:13 -0500 Message-ID: <0a93a7133dabe9a3d65439af44bab19ba8c892ef.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Omar Sandoval These ioctls allow encryption to actually be used. The set_encryption_policy ioctl is the thing which actually turns on encryption, and therefore sets the ENCRYPT flag in the superblock. This prevents the filesystem from being loaded on older kernels. fscrypt provides CONFIG_FS_ENCRYPTION-disabled versions of all these functions which just return -EOPNOTSUPP, so the ioctls don't need to be compiled out if CONFIG_FS_ENCRYPTION isn't enabled. We could instead gate this ioctl on the superblock having the flag set, if we wanted to require mkfs with the encrypt flag in order to have a filesystem with any encryption. Signed-off-by: Omar Sandoval Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/ioctl.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 6acf898f693e..9968a36079c4 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -4573,6 +4573,34 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_get_fslabel(fs_info, argp); case FS_IOC_SETFSLABEL: return btrfs_ioctl_set_fslabel(file, argp); + case FS_IOC_SET_ENCRYPTION_POLICY: { + if (!IS_ENABLED(CONFIG_FS_ENCRYPTION)) + return -EOPNOTSUPP; + if (sb_rdonly(fs_info->sb)) + return -EROFS; + /* + * If we crash before we commit, nothing encrypted could have + * been written so it doesn't matter whether the encrypted + * state persists. + */ + btrfs_set_fs_incompat(fs_info, ENCRYPT); + return fscrypt_ioctl_set_policy(file, (const void __user *)arg); + } + case FS_IOC_GET_ENCRYPTION_POLICY: + return fscrypt_ioctl_get_policy(file, (void __user *)arg); + case FS_IOC_GET_ENCRYPTION_POLICY_EX: + return fscrypt_ioctl_get_policy_ex(file, (void __user *)arg); + case FS_IOC_ADD_ENCRYPTION_KEY: + return fscrypt_ioctl_add_key(file, (void __user *)arg); + case FS_IOC_REMOVE_ENCRYPTION_KEY: + return fscrypt_ioctl_remove_key(file, (void __user *)arg); + case FS_IOC_REMOVE_ENCRYPTION_KEY_ALL_USERS: + return fscrypt_ioctl_remove_key_all_users(file, + (void __user *)arg); + case FS_IOC_GET_ENCRYPTION_KEY_STATUS: + return fscrypt_ioctl_get_key_status(file, (void __user *)arg); + case FS_IOC_GET_ENCRYPTION_NONCE: + return fscrypt_ioctl_get_nonce(file, (void __user *)arg); case FITRIM: return btrfs_ioctl_fitrim(fs_info, argp); case BTRFS_IOC_SNAP_CREATE: From patchwork Fri Dec 1 22:11:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476504 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="1XvDMNHj" Received: from mail-yw1-x1130.google.com (mail-yw1-x1130.google.com [IPv6:2607:f8b0:4864:20::1130]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EFC6BD50 for ; Fri, 1 Dec 2023 14:12:17 -0800 (PST) Received: by mail-yw1-x1130.google.com with SMTP id 00721157ae682-5c08c47c055so29080417b3.1 for ; Fri, 01 Dec 2023 14:12:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468737; x=1702073537; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=xJBhhgJ+1T9YX1Azl50SzieInTuno7x/kRfcGFlFKhk=; b=1XvDMNHjmsg1O2b89cOD0fX2jISRqcWq9WFoV5788CPayCC0YPtDi3wANdjWo2LTV8 XPM4bBE2jC8wQzJ1GChUs+AFRFURxzb/T+bZ+U0COEFF8s2pxOR3r1pSaJBSj/KoA+Dv yzp6WUX4xbR3jEmsL/ZHUOu59RPUzDJYJLuoueAl5VedMDvlub7wkzeFXwCnOGoXFa3r Q8Is/ofhHaLgXJCZUW4C38olJGVhcqa0go3YwgVQRVWugvvbsri83XC5sJr2MitO0BAQ drOBV401QkF1B9L9VRz7ROkM9NNifBhGjLeEATWmcR+gCAgegs3JSbVQxJLXBDx3iMN1 BZ1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468737; x=1702073537; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=xJBhhgJ+1T9YX1Azl50SzieInTuno7x/kRfcGFlFKhk=; b=v2kkaPVgviLfnN/TA5xl+29DGINbwyVeWrh3mWgkDmUY7by8B3bMql54JEhcHTHS0X JNKGq7pLK8zRsUWy914dhES8hHy7o4ES1NtlXVpimuozjgwuXTEHn1UuLAm+1wyu9tKS ddEViqvdeqTBEktxJQqmFyZjJ2rvjeOfubNLbrtOganAzP2w5eK5wejWAL8aKjhxEMHl YMsaT0OIFpsa6+21Lqm4DMRaz3LLsBGMzMzDGtm2IhEZIoU1EGfsI5scJ/Yfl1Qoss7c 3OKsUgxHxKH36XD/xAFHfsyqi25JeZ+fTFrUZVTuLccNgLHm808KUdlr9Y5kjU+Yxz+p lcwA== X-Gm-Message-State: AOJu0YxZ6EKnw/xAnkkkjgyteOfiOK4MpFlw5pzTt3Ph/HZn0tu7rMwn AmvN2gBzEuQ3TBTC7vsjhpd/3s4yLPfmXFYntp057Q== X-Google-Smtp-Source: AGHT+IEpiSNvOiaKjibA/IViu1TIx8ICi0Ven/x7rIS7LMv7zL85hNSe7A2i3HsIVEp7yzw53XnwMg== X-Received: by 2002:a0d:c985:0:b0:5cd:6d0e:5369 with SMTP id l127-20020a0dc985000000b005cd6d0e5369mr378564ywd.34.1701468737049; Fri, 01 Dec 2023 14:12:17 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id h13-20020a81b40d000000b005d1b2153b7bsm1365091ywi.18.2023.12.01.14.12.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:16 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Sweet Tea Dorminy Subject: [PATCH v4 17/46] btrfs: add encryption to CONFIG_BTRFS_DEBUG Date: Fri, 1 Dec 2023 17:11:14 -0500 Message-ID: <162cd559b6a47e1df6e49b15acb24942577280f5.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Sweet Tea Dorminy Since encryption is currently under BTRFS_DEBUG, this adds its dependencies: inline encryption from fscrypt, and the inline encryption fallback path from the block layer. Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/ioctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 9968a36079c4..0e8e2ca48a2e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -4573,6 +4573,7 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_get_fslabel(fs_info, argp); case FS_IOC_SETFSLABEL: return btrfs_ioctl_set_fslabel(file, argp); +#ifdef CONFIG_BTRFS_DEBUG case FS_IOC_SET_ENCRYPTION_POLICY: { if (!IS_ENABLED(CONFIG_FS_ENCRYPTION)) return -EOPNOTSUPP; @@ -4601,6 +4602,7 @@ long btrfs_ioctl(struct file *file, unsigned int return fscrypt_ioctl_get_key_status(file, (void __user *)arg); case FS_IOC_GET_ENCRYPTION_NONCE: return fscrypt_ioctl_get_nonce(file, (void __user *)arg); +#endif /* CONFIG_BTRFS_DEBUG */ case FITRIM: return btrfs_ioctl_fitrim(fs_info, argp); case BTRFS_IOC_SNAP_CREATE: From patchwork Fri Dec 1 22:11:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476506 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="te1o93ld" Received: from mail-yw1-x112e.google.com (mail-yw1-x112e.google.com [IPv6:2607:f8b0:4864:20::112e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A07EA10F1 for ; Fri, 1 Dec 2023 14:12:19 -0800 (PST) Received: by mail-yw1-x112e.google.com with SMTP id 00721157ae682-5d7084b6bb1so3014677b3.2 for ; Fri, 01 Dec 2023 14:12:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468739; x=1702073539; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Cn/5d23+Piiaq9wfrRh434zM+tA72DN+x3v+pwhuqj8=; b=te1o93ldXA8bGPpTugHIdBQXZbUqnFxjPgdM+XseecIqy2KSdnC2xMk4JbyfOwZAru Uf4ggk70UcK8ULMamB+DXy1s+MLDu/oxLNyMMriy9s/FWPLiLdbsm7P8Shv2ZGbInaaj xU9bbF4TmJp5w/4cuqOS5nnSUnAyvsVYbfzKuA+z2TCB2+Io+hFyv+qEeiKKe35xQumu MfhYquLYoAxUFF8JigQKp1JIhVlFw2hCeWkK9rjBfOgtTI2qyKJ1PS4djrlyc37rXjvJ GEXmE4Gb3kwSQ19btVa52U4NMQassVSHd4ITwvHAQctlKpBxW5NAmCZ6f2hFUGGOd47s /3pQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468739; x=1702073539; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Cn/5d23+Piiaq9wfrRh434zM+tA72DN+x3v+pwhuqj8=; b=BZJ7Xx5GB6oZtRTqPI5bo2tE8nl4AeWaisaBmI4K2GY7xVn0fphEj7Z95QJLc+GDCg hvnk2uRgQKaHJaluWhBPFkcZBMQAR783c4lnqFEUOkHImi05X0w0wVw6ezkye1816PEU eK1sqb6Fc3N7FKqF93+WPU30tReFaL3D1shI6EsOuIMSyrgpy2mKHDl+mhSM78+BHkAj aZOY5721xlHvHDbLc0UEzEVARJWY8Tw/H4peIVCfXlIUTlPG9T7TItxOA5MCSdxGiSH1 vmdmU/WG3BI0sKm/XyVKCBdbywV9OoiTeUZEXL6pHiElow+CDuvzZCEUU0I1Gwbuq1de P36w== X-Gm-Message-State: AOJu0YzMxHOna+4uk3KRr9w8n9hiUgDmKBN1GAfpEhmbPuvuPeFQ9Fx1 kFr/eWJf1ATMfIdn0FPUBSxMZpa/nnSubt3F17AtBA== X-Google-Smtp-Source: AGHT+IGwKgKwJieuod2BvgdYGZbGi6RK3u0kD5BnpiTCasyQjPg9Qmn5EOtaFfHx3/XBEyUTpFupSw== X-Received: by 2002:a81:99d4:0:b0:5d7:1940:f3f1 with SMTP id q203-20020a8199d4000000b005d71940f3f1mr149497ywg.89.1701468738787; Fri, 01 Dec 2023 14:12:18 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id t7-20020a815f07000000b005d0fea7ad01sm1392549ywb.122.2023.12.01.14.12.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:17 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Sweet Tea Dorminy Subject: [PATCH v4 18/46] btrfs: add get_devices hook for fscrypt Date: Fri, 1 Dec 2023 17:11:15 -0500 Message-ID: <7d727ad8e77df8e05f8e1374abbd4745603221d8.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Sweet Tea Dorminy Since extent encryption requires inline encryption, even though we expect to use the inlinecrypt software fallback most of the time, we need to enumerate all the devices in use by btrfs. Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/fscrypt.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/fs/btrfs/fscrypt.c b/fs/btrfs/fscrypt.c index 9103da28af7e..2d037b105b5f 100644 --- a/fs/btrfs/fscrypt.c +++ b/fs/btrfs/fscrypt.c @@ -11,7 +11,9 @@ #include "ioctl.h" #include "messages.h" #include "root-tree.h" +#include "super.h" #include "transaction.h" +#include "volumes.h" #include "xattr.h" /* @@ -178,8 +180,43 @@ static bool btrfs_fscrypt_empty_dir(struct inode *inode) return inode->i_size == BTRFS_EMPTY_DIR_SIZE; } +static struct block_device **btrfs_fscrypt_get_devices(struct super_block *sb, + unsigned int *num_devs) +{ + struct btrfs_fs_info *fs_info = btrfs_sb(sb); + struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; + int nr_devices = fs_devices->open_devices; + struct block_device **devs; + struct btrfs_device *device; + int i = 0; + + devs = kmalloc_array(nr_devices, sizeof(*devs), GFP_NOFS | GFP_NOWAIT); + if (!devs) + return ERR_PTR(-ENOMEM); + + rcu_read_lock(); + list_for_each_entry_rcu(device, &fs_devices->devices, dev_list) { + if (!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, + &device->dev_state) || + !device->bdev || + test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state)) + continue; + + devs[i++] = device->bdev; + + if (i >= nr_devices) + break; + + } + rcu_read_unlock(); + + *num_devs = i; + return devs; +} + const struct fscrypt_operations btrfs_fscrypt_ops = { .get_context = btrfs_fscrypt_get_context, .set_context = btrfs_fscrypt_set_context, .empty_dir = btrfs_fscrypt_empty_dir, + .get_devices = btrfs_fscrypt_get_devices, }; From patchwork Fri Dec 1 22:11:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476507 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="R4w4SWTT" Received: from mail-yb1-xb2e.google.com (mail-yb1-xb2e.google.com [IPv6:2607:f8b0:4864:20::b2e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EC6C410FA for ; Fri, 1 Dec 2023 14:12:20 -0800 (PST) Received: by mail-yb1-xb2e.google.com with SMTP id 3f1490d57ef6-db537948ea0so1002955276.2 for ; Fri, 01 Dec 2023 14:12:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468740; x=1702073540; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+Me6PFFvsP0oOFqy+GUmI2ph2kV3o9d2iI4+tysJcII=; b=R4w4SWTTpW7KzYVQauN2gp9dEJLYJxXeRqI1dUjH1mnXrGQbcgYh/RB6BwEzM36zuG DR+rtwFmnvM2sqWFCbQNWzTQKlCHDSty1vPrjTtbpvSaJN9/+/wHKL6kABRwmlFxl5LK yH4YFJtJi19Q/C9rDLr7ycrIWX+yeGPalKjpwaKfSZZqFDMoIdj2Rw+jE7VI5VmaVFdZ oadJAyt0c3SX4UUCAI9KPtEfLDHlFTMNEQ7BV/ZEPCDJbJ78OVCNeF2BZ5vtfelrLstn GTOAituqiMU2JBHWZx7cMAIVOWem2YdtGnKFBC8LEWkyPkZn5Deky7uujQFPVqIvtbCY 1hDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468740; x=1702073540; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+Me6PFFvsP0oOFqy+GUmI2ph2kV3o9d2iI4+tysJcII=; b=WXIKpdAfDMsq/eb78EFrHRmrY+b5Im9rl/54+kZVdLSML3MZjhI4qMYe2ITJjpO9he cohDsnMfzH4AVbaCj2XizQHTkI7nmV+78p0Wyh+75zATu8MtMQNjhfOCVSITTH7MC0g8 c8JWN/tndP4+ldjzTLSUjgl0/BAsYhbCd8OUQDWgWzGCTtM5TGBOt7pL9X6C+oLQzRI0 qY/CfazCu1vMXc4cBRto6aC7dITnPcgH5HWlwWenRp4sm4JEUZXJ2/t1aBAEQQBipPXM KC6w39gnLDDFed1p4qXOZi6bFqAjbm3ZgLLeHin4nXXuRuR1lNr9nmmMmyKc0UncJVys Ikjg== X-Gm-Message-State: AOJu0Yy457eTC103vyXPx/gCSijPVdF0jLpKQUQRRYTUJLRvHQFCNmPu W2AOoDqdqWT7HQ2SvofpkgCD6WzX1sH+Lmk8Sb37hw== X-Google-Smtp-Source: AGHT+IEjo91gSjhScAPnqj4DgQfMU9fMdxAI0H9kp/g/wavzbx2+kweH1uzNpCiiW7mdbbh3M9wYVg== X-Received: by 2002:a0d:ee41:0:b0:57a:cf8:5b4 with SMTP id x62-20020a0dee41000000b0057a0cf805b4mr25684019ywe.51.1701468739945; Fri, 01 Dec 2023 14:12:19 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id w197-20020a0dd4ce000000b005d6cb0e49f9sm389137ywd.105.2023.12.01.14.12.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:19 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Sweet Tea Dorminy Subject: [PATCH v4 19/46] btrfs: turn on inlinecrypt mount option for encrypt Date: Fri, 1 Dec 2023 17:11:16 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Sweet Tea Dorminy fscrypt's extent encryption requires the use of inline encryption or the software fallback that the block layer provides; it is rather complicated to allow software encryption with extent encryption due to the timing of memory allocations. Thus, if btrfs has ever had a encrypted file, or when encryption is enabled on a directory, update the mount flags to include inlinecrypt. Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/ioctl.c | 3 +++ fs/btrfs/super.c | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 0e8e2ca48a2e..48d751011d07 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -4585,6 +4585,9 @@ long btrfs_ioctl(struct file *file, unsigned int * state persists. */ btrfs_set_fs_incompat(fs_info, ENCRYPT); + if (!(inode->i_sb->s_flags & SB_INLINECRYPT)) { + inode->i_sb->s_flags |= SB_INLINECRYPT; + } return fscrypt_ioctl_set_policy(file, (const void __user *)arg); } case FS_IOC_GET_ENCRYPTION_POLICY: diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 39a338e92115..462a23db26af 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -946,6 +946,16 @@ static int btrfs_fill_super(struct super_block *sb, return err; } + if (btrfs_fs_incompat(fs_info, ENCRYPT)) { + if (IS_ENABLED(CONFIG_FS_ENCRYPTION_INLINE_CRYPT)) { + sb->s_flags |= SB_INLINECRYPT; + } else { + btrfs_err(fs_info, "encryption not supported"); + err = -EINVAL; + goto fail_close; + } + } + inode = btrfs_iget(sb, BTRFS_FIRST_FREE_OBJECTID, fs_info->fs_root); if (IS_ERR(inode)) { err = PTR_ERR(inode); From patchwork Fri Dec 1 22:11:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476508 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="WUnV6Pku" Received: from mail-yw1-x1132.google.com (mail-yw1-x1132.google.com [IPv6:2607:f8b0:4864:20::1132]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EA15810FD for ; Fri, 1 Dec 2023 14:12:21 -0800 (PST) Received: by mail-yw1-x1132.google.com with SMTP id 00721157ae682-5c08c47c055so29080907b3.1 for ; Fri, 01 Dec 2023 14:12:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468741; x=1702073541; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LzinTCkDfALoxVW/93SBKBIC+NFbTZc80WmEA1KnS5U=; b=WUnV6PkuCDym8X1mVrgDN/JsQ4eQ3oJDQE9h7LPJFoPja1CHIcOMX0hssakH2PvnQk C6rEx51hh9TPwDSYcDUaluUu058Sg5fdNWFXOFj8kGrFw5dwfxQoUybBHWIzzGflxU7l YEdpK/fPMJmu/Gg1dFIAxSXuGMUZ2LBwPco1xpdn7aPWM3dYDZTGrgMroWWJGknJwBpr jnzpNybm3M2pDAj3iEmqhyL3+/L4SBBvwGcmV8wa1FGDAoIqu/RZP3dcEs4Z56QRBu06 fG3suXMzAwnBzqpWO74uCntKY4OYf+X5y6u3LJi7+ZkV0Q213VhiqNDeF8PZhJj4uPBW vpnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468741; x=1702073541; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LzinTCkDfALoxVW/93SBKBIC+NFbTZc80WmEA1KnS5U=; b=dfvS+tTRa55xfnncFW1Tw83TLh5ZdeDjqVv/vhKXywAX3lG5XNAqGKSfub07E49Qem 3MWCDfQONDtmsp3ZfDt9Pugx6DgHb3j2QoHNctjnH46wKvmdArDJ7eW6w4Hc9LAHtV75 u4Nk+yz5JLuT0ks6+3Zk7bok7lOrEOpjouX2vYdFmDYKK/e0owJd0D/PGrLFW5eaFXx6 V0AjMjMexpxe5RDO9INLR8b+IgtQ9SMFJ4v1JFfmDb3VNX3voU1f4Z3tqYqzInVzOVrr lvSDt2ZUh4RpVLIrs151O6UwChRoKIpBEziEMJ0jEGGqJBl+gKZznNNSYjRx3piT/JgI la8A== X-Gm-Message-State: AOJu0YwtJuXS0eQlC6RwV9QQ890d+5CkAxVG9nYOpQcp3Dblmees4dC6 Q10lltT0xCd6+bxdsfMnvfvluo2PjyNYbtZ/xyVsZA== X-Google-Smtp-Source: AGHT+IH8/SL3ehe18tXNjC/LUcLv0rpp8LnrsfN3yJxi/vBfvyeg3PxZcURMLxz/UEEyuMChRPHn6A== X-Received: by 2002:a05:690c:30a:b0:5ce:1046:c85e with SMTP id bg10-20020a05690c030a00b005ce1046c85emr400921ywb.28.1701468741014; Fri, 01 Dec 2023 14:12:21 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id n14-20020a819e4e000000b0059b2be24f88sm1344917ywj.143.2023.12.01.14.12.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:20 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Sweet Tea Dorminy Subject: [PATCH v4 20/46] btrfs: set file extent encryption excplicitly Date: Fri, 1 Dec 2023 17:11:17 -0500 Message-ID: <7337bfb86c3546ffedb706df0e785e2a346aa374.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Sweet Tea Dorminy This puts the long-preserved 1-byte encryption field to work, storing whether the extent is encrypted. Update the tree-checker to allow for the encryption bit to be set to our valid types. Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/accessors.h | 2 ++ fs/btrfs/inode.c | 8 ++++++-- fs/btrfs/tree-checker.c | 8 +++++--- fs/btrfs/tree-log.c | 2 ++ include/uapi/linux/btrfs_tree.h | 8 +++++++- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/accessors.h b/fs/btrfs/accessors.h index aa0844535644..5aaf204fa55f 100644 --- a/fs/btrfs/accessors.h +++ b/fs/btrfs/accessors.h @@ -949,6 +949,8 @@ BTRFS_SETGET_STACK_FUNCS(stack_file_extent_disk_num_bytes, struct btrfs_file_extent_item, disk_num_bytes, 64); BTRFS_SETGET_STACK_FUNCS(stack_file_extent_compression, struct btrfs_file_extent_item, compression, 8); +BTRFS_SETGET_STACK_FUNCS(stack_file_extent_encryption, + struct btrfs_file_extent_item, encryption, 8); BTRFS_SETGET_FUNCS(file_extent_type, struct btrfs_file_extent_item, type, 8); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 60d1e93c2567..f894f5b5e786 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3001,7 +3001,9 @@ static int insert_ordered_extent_file_extent(struct btrfs_trans_handle *trans, btrfs_set_stack_file_extent_num_bytes(&stack_fi, num_bytes); btrfs_set_stack_file_extent_ram_bytes(&stack_fi, ram_bytes); btrfs_set_stack_file_extent_compression(&stack_fi, oe->compress_type); - /* Encryption and other encoding is reserved and all 0 */ + btrfs_set_stack_file_extent_encryption(&stack_fi, + BTRFS_ENCRYPTION_NONE); + /* Other encoding is reserved and always 0 */ /* * For delalloc, when completing an ordered extent we update the inode's @@ -9671,7 +9673,9 @@ static struct btrfs_trans_handle *insert_prealloc_file_extent( btrfs_set_stack_file_extent_num_bytes(&stack_fi, len); btrfs_set_stack_file_extent_ram_bytes(&stack_fi, len); btrfs_set_stack_file_extent_compression(&stack_fi, BTRFS_COMPRESS_NONE); - /* Encryption and other encoding is reserved and all 0 */ + btrfs_set_stack_file_extent_encryption(&stack_fi, + BTRFS_ENCRYPTION_NONE); + /* Other encoding is reserved and always 0 */ qgroup_released = btrfs_qgroup_release_data(inode, file_offset, len); if (qgroup_released < 0) diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c index 50fdc69fdddf..1af2c967436b 100644 --- a/fs/btrfs/tree-checker.c +++ b/fs/btrfs/tree-checker.c @@ -211,6 +211,7 @@ static int check_extent_data_item(struct extent_buffer *leaf, u32 sectorsize = fs_info->sectorsize; u32 item_size = btrfs_item_size(leaf, slot); u64 extent_end; + u8 policy; if (unlikely(!IS_ALIGNED(key->offset, sectorsize))) { file_extent_err(leaf, slot, @@ -262,10 +263,11 @@ static int check_extent_data_item(struct extent_buffer *leaf, BTRFS_NR_COMPRESS_TYPES - 1); return -EUCLEAN; } - if (unlikely(btrfs_file_extent_encryption(leaf, fi))) { + policy = btrfs_file_extent_encryption(leaf, fi); + if (unlikely(policy >= BTRFS_NR_ENCRYPTION_TYPES)) { file_extent_err(leaf, slot, - "invalid encryption for file extent, have %u expect 0", - btrfs_file_extent_encryption(leaf, fi)); + "invalid encryption for file extent, have %u expect range [0, %u]", + policy, BTRFS_NR_ENCRYPTION_TYPES - 1); return -EUCLEAN; } if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) { diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 89d3dc769b15..36063dc39443 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -4627,6 +4627,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans, u64 extent_offset = em->start - em->orig_start; u64 block_len; int ret; + u8 encryption = BTRFS_ENCRYPTION_NONE; btrfs_set_stack_file_extent_generation(&fi, trans->transid); if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) @@ -4648,6 +4649,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans, btrfs_set_stack_file_extent_num_bytes(&fi, em->len); btrfs_set_stack_file_extent_ram_bytes(&fi, em->ram_bytes); btrfs_set_stack_file_extent_compression(&fi, em->compress_type); + btrfs_set_stack_file_extent_encryption(&fi, encryption); ret = log_extent_csums(trans, inode, log, em, ctx); if (ret) diff --git a/include/uapi/linux/btrfs_tree.h b/include/uapi/linux/btrfs_tree.h index 08f561da33cd..af56a5eb3a00 100644 --- a/include/uapi/linux/btrfs_tree.h +++ b/include/uapi/linux/btrfs_tree.h @@ -1101,8 +1101,14 @@ struct btrfs_file_extent_item { * but not for stat. */ __u8 compression; + + /* + * Type of encryption in use. Unencrypted value is 0. + */ __u8 encryption; - __le16 other_encoding; /* spare for later use */ + + /* spare for later use */ + __le16 other_encoding; /* are we inline data or a real extent? */ __u8 type; From patchwork Fri Dec 1 22:11:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476509 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="1ep0p1mj" Received: from mail-yb1-xb2a.google.com (mail-yb1-xb2a.google.com [IPv6:2607:f8b0:4864:20::b2a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E20010DB for ; Fri, 1 Dec 2023 14:12:23 -0800 (PST) Received: by mail-yb1-xb2a.google.com with SMTP id 3f1490d57ef6-db549f869a3so1039855276.1 for ; Fri, 01 Dec 2023 14:12:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468742; x=1702073542; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zTK1Rkp+qKkPtMOondRTum0dicS58Ez8ls+Mvz2mZlQ=; b=1ep0p1mjJkVlhZX11vU5DY8ZCBp3LKKo0FqSd8WiWHs5kHowhMP7LLD4954IHuTAXW jbk1NeXR+TjqhIiEneMnV0V/w2I+4X8s/f/Gkc0g2OMmwMTR/dx3dQOf+DdtEU8tFOBd jtLPWc39dYs3lWnaH05/C9OsGQdvXXfzcgBTkqztB9qyRxr4CmJ6ZtUU/XshxQ3nbrsT mZofyFHth3P5tkjmTU+1LMfSYItvZN2fNyWiCby2WRq+Im2/Lp5f2QF2jqYxIT82rdyJ KbxmJgH0MMKlUdCFH7soZ5Do2pZt+K+N2lV7NjQzYnTRrRQWtzhHL7cYWk+yvDlWwrrB ysVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468742; x=1702073542; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zTK1Rkp+qKkPtMOondRTum0dicS58Ez8ls+Mvz2mZlQ=; b=a2NmQ7Ct8yh3WW7xAZ7YD6odBtZze3qz8gakjh075d0xBcH7Zv0CgbpzBhC4R5MihQ dfAIC/CUr7k+wIfvGROFc6F7JnXEMBdVIEM4FEYLf81HIjGyVsEaPxWMO7FHZISHxcqd EeH49ACwrAAgQPJUqYUBmtUMYXDl2XUXX2wJpIUnKtH/ZB0Gbn7H4p5RfZR83hUxTjmM DdjzX4JtzMDAFMi9o37KCAgk066RQoarAuIDIS10lDAtYRKh6DBjLN6d++WXykMN3OiZ oHFQ4iOepzdZPWOGzN9sYCsrQnQ10t6iIwZbO8N94+ia6Bu330qRgmzOg2HPocWs4xkh EQkQ== X-Gm-Message-State: AOJu0YzMh8F/X1uIXiV7Uzzu3oni1ee6VB97HzSB4C2B5Ax2lxw0TXz0 oTqPjAxOhc/laTCX5eoWpTWCE/W1CWMzmaRmS5Ri1Q== X-Google-Smtp-Source: AGHT+IHKmTurH/z9r6b/RFSMoEMbNd9b8W+3gOMRA7gV20MLjg3yfDEZdyHNaybPbj1oMwqJQQm+CA== X-Received: by 2002:a25:bc1:0:b0:db7:b6fb:7446 with SMTP id 184-20020a250bc1000000b00db7b6fb7446mr244480ybl.9.1701468742178; Fri, 01 Dec 2023 14:12:22 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id p5-20020a258185000000b00da086d6921fsm613029ybk.50.2023.12.01.14.12.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:21 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Sweet Tea Dorminy Subject: [PATCH v4 21/46] btrfs: add fscrypt_info and encryption_type to extent_map Date: Fri, 1 Dec 2023 17:11:18 -0500 Message-ID: <2bc7d813a291837430fca8f3656fb894665d2e14.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Sweet Tea Dorminy Each extent_map will end up with a pointer to its associated fscrypt_info if any, which should have the same lifetime as the extent_map. We are also going to need to track the encryption_type for the file extent items. Add the fscrypt_info to the extent_map, and the subsequent code for transferring it in the split and merge cases, as well as the code necessary to free them. A future patch will add the code to load them as appropriate. Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/extent_map.c | 39 +++++++++++++++++++++++++++++++++++---- fs/btrfs/extent_map.h | 2 ++ fs/btrfs/file-item.c | 1 + fs/btrfs/inode.c | 1 + 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 20d347fa6f8a..b87d26fe6785 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -59,6 +59,12 @@ struct extent_map *alloc_extent_map(void) return em; } +static void __free_extent_map(struct extent_map *em) +{ + fscrypt_put_extent_info(em->fscrypt_info); + kmem_cache_free(extent_map_cache, em); +} + /* * Drop the reference out on @em by one and free the structure if the reference * count hits zero. @@ -70,7 +76,7 @@ void free_extent_map(struct extent_map *em) if (refcount_dec_and_test(&em->refs)) { WARN_ON(extent_map_in_tree(em)); WARN_ON(!list_empty(&em->list)); - kmem_cache_free(extent_map_cache, em); + __free_extent_map(em); } } @@ -96,12 +102,24 @@ void free_extent_map_safe(struct extent_map_tree *tree, if (!em) return; - if (refcount_dec_and_test(&em->refs)) { - WARN_ON(extent_map_in_tree(em)); - WARN_ON(!list_empty(&em->list)); + if (!refcount_dec_and_test(&em->refs)) + return; + + WARN_ON(extent_map_in_tree(em)); + WARN_ON(!list_empty(&em->list)); + + /* + * We could take a lock freeing the fscrypt_info, so add this to the + * list of freed_extents to be freed later. + */ + if (em->fscrypt_info) { list_add_tail(&em->free_list, &tree->freed_extents); set_bit(EXTENT_MAP_TREE_PENDING_FREES, &tree->flags); + return; } + + /* Nothing scary here, just free the object. */ + __free_extent_map(em); } /* @@ -274,6 +292,12 @@ static int mergable_maps(struct extent_map *prev, struct extent_map *next) if (!list_empty(&prev->list) || !list_empty(&next->list)) return 0; + /* + * Don't merge adjacent encrypted maps. + */ + if (prev->fscrypt_info || next->fscrypt_info) + return 0; + ASSERT(next->block_start != EXTENT_MAP_DELALLOC && prev->block_start != EXTENT_MAP_DELALLOC); @@ -840,6 +864,8 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, split->generation = gen; split->flags = flags; split->compress_type = em->compress_type; + split->fscrypt_info = + fscrypt_get_extent_info(em->fscrypt_info); replace_extent_mapping(em_tree, em, split, modified); free_extent_map(split); split = split2; @@ -881,6 +907,8 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, split->orig_block_len = 0; } + split->fscrypt_info = + fscrypt_get_extent_info(em->fscrypt_info); if (extent_map_in_tree(em)) { replace_extent_mapping(em_tree, em, split, modified); @@ -1043,6 +1071,7 @@ int split_extent_map(struct btrfs_inode *inode, u64 start, u64 len, u64 pre, split_pre->flags = flags; split_pre->compress_type = em->compress_type; split_pre->generation = em->generation; + split_pre->fscrypt_info = fscrypt_get_extent_info(em->fscrypt_info); replace_extent_mapping(em_tree, em, split_pre, 1); @@ -1062,6 +1091,8 @@ int split_extent_map(struct btrfs_inode *inode, u64 start, u64 len, u64 pre, split_mid->flags = flags; split_mid->compress_type = em->compress_type; split_mid->generation = em->generation; + split_mid->fscrypt_info = fscrypt_get_extent_info(em->fscrypt_info); + add_extent_mapping(em_tree, split_mid, 1); /* Once for us */ diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index fb8905f88f7c..e1075cadfd94 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h @@ -48,8 +48,10 @@ struct extent_map { */ u64 generation; unsigned long flags; + struct fscrypt_extent_info *fscrypt_info; refcount_t refs; unsigned int compress_type; + unsigned int encryption_type; struct list_head list; struct list_head free_list; }; diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 45cae356e89b..26f35c1baedc 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -1305,6 +1305,7 @@ void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode, if (type == BTRFS_FILE_EXTENT_PREALLOC) set_bit(EXTENT_FLAG_PREALLOC, &em->flags); } + em->encryption_type = btrfs_file_extent_encryption(leaf, fi); } else if (type == BTRFS_FILE_EXTENT_INLINE) { em->block_start = EXTENT_MAP_INLINE; em->start = extent_start; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f894f5b5e786..5b1aea9f5f46 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7373,6 +7373,7 @@ static struct extent_map *create_io_em(struct btrfs_inode *inode, u64 start, set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); em->compress_type = compress_type; } + em->encryption_type = BTRFS_ENCRYPTION_NONE; ret = btrfs_replace_extent_map_range(inode, em, true); if (ret) { From patchwork Fri Dec 1 22:11:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476510 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="ag69eQnt" Received: from mail-yw1-x112b.google.com (mail-yw1-x112b.google.com [IPv6:2607:f8b0:4864:20::112b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 17C4310F4 for ; Fri, 1 Dec 2023 14:12:24 -0800 (PST) Received: by mail-yw1-x112b.google.com with SMTP id 00721157ae682-5d35a952943so24394167b3.3 for ; Fri, 01 Dec 2023 14:12:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468743; x=1702073543; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=rmF4uxZfMCODtKSUU/38ctU//N0K7aMAz+DrB4iNNOA=; b=ag69eQntN44PZaWezmodh8ZzZ2g1dGLZ4NcLMKNuNK6svISJ9ERWV5nx9iw0H5s5JB xUwiR686a8S4/1g2TiLzH3Uw1/+3dZN50mE+WlWtaTnMO60WmtHGv5oJlPua/VqGK3Fi YVjPBUwIH9oUBQFVec/sUDBOuywefnWI8coR9ngjG+/6TkWNqjQINqAWKG2MA4CkBxdt Lb56KoVuY+sQGtgrmFB3msgBkiUbrKno8DVrYPrZ6qFPby6vfCftx93AOqqUTUSuKBwR xlpUpO+qZq5PM9Y6doHOsoBPpNbd+C4LT+GmUSSBgmLSqWgJI4CAT4gLDAN0rZYokU1y 2d7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468743; x=1702073543; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=rmF4uxZfMCODtKSUU/38ctU//N0K7aMAz+DrB4iNNOA=; b=YyJN0qEJSDvoa3+INoCQl75/+1v4WyqMIxPgTyFMoqzkjt2bp7EfjDCDj6mQ36aNCQ ILplnkMzMuQj3R5+vS4p0sLkMIYjqvgPfr0Hq6C5JC47uYVuwBJcsbIey9er1eyzLdQp DAcJzIFD4wtZVkzufvi6zVXq1hdj/KPqBAU4CuM9wNoi5rAzLRJZadS6QE2vWah/DnHR 6W5W/Cce5jLejoOhOJ3Dlk5r/jKELYJ0aBcIdUm7/O4RcoREOljw2iWpbw5RQHUQk6oz x6ARmZK/FX5sEc3rxxdVnvJa1hH28aMoWXYlW0ngLgQNlVMCf0Wl1DmksgTa6SJXciXX 3CsQ== X-Gm-Message-State: AOJu0YzTC5eY6ooTBkaeYUR6Lpgy1+UQZS21c6KmXLajt2tIzJidAHZt 7lfBIfIVW0DVC5rHyQ2c2bkPi7YbTu0p9YWhP1X43Q== X-Google-Smtp-Source: AGHT+IG0LrsT+litWNSx7aIMV3+r4xWV76gGMR4vpcUIaBbJ7yXgEsZoTkztw9ru8vFiIEH7eEgwfQ== X-Received: by 2002:a05:690c:368f:b0:5cf:9a35:d406 with SMTP id fu15-20020a05690c368f00b005cf9a35d406mr301552ywb.34.1701468743146; Fri, 01 Dec 2023 14:12:23 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id d1-20020a0ddb01000000b005d427fea43bsm677174ywe.48.2023.12.01.14.12.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:22 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 22/46] btrfs: add fscrypt_info and encryption_type to ordered_extent Date: Fri, 1 Dec 2023 17:11:19 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We're going to need these to update the file extent items once the writes are complete. Add them and add the pieces necessary to assign them and free everything. Signed-off-by: Josef Bacik --- fs/btrfs/ordered-data.c | 2 ++ fs/btrfs/ordered-data.h | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 574e8a55e24a..27350dd50828 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -181,6 +181,7 @@ static struct btrfs_ordered_extent *alloc_ordered_extent( entry->bytes_left = num_bytes; entry->inode = igrab(&inode->vfs_inode); entry->compress_type = compress_type; + entry->encryption_type = BTRFS_ENCRYPTION_NONE; entry->truncated_len = (u64)-1; entry->qgroup_rsv = ret; entry->flags = flags; @@ -564,6 +565,7 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) list_del(&sum->list); kvfree(sum); } + fscrypt_put_extent_info(entry->fscrypt_info); kmem_cache_free(btrfs_ordered_extent_cache, entry); } } diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 127ef8bf0ffd..85ba9a381880 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h @@ -108,6 +108,9 @@ struct btrfs_ordered_extent { /* compression algorithm */ int compress_type; + /* encryption mode */ + int encryption_type; + /* Qgroup reserved space */ int qgroup_rsv; @@ -117,6 +120,9 @@ struct btrfs_ordered_extent { /* the inode we belong to */ struct inode *inode; + /* the fscrypt_info for this extent, if necessary */ + struct fscrypt_extent_info *fscrypt_info; + /* list of checksums for insertion when the extent io is done */ struct list_head list; From patchwork Fri Dec 1 22:11:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476511 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="IstI/onB" Received: from mail-yw1-x1135.google.com (mail-yw1-x1135.google.com [IPv6:2607:f8b0:4864:20::1135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 01D9510EA for ; Fri, 1 Dec 2023 14:12:25 -0800 (PST) Received: by mail-yw1-x1135.google.com with SMTP id 00721157ae682-5d3d0f862f7so18587087b3.0 for ; Fri, 01 Dec 2023 14:12:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468744; x=1702073544; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=ECsbNqk7e25qCTyOZ0B1DCO4cPIk26VYu5GvEvu1st4=; b=IstI/onBSksKYzVf6Mj3UZSbQZwivm11DLpFp27eunKOdKXw2LjXDDYu+owILpl8Jj fCrLGxFa+1gY7kpE1B6Fkb3iA72e0uCxQjK05aCN1OA4hwvL89BFnzN5lAPCxkRrBeRo zj0vkciHwmMue0+SSIe0vsIhahhEEXXLb2fwwKoXO8o3dDP4KYn7y+66Iiz+OdNEkNbQ cnrfA1mS8lOnCsmscXoKaWAwhwQTR2yTzFusWNuCNGsL2r5Qsota8lKqD5TUoieVki9Q AA/pUW96wMh5JYkJX+m3OwntkWtg8WGdaLo68pu7UfL3WjQyJPhoSUHq14TfVK+F70ty FJMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468744; x=1702073544; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ECsbNqk7e25qCTyOZ0B1DCO4cPIk26VYu5GvEvu1st4=; b=vx/XB8fyiOGSqCR/KC+k/MjyVkiIJQkNRFj1V132p9yqxzrKhYH12tmjo+4I5bu2c6 84ATv5sDcQu4TmVAbBRIcOHdCheZTeoIFX14YZBLpFO+YEaYlxTZaiW8zZWS4BKhE0vu ejW6eS9Q2sxqW7bPOB7AVnPe8xsBgHLL5h3BBpfx+bXRNMwi4XkeSB1sUOnHoc4JuWpb UWMAswFvnoRmcLxFbOro9709x7QC3G1d7aJ/xovlZlCz7o5wAFA9eYmAA0AWbqe90AQj GLXF3Fd0t3LiYl+scNYIiydUonUhtBs8/06EkAK/li+1DzNWmKqxccncNbNSiNlb2xUP N/BQ== X-Gm-Message-State: AOJu0YxPwNPirfdkZ/TxHQxecFWi2LiRFV36qxL2OoV9cy69MDpa6IIP l4sVeWiVN43q7EUCbFP/sznnqN9YQMlAFKO23YZ2bA== X-Google-Smtp-Source: AGHT+IFXRlEIXJmhzgWxdWPuqeivMeWTmnJ0wTj3kE6YB5CkE+oqtHmV9ymTBgNEXAmD8a8vidqtvw== X-Received: by 2002:a81:7845:0:b0:5d7:1940:b37a with SMTP id t66-20020a817845000000b005d71940b37amr168736ywc.70.1701468744098; Fri, 01 Dec 2023 14:12:24 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id u189-20020a8179c6000000b005d34a381f59sm1359711ywc.102.2023.12.01.14.12.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:23 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 23/46] btrfs: plumb through setting the fscrypt_info for ordered extents Date: Fri, 1 Dec 2023 17:11:20 -0500 Message-ID: <7c9457e4e001b42fbb3f190334e954124765e50b.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We're going to be getting fscrypt_info from the extent maps, update the helpers to take an fscrypt_info argument and use that to set the encryption type on the ordered extent. Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 20 +++++++++++--------- fs/btrfs/ordered-data.c | 32 ++++++++++++++++++++------------ fs/btrfs/ordered-data.h | 9 +++++---- 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5b1aea9f5f46..83d653376deb 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1171,7 +1171,8 @@ static void submit_one_async_extent(struct async_chunk *async_chunk, } free_extent_map(em); - ordered = btrfs_alloc_ordered_extent(inode, start, /* file_offset */ + ordered = btrfs_alloc_ordered_extent(inode, NULL, + start, /* file_offset */ async_extent->ram_size, /* num_bytes */ async_extent->ram_size, /* ram_bytes */ ins.objectid, /* disk_bytenr */ @@ -1434,9 +1435,10 @@ static noinline int cow_file_range(struct btrfs_inode *inode, } free_extent_map(em); - ordered = btrfs_alloc_ordered_extent(inode, start, ram_size, - ram_size, ins.objectid, cur_alloc_size, - 0, 1 << BTRFS_ORDERED_REGULAR, + ordered = btrfs_alloc_ordered_extent(inode, NULL, + start, ram_size, ram_size, ins.objectid, + cur_alloc_size, 0, + 1 << BTRFS_ORDERED_REGULAR, BTRFS_COMPRESS_NONE); if (IS_ERR(ordered)) { ret = PTR_ERR(ordered); @@ -2167,7 +2169,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, free_extent_map(em); } - ordered = btrfs_alloc_ordered_extent(inode, cur_offset, + ordered = btrfs_alloc_ordered_extent(inode, NULL, cur_offset, nocow_args.num_bytes, nocow_args.num_bytes, nocow_args.disk_bytenr, nocow_args.num_bytes, 0, is_prealloc @@ -7058,7 +7060,7 @@ static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode, if (IS_ERR(em)) goto out; } - ordered = btrfs_alloc_ordered_extent(inode, start, len, len, + ordered = btrfs_alloc_ordered_extent(inode, NULL, start, len, len, block_start, block_len, 0, (1 << type) | (1 << BTRFS_ORDERED_DIRECT), @@ -10543,9 +10545,9 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from, } free_extent_map(em); - ordered = btrfs_alloc_ordered_extent(inode, start, num_bytes, ram_bytes, - ins.objectid, ins.offset, - encoded->unencoded_offset, + ordered = btrfs_alloc_ordered_extent(inode, NULL, start, + num_bytes, ram_bytes, ins.objectid, + ins.offset, encoded->unencoded_offset, (1 << BTRFS_ORDERED_ENCODED) | (1 << BTRFS_ORDERED_COMPRESSED), compression); diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 27350dd50828..ee3138a6d11e 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -146,9 +146,11 @@ static inline struct rb_node *ordered_tree_search(struct btrfs_inode *inode, } static struct btrfs_ordered_extent *alloc_ordered_extent( - struct btrfs_inode *inode, u64 file_offset, u64 num_bytes, - u64 ram_bytes, u64 disk_bytenr, u64 disk_num_bytes, - u64 offset, unsigned long flags, int compress_type) + struct btrfs_inode *inode, + struct fscrypt_extent_info *fscrypt_info, + u64 file_offset, u64 num_bytes, u64 ram_bytes, + u64 disk_bytenr, u64 disk_num_bytes, u64 offset, + unsigned long flags, int compress_type) { struct btrfs_ordered_extent *entry; int ret; @@ -181,10 +183,12 @@ static struct btrfs_ordered_extent *alloc_ordered_extent( entry->bytes_left = num_bytes; entry->inode = igrab(&inode->vfs_inode); entry->compress_type = compress_type; - entry->encryption_type = BTRFS_ENCRYPTION_NONE; entry->truncated_len = (u64)-1; entry->qgroup_rsv = ret; entry->flags = flags; + entry->fscrypt_info = fscrypt_get_extent_info(fscrypt_info); + entry->encryption_type = entry->fscrypt_info ? + BTRFS_ENCRYPTION_FSCRYPT : BTRFS_ENCRYPTION_NONE; refcount_set(&entry->refs, 1); init_waitqueue_head(&entry->wait); INIT_LIST_HEAD(&entry->list); @@ -247,6 +251,7 @@ static void insert_ordered_extent(struct btrfs_ordered_extent *entry) * Add an ordered extent to the per-inode tree. * * @inode: Inode that this extent is for. + * @fscrypt_info: The fscrypt_extent_info for this extent, if necessary. * @file_offset: Logical offset in file where the extent starts. * @num_bytes: Logical length of extent in file. * @ram_bytes: Full length of unencoded data. @@ -263,17 +268,19 @@ static void insert_ordered_extent(struct btrfs_ordered_extent *entry) * Return: the new ordered extent or error pointer. */ struct btrfs_ordered_extent *btrfs_alloc_ordered_extent( - struct btrfs_inode *inode, u64 file_offset, - u64 num_bytes, u64 ram_bytes, u64 disk_bytenr, - u64 disk_num_bytes, u64 offset, unsigned long flags, - int compress_type) + struct btrfs_inode *inode, + struct fscrypt_extent_info *fscrypt_info, + u64 file_offset, u64 num_bytes, u64 ram_bytes, + u64 disk_bytenr, u64 disk_num_bytes, u64 offset, + unsigned long flags, int compress_type) { struct btrfs_ordered_extent *entry; ASSERT((flags & ~BTRFS_ORDERED_TYPE_FLAGS) == 0); - entry = alloc_ordered_extent(inode, file_offset, num_bytes, ram_bytes, - disk_bytenr, disk_num_bytes, offset, flags, + entry = alloc_ordered_extent(inode, fscrypt_info, file_offset, + num_bytes, ram_bytes, disk_bytenr, + disk_num_bytes, offset, flags, compress_type); if (!IS_ERR(entry)) insert_ordered_extent(entry); @@ -1166,8 +1173,9 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent( if (WARN_ON_ONCE(ordered->disk_num_bytes != ordered->num_bytes)) return ERR_PTR(-EINVAL); - new = alloc_ordered_extent(inode, file_offset, len, len, disk_bytenr, - len, 0, flags, ordered->compress_type); + new = alloc_ordered_extent(inode, ordered->fscrypt_info, file_offset, + len, len, disk_bytenr, len, 0, flags, + ordered->compress_type); if (IS_ERR(new)) return new; diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 85ba9a381880..57ca8ce6eb6d 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h @@ -163,10 +163,11 @@ bool btrfs_dec_test_ordered_pending(struct btrfs_inode *inode, struct btrfs_ordered_extent **cached, u64 file_offset, u64 io_size); struct btrfs_ordered_extent *btrfs_alloc_ordered_extent( - struct btrfs_inode *inode, u64 file_offset, - u64 num_bytes, u64 ram_bytes, u64 disk_bytenr, - u64 disk_num_bytes, u64 offset, unsigned long flags, - int compress_type); + struct btrfs_inode *inode, + struct fscrypt_extent_info *fscrypt_info, + u64 file_offset, u64 num_bytes, u64 ram_bytes, + u64 disk_bytenr, u64 disk_num_bytes, u64 offset, + unsigned long flags, int compress_type); void btrfs_add_ordered_sum(struct btrfs_ordered_extent *entry, struct btrfs_ordered_sum *sum); struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct btrfs_inode *inode, From patchwork Fri Dec 1 22:11:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476512 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="oJhpZ1cd" Received: from mail-yb1-xb2e.google.com (mail-yb1-xb2e.google.com [IPv6:2607:f8b0:4864:20::b2e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E2F6B128 for ; Fri, 1 Dec 2023 14:12:25 -0800 (PST) Received: by mail-yb1-xb2e.google.com with SMTP id 3f1490d57ef6-db5e5647c24so801321276.1 for ; Fri, 01 Dec 2023 14:12:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468745; x=1702073545; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=wVMEIuPyFk0UJVVDGNAANRB18O7eDV0fbcVAkCK7tns=; b=oJhpZ1cdahfk4PB2leOlA3UBPvzrUhWRpVmKMphmXY909mnvdWhZhltXykJEpu7lgk R1lB+vo+4zpO6/9uD4qaLtAI1HE76207LB2YWr5JYBUgH8bwClJ9jijC/bsNyAsfxUXa +Hc5603CzDd+KFgm3wobKClMePrxoa0PHY55Lb2tgH3oA9e39o/Mnn8SFQ3E5WvD5qO3 QTn6Te2Xff6KUEmfCo28Zx7cVnh4FlCFav8o8Fw+TC2dADsbs8S/B2+RRNFnP5yLFj1K VxXsz+8P5D9MFx1xo4YGfl7Z7o+LFjv9bw1Yc8jb+CdXJDV1WUiCCt8YoM1njeZDt6mV crsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468745; x=1702073545; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wVMEIuPyFk0UJVVDGNAANRB18O7eDV0fbcVAkCK7tns=; b=nWPQRyQ6sf1BOjPHNRHWryHMK5ubrmkUP6kKIRwGZc6SB9WT6av8dG8isSqSrSnuhP /GmZ7tCAoSZA6znOVDQeqVJeO0ch1YdPxqtiqK1CpqUU/4Aw41pZF8sjuR/F4GPj7yxS k0wSPIv2DinzU2kscLtzaeTL7HsPzZAPhIJI6udOxMF0xgcTVbZmbcNZ23U8aBZIIR4N 8A8G/iglbp+VCKZ5HTUYrkkPHeUvGwYkxgV9rNBghPFzHOzJDe2L4hgyxrtfse2KIKyw grtm+VZPEh2xXNq+rzyh/FcPwsdRlM3fCSg5cKT8KK6gaU1cCMUdidzu5MRmkgSVDRQV MKjw== X-Gm-Message-State: AOJu0YzewWMMMhV28yB9NkNUPTOF8/qnKxWpwipHqE46cEaU6J0DNmR9 J3n4kO5GdeeEPvGfgiNiVKAIsz8Mg1GaG6QlcyPrGw== X-Google-Smtp-Source: AGHT+IGL+TuLPtA3yVi7sUzk54735kxowGtQwrFaP3ucpcX739HW39tw7HQhc25cSM22SGGoQ6bbzA== X-Received: by 2002:a05:690c:368d:b0:5d7:1940:3efb with SMTP id fu13-20020a05690c368d00b005d719403efbmr153365ywb.44.1701468744993; Fri, 01 Dec 2023 14:12:24 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id m20-20020a819c14000000b005a4da74b869sm695899ywa.139.2023.12.01.14.12.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:24 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 24/46] btrfs: plumb the fscrypt extent context through create_io_em Date: Fri, 1 Dec 2023 17:11:21 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 For prealloc extents we create an em, since we already have the context loaded from the original prealloc extent creation we need to pre-populate the extent map fscrypt info so it can be read properly later if the pages are evicted. Add the argument for create_io_em and set it to NULL until we're ready to populate it properly. Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 83d653376deb..837d7a3969d1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -140,11 +140,12 @@ static noinline int run_delalloc_cow(struct btrfs_inode *inode, struct page *locked_page, u64 start, u64 end, struct writeback_control *wbc, bool pages_dirty); -static struct extent_map *create_io_em(struct btrfs_inode *inode, u64 start, - u64 len, u64 orig_start, u64 block_start, - u64 block_len, u64 orig_block_len, - u64 ram_bytes, int compress_type, - int type); +static struct extent_map *create_io_em(struct btrfs_inode *inode, + struct fscrypt_extent_info *fscrypt_info, + u64 start, u64 len, u64 orig_start, + u64 block_start, u64 block_len, + u64 orig_block_len, u64 ram_bytes, + int compress_type, int type); static int data_reloc_print_warning_inode(u64 inum, u64 offset, u64 num_bytes, u64 root, void *warn_ctx) @@ -1156,7 +1157,7 @@ static void submit_one_async_extent(struct async_chunk *async_chunk, } /* Here we're doing allocation and writeback of the compressed pages */ - em = create_io_em(inode, start, + em = create_io_em(inode, NULL, start, async_extent->ram_size, /* len */ start, /* orig_start */ ins.objectid, /* block_start */ @@ -1421,7 +1422,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode, extent_reserved = true; ram_size = ins.offset; - em = create_io_em(inode, start, ins.offset, /* len */ + em = create_io_em(inode, NULL, start, ins.offset, /* len */ start, /* orig_start */ ins.objectid, /* block_start */ ins.offset, /* block_len */ @@ -2154,7 +2155,8 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, u64 orig_start = found_key.offset - nocow_args.extent_offset; struct extent_map *em; - em = create_io_em(inode, cur_offset, nocow_args.num_bytes, + em = create_io_em(inode, NULL, cur_offset, + nocow_args.num_bytes, orig_start, nocow_args.disk_bytenr, /* block_start */ nocow_args.num_bytes, /* block_len */ @@ -7053,8 +7055,9 @@ static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode, struct btrfs_ordered_extent *ordered; if (type != BTRFS_ORDERED_NOCOW) { - em = create_io_em(inode, start, len, orig_start, block_start, - block_len, orig_block_len, ram_bytes, + em = create_io_em(inode, NULL, start, len, orig_start, + block_start, block_len, orig_block_len, + ram_bytes, BTRFS_COMPRESS_NONE, /* compress_type */ type); if (IS_ERR(em)) @@ -7342,11 +7345,12 @@ static int lock_extent_direct(struct inode *inode, u64 lockstart, u64 lockend, } /* The callers of this must take lock_extent() */ -static struct extent_map *create_io_em(struct btrfs_inode *inode, u64 start, - u64 len, u64 orig_start, u64 block_start, - u64 block_len, u64 orig_block_len, - u64 ram_bytes, int compress_type, - int type) +static struct extent_map *create_io_em(struct btrfs_inode *inode, + struct fscrypt_extent_info *fscrypt_info, + u64 start, u64 len, u64 orig_start, + u64 block_start, u64 block_len, + u64 orig_block_len, u64 ram_bytes, + int compress_type, int type) { struct extent_map *em; int ret; @@ -10535,7 +10539,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from, goto out_delalloc_release; extent_reserved = true; - em = create_io_em(inode, start, num_bytes, + em = create_io_em(inode, NULL, start, num_bytes, start - encoded->unencoded_offset, ins.objectid, ins.offset, ins.offset, ram_bytes, compression, BTRFS_ORDERED_COMPRESSED); From patchwork Fri Dec 1 22:11:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476513 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="FdEtEq/f" Received: from mail-yw1-x1129.google.com (mail-yw1-x1129.google.com [IPv6:2607:f8b0:4864:20::1129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 318DD10EF for ; Fri, 1 Dec 2023 14:12:27 -0800 (PST) Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-5d3d0f862f7so18587267b3.0 for ; Fri, 01 Dec 2023 14:12:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468746; x=1702073546; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=ek5VDxe4u6nMgsTGQg53bhX64gutAEVKYEBo1llkfyg=; b=FdEtEq/f/xAsuYy9NEFOX7JFkTwW4/PDUx9tNQtPhCLLV8vBv56KKN1sMN6ygVz8H+ CBJp4zLnT8lEaDJRBsd4cx/CEvn39JBARKTARE4kmDVj+uGjSZ/N0hAAdpDyv7jWJkJg XB2WWJx3DXsphBmhWvQGjbW+UmX+2pWaqJMY1XgJcf0TP13fgjZ2treUOG2ycQcfqzSA /GLoqrkj2Nj96idYrYVDj3lbDy+WO+GVhKz4wDO1DwNUiiTQKoTjPedVZ5mLx7UdaYqC swFuf1QtpB2nPDgCMzNG9/Y+wFQZ72JOS/NqnznskPjqqUWwQQ/eKr/LcO0uq8Bj1hkP 5Xqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468746; x=1702073546; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ek5VDxe4u6nMgsTGQg53bhX64gutAEVKYEBo1llkfyg=; b=crngDf5rYzjTEFMeHulCdx9hOq0GYQTeW3vC4H51ICgtHRbwUFcBOIcnPAe6sWqKGd BrtxXD52aAdLtC3memkUO1UkzGJ08/qUxxDS+Y6YsR99GLTIev/HgZWiaUHJ3T5FR33H 4OzoopjMOnQ4Ti6VOES7UiNTuGEHMd32mekmTboEzEeZVVGzXfDF0rhNnEkuXCrBOxTk 9FKXzobKzLSeAYJ3EfOJwry6MM/QoJInoQ/mzm5fExF9JBDw2xXfKf+Z65P5s2BCfga5 7ZLCYZJk1Xj27hAjX7c36ViC1w9d4dVPFdiKtnY3b69MFEg0C8KCrEIhLysos/vMdaFz TUUw== X-Gm-Message-State: AOJu0YzfFl3HKoouckaxLiwBc7ciVKTZAIR7WbE3KZLdKQSK3P9gdyUH Srv2+uGFk3nUE/dMt0G3Xb4mLjXNaq/1R/GT+01TTA== X-Google-Smtp-Source: AGHT+IFU62CwfBowml7OMWcFxDo2470t9e0vP430EQGlaT5wyCBNIv9Bm+1IRruiXnSoIb32Me7FDA== X-Received: by 2002:a0d:d40c:0:b0:5d7:1940:b38e with SMTP id w12-20020a0dd40c000000b005d71940b38emr167008ywd.90.1701468746222; Fri, 01 Dec 2023 14:12:26 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id x67-20020a817c46000000b0057a8de72338sm1375955ywc.68.2023.12.01.14.12.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:25 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 25/46] btrfs: populate the ordered_extent with the fscrypt context Date: Fri, 1 Dec 2023 17:11:22 -0500 Message-ID: <6ef7620cd1bfaf1592549de0898c81c9b953b395.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The fscrypt_extent_info will be tied to the extent_map lifetime, so it will be created when we create the IO em, or it'll already exist in the NOCOW case. Use this fscrypt_info when creating the ordered extent to make sure everything is passed through properly. Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 77 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 21 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 837d7a3969d1..9c704b1cfe05 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1170,9 +1170,8 @@ static void submit_one_async_extent(struct async_chunk *async_chunk, ret = PTR_ERR(em); goto out_free_reserve; } - free_extent_map(em); - ordered = btrfs_alloc_ordered_extent(inode, NULL, + ordered = btrfs_alloc_ordered_extent(inode, em->fscrypt_info, start, /* file_offset */ async_extent->ram_size, /* num_bytes */ async_extent->ram_size, /* ram_bytes */ @@ -1181,6 +1180,7 @@ static void submit_one_async_extent(struct async_chunk *async_chunk, 0, /* offset */ 1 << BTRFS_ORDERED_COMPRESSED, async_extent->compress_type); + free_extent_map(em); if (IS_ERR(ordered)) { btrfs_drop_extent_map_range(inode, start, end, false); ret = PTR_ERR(ordered); @@ -1434,13 +1434,13 @@ static noinline int cow_file_range(struct btrfs_inode *inode, ret = PTR_ERR(em); goto out_reserve; } - free_extent_map(em); - ordered = btrfs_alloc_ordered_extent(inode, NULL, + ordered = btrfs_alloc_ordered_extent(inode, em->fscrypt_info, start, ram_size, ram_size, ins.objectid, cur_alloc_size, 0, 1 << BTRFS_ORDERED_REGULAR, BTRFS_COMPRESS_NONE); + free_extent_map(em); if (IS_ERR(ordered)) { ret = PTR_ERR(ordered); goto out_drop_extent_cache; @@ -2013,6 +2013,8 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, struct btrfs_key found_key; struct btrfs_file_extent_item *fi; struct extent_buffer *leaf; + struct extent_map *em = NULL; + struct fscrypt_extent_info *fscrypt_info = NULL; u64 extent_end; u64 ram_bytes; u64 nocow_end; @@ -2149,13 +2151,29 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, } } + /* + * We only want to do this lookup if we're encrypted, otherwise + * fsrypt_info will be null and we can avoid this lookup. + */ + if (IS_ENCRYPTED(&inode->vfs_inode)) { + em = btrfs_get_extent(inode, NULL, 0, cur_offset, + nocow_args.num_bytes); + if (IS_ERR(em)) { + btrfs_dec_nocow_writers(nocow_bg); + ret = PTR_ERR(em); + goto error; + } + fscrypt_info = fscrypt_get_extent_info(em->fscrypt_info); + free_extent_map(em); + em = NULL; + } + nocow_end = cur_offset + nocow_args.num_bytes - 1; is_prealloc = extent_type == BTRFS_FILE_EXTENT_PREALLOC; if (is_prealloc) { u64 orig_start = found_key.offset - nocow_args.extent_offset; - struct extent_map *em; - em = create_io_em(inode, NULL, cur_offset, + em = create_io_em(inode, fscrypt_info, cur_offset, nocow_args.num_bytes, orig_start, nocow_args.disk_bytenr, /* block_start */ @@ -2164,6 +2182,7 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, ram_bytes, BTRFS_COMPRESS_NONE, BTRFS_ORDERED_PREALLOC); if (IS_ERR(em)) { + fscrypt_put_extent_info(fscrypt_info); btrfs_dec_nocow_writers(nocow_bg); ret = PTR_ERR(em); goto error; @@ -2171,13 +2190,15 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, free_extent_map(em); } - ordered = btrfs_alloc_ordered_extent(inode, NULL, cur_offset, - nocow_args.num_bytes, nocow_args.num_bytes, - nocow_args.disk_bytenr, nocow_args.num_bytes, 0, + ordered = btrfs_alloc_ordered_extent(inode, fscrypt_info, + cur_offset, nocow_args.num_bytes, + nocow_args.num_bytes, nocow_args.disk_bytenr, + nocow_args.num_bytes, 0, is_prealloc ? (1 << BTRFS_ORDERED_PREALLOC) : (1 << BTRFS_ORDERED_NOCOW), BTRFS_COMPRESS_NONE); + fscrypt_put_extent_info(fscrypt_info); btrfs_dec_nocow_writers(nocow_bg); if (IS_ERR(ordered)) { if (is_prealloc) { @@ -7042,6 +7063,7 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode, static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode, struct btrfs_dio_data *dio_data, + struct extent_map *orig_em, const u64 start, const u64 len, const u64 orig_start, @@ -7053,18 +7075,24 @@ static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode, { struct extent_map *em = NULL; struct btrfs_ordered_extent *ordered; + struct fscrypt_extent_info *fscrypt_info = NULL; + + if (orig_em) + fscrypt_info = orig_em->fscrypt_info; if (type != BTRFS_ORDERED_NOCOW) { - em = create_io_em(inode, NULL, start, len, orig_start, + em = create_io_em(inode, fscrypt_info, start, len, orig_start, block_start, block_len, orig_block_len, ram_bytes, BTRFS_COMPRESS_NONE, /* compress_type */ type); if (IS_ERR(em)) goto out; + fscrypt_info = em->fscrypt_info; } - ordered = btrfs_alloc_ordered_extent(inode, NULL, start, len, len, - block_start, block_len, 0, + + ordered = btrfs_alloc_ordered_extent(inode, fscrypt_info, start, len, + len, block_start, block_len, 0, (1 << type) | (1 << BTRFS_ORDERED_DIRECT), BTRFS_COMPRESS_NONE); @@ -7108,9 +7136,10 @@ static struct extent_map *btrfs_new_extent_direct(struct btrfs_inode *inode, if (ret) return ERR_PTR(ret); - em = btrfs_create_dio_extent(inode, dio_data, start, ins.offset, start, - ins.objectid, ins.offset, ins.offset, - ins.offset, BTRFS_ORDERED_REGULAR); + em = btrfs_create_dio_extent(inode, dio_data, NULL, start, ins.offset, + start, ins.objectid, ins.offset, + ins.offset, ins.offset, + BTRFS_ORDERED_REGULAR); btrfs_dec_block_group_reservations(fs_info, ins.objectid); if (IS_ERR(em)) btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, @@ -7379,7 +7408,13 @@ static struct extent_map *create_io_em(struct btrfs_inode *inode, set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); em->compress_type = compress_type; } - em->encryption_type = BTRFS_ENCRYPTION_NONE; + + if (fscrypt_info) { + em->encryption_type = BTRFS_ENCRYPTION_FSCRYPT; + em->fscrypt_info = fscrypt_get_extent_info(fscrypt_info); + } else { + em->encryption_type = BTRFS_ENCRYPTION_NONE; + } ret = btrfs_replace_extent_map_range(inode, em, true); if (ret) { @@ -7455,9 +7490,9 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map, } space_reserved = true; - em2 = btrfs_create_dio_extent(BTRFS_I(inode), dio_data, start, len, - orig_start, block_start, - len, orig_block_len, + em2 = btrfs_create_dio_extent(BTRFS_I(inode), dio_data, em, + start, len, orig_start, + block_start, len, orig_block_len, ram_bytes, type); btrfs_dec_nocow_writers(bg); if (type == BTRFS_ORDERED_PREALLOC) { @@ -10547,14 +10582,14 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from, ret = PTR_ERR(em); goto out_free_reserved; } - free_extent_map(em); - ordered = btrfs_alloc_ordered_extent(inode, NULL, start, + ordered = btrfs_alloc_ordered_extent(inode, em->fscrypt_info, start, num_bytes, ram_bytes, ins.objectid, ins.offset, encoded->unencoded_offset, (1 << BTRFS_ORDERED_ENCODED) | (1 << BTRFS_ORDERED_COMPRESSED), compression); + free_extent_map(em); if (IS_ERR(ordered)) { btrfs_drop_extent_map_range(inode, start, end, false); ret = PTR_ERR(ordered); From patchwork Fri Dec 1 22:11:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476514 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="mPl+enRh" Received: from mail-yw1-x1129.google.com (mail-yw1-x1129.google.com [IPv6:2607:f8b0:4864:20::1129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1304410DB for ; Fri, 1 Dec 2023 14:12:28 -0800 (PST) Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-5cd81e76164so29418627b3.1 for ; Fri, 01 Dec 2023 14:12:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468747; x=1702073547; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=9mgqq6E721isnoR2dH2C/hG8cphDsR22LsNDoTUSxfc=; b=mPl+enRhConyUzPaV8kPHSruBzynmVEIJuUeKWTGvTROkAmgKOIjhQiLw6An8DkP/8 Mw4hH6PzDEQ0+cKOGkA2GGk/l0cNxqoPVjXPcl/2dUt6/aDWbgc+FSJSvy1T0nrbw5JY iLdVj4RgGiMgoBkGbIq7P7q09cSrw+VKPqrrzX9xZVTLbwDg66JRWtVbT9zsiKoJHYOm 0cERtPNYojpjnew83rkBdT3X+iAvPtdwa7KhXSfHq449/JrpnUwRoCYpHego7K5dgv9T HqyutrYi7/27B612SjPF0vqC615s3BX3PtSWZqzT5XIroRF1WJOyr6If2z/eorR/gSb4 dpmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468747; x=1702073547; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9mgqq6E721isnoR2dH2C/hG8cphDsR22LsNDoTUSxfc=; b=eh3SCdbVZKLt88/4p4ivFGVwcWbiMw0GlmwBew//FKL/3La2xleskrtgs77TvvG7oG dcImNjWlX1AvX3cNb1ZiYinuk4QVQLgMg6MbsHfeuzxRlwHaXykuZ2UqPHCHAYIQklC6 qyHWj2UkcQDppKOiXh4lrsctXmBMqaizCWMiLUItQR9m6BGiXl/83sqRATNd+zIM0ROg lZ1kLDA50RSwKZRZ3jwC+OUeVIXLcUsEnlWbwBXWzJ7xtTEiJVj2exccVVWdPle/eVn6 KgiIEODiVFE7EwlmYnxmOJ9W6kosocgTSjnpczzqVhJZAsznu8I+qCzgaD9Hu9fvcqbI LErA== X-Gm-Message-State: AOJu0Yx7Ke/qhnuhrIGHLC+ZJojXZPrtVbGRf6Jksa/XKE/Xl8i1PP4c 73CwR/2qpdjK1mclBI+GEEPORpq5X3bRg782yYISKQ== X-Google-Smtp-Source: AGHT+IHt7hvUvh7DsYdtQPnlAuZ8fHvTnnhmbNy558zezYxZ3eRdR17HSWBvqeyrMYhURbY+W1G15g== X-Received: by 2002:a0d:eaca:0:b0:5d7:1940:dd7f with SMTP id t193-20020a0deaca000000b005d71940dd7fmr176879ywe.85.1701468747192; Fri, 01 Dec 2023 14:12:27 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id i2-20020a816d02000000b005d721755ca8sm64192ywc.29.2023.12.01.14.12.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:26 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 26/46] btrfs: keep track of fscrypt info and orig_start for dio reads Date: Fri, 1 Dec 2023 17:11:23 -0500 Message-ID: <5e74c0395e4f58082b9446fb0105c0cb99e8338d.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We keep track of this information in the ordered extent for writes, but we need it for reads as well. Add fscrypt_extent_info and orig_start to the dio_data so we can populate this on reads. This will be used later when we attach the fscrypt context to the bios. Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9c704b1cfe05..dbdc01f25215 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -83,6 +83,8 @@ struct btrfs_dio_data { ssize_t submitted; struct extent_changeset *data_reserved; struct btrfs_ordered_extent *ordered; + struct fscrypt_extent_info *fscrypt_info; + u64 orig_start; bool data_space_reserved; bool nocow_done; }; @@ -7767,6 +7769,10 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start, release_len); } } else { + dio_data->fscrypt_info = + fscrypt_get_extent_info(em->fscrypt_info); + dio_data->orig_start = em->orig_start; + /* * We need to unlock only the end area that we aren't using. * The rest is going to be unlocked by the endio routine. @@ -7848,6 +7854,11 @@ static int btrfs_dio_iomap_end(struct inode *inode, loff_t pos, loff_t length, dio_data->ordered = NULL; } + if (dio_data->fscrypt_info) { + fscrypt_put_extent_info(dio_data->fscrypt_info); + dio_data->fscrypt_info = NULL; + } + if (write) extent_changeset_free(dio_data->data_reserved); return ret; From patchwork Fri Dec 1 22:11:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476515 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="NKx4qtXj" Received: from mail-yw1-x1133.google.com (mail-yw1-x1133.google.com [IPv6:2607:f8b0:4864:20::1133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4D1310EA for ; Fri, 1 Dec 2023 14:12:33 -0800 (PST) Received: by mail-yw1-x1133.google.com with SMTP id 00721157ae682-5d34d85e610so25972227b3.3 for ; Fri, 01 Dec 2023 14:12:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468752; x=1702073552; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=b9RfA7n1NXi8m/qaMDWuy5KBTwX4TEpS23gnV0lnWV4=; b=NKx4qtXjLjSB5aBO9Bwa6rO8ZnxWfBBcXEVJhYtwlSpnyLLOngUP9Xg0Z+VTiuDyIW 4kInL3dW+yfg3W6amJBun9BKzX7a28OIF0WkErKyXu93PBb2O3vmeUo2sWqZutVAjypo cEc8m1OLzEFC4IJrnksyv6OCCyoFko5SIcO82wT4pox7+t/xv+SKngd0NcI02b4f/ELN uImqEiCDXrpeFhjLEdsd3H6OiVf78uK4RlZjHl1pCPfNoS8X0F4FRg2UfT/tHypo/pDq 3gOUPYu3o7SeBaiNxAb6Wi0CzuLMweJY01M/iJOrtjUPOjOYPC5WNzkvw0+TZEjslA6s bVAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468752; x=1702073552; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=b9RfA7n1NXi8m/qaMDWuy5KBTwX4TEpS23gnV0lnWV4=; b=QT6HhA3ESfPpL2znq1uNo+rDulABmui0+A6u0UOpOJM2IDrcVrctptOar89mwACHA4 fvM3rMKXWNkJWHjVou7D8+gEh3rBCOW040qI+iVHMNFkLQtRW1DzgCh2ftUjdvEyYu/W idmouqUv5jRzdfUr77f8JaPbsEnQLDeAoCcyHw8eB/fyiDzfnMKTgnOKz29S32Pmy/73 5sudn+HgwmHOrBLMpjOTMUwfgxJY2RC2qHLGOPXs/4MYU2WwYIQPYscJL+F2SBkIRCT9 t43aSBm5DMUT2y7AgQ9T9C4AfIR1sYjW50P+/GyKx4gBm4StX7p1oA98SIj9R6mduUdo p8kA== X-Gm-Message-State: AOJu0Yy+X5JOOyM1uCeJXr9MT+BFEOMTBIzM7HtYNTIrK1MqqPyp0cNd RkqumuIcj7DlMY4QvaGvAyW9SsbbVah9pwRwSMgEzg== X-Google-Smtp-Source: AGHT+IHqbgggU/vawI/jybppcyduEYAhOOVPOFkmFa78aSx7RFWPDkf+/WsDgsI+VThZcRo1G2yC9Q== X-Received: by 2002:a0d:ca46:0:b0:5d7:1940:7d72 with SMTP id m67-20020a0dca46000000b005d719407d72mr210426ywd.73.1701468752718; Fri, 01 Dec 2023 14:12:32 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id m184-20020a0dcac1000000b005c862c66ffasm1395957ywd.16.2023.12.01.14.12.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:27 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 27/46] btrfs: add an optional encryption context to the end of file extents Date: Fri, 1 Dec 2023 17:11:24 -0500 Message-ID: <1babac314ded699b29801993cc1c752ebcca127d.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The fscrypt encryption context can be extended to include different things in the future. To facilitate future expansion add an optional btrfs_encryption_info to the end of the file extent. This will hold the size of the context and then will have the binary context tacked onto the end of the extent item. Add the appropriate accessors to make it easy to read this information if we have encryption set, and then update the tree-checker to validate that if this is indeed set properly that the size matches properly. Signed-off-by: Josef Bacik --- fs/btrfs/accessors.h | 48 +++++++++++++++++++++++++++ fs/btrfs/tree-checker.c | 58 ++++++++++++++++++++++++++++----- include/uapi/linux/btrfs_tree.h | 17 +++++++++- 3 files changed, 113 insertions(+), 10 deletions(-) diff --git a/fs/btrfs/accessors.h b/fs/btrfs/accessors.h index 5aaf204fa55f..a54a4671bd15 100644 --- a/fs/btrfs/accessors.h +++ b/fs/btrfs/accessors.h @@ -932,6 +932,10 @@ BTRFS_SETGET_STACK_FUNCS(super_uuid_tree_generation, struct btrfs_super_block, BTRFS_SETGET_STACK_FUNCS(super_nr_global_roots, struct btrfs_super_block, nr_global_roots, 64); +/* struct btrfs_file_extent_encryption_info */ +BTRFS_SETGET_FUNCS(encryption_info_size, struct btrfs_encryption_info, size, + 32); + /* struct btrfs_file_extent_item */ BTRFS_SETGET_STACK_FUNCS(stack_file_extent_type, struct btrfs_file_extent_item, type, 8); @@ -973,6 +977,50 @@ BTRFS_SETGET_FUNCS(file_extent_encryption, struct btrfs_file_extent_item, BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item, other_encoding, 16); +static inline struct btrfs_encryption_info *btrfs_file_extent_encryption_info( + const struct btrfs_file_extent_item *ei) +{ + unsigned long offset = (unsigned long)ei; + + offset += offsetof(struct btrfs_file_extent_item, encryption_info); + return (struct btrfs_encryption_info *)offset; +} + +static inline unsigned long btrfs_file_extent_encryption_ctx_offset( + const struct btrfs_file_extent_item *ei) +{ + unsigned long offset = (unsigned long)ei; + + offset += offsetof(struct btrfs_file_extent_item, encryption_info); + return offset + offsetof(struct btrfs_encryption_info, context); +} + +static inline u32 btrfs_file_extent_encryption_ctx_size( + const struct extent_buffer *eb, + const struct btrfs_file_extent_item *ei) +{ + return btrfs_encryption_info_size(eb, + btrfs_file_extent_encryption_info(ei)); +} + +static inline void btrfs_set_file_extent_encryption_ctx_size( + const struct extent_buffer *eb, + struct btrfs_file_extent_item *ei, + u32 val) +{ + btrfs_set_encryption_info_size(eb, + btrfs_file_extent_encryption_info(ei), + val); +} + +static inline u32 btrfs_file_extent_encryption_info_size( + const struct extent_buffer *eb, + const struct btrfs_file_extent_item *ei) +{ + return btrfs_encryption_info_size(eb, + btrfs_file_extent_encryption_info(ei)); +} + /* btrfs_qgroup_status_item */ BTRFS_SETGET_FUNCS(qgroup_status_generation, struct btrfs_qgroup_status_item, generation, 64); diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c index 1af2c967436b..ccf1bf59d7e0 100644 --- a/fs/btrfs/tree-checker.c +++ b/fs/btrfs/tree-checker.c @@ -212,6 +212,7 @@ static int check_extent_data_item(struct extent_buffer *leaf, u32 item_size = btrfs_item_size(leaf, slot); u64 extent_end; u8 policy; + u8 fe_type; if (unlikely(!IS_ALIGNED(key->offset, sectorsize))) { file_extent_err(leaf, slot, @@ -242,12 +243,12 @@ static int check_extent_data_item(struct extent_buffer *leaf, SZ_4K); return -EUCLEAN; } - if (unlikely(btrfs_file_extent_type(leaf, fi) >= - BTRFS_NR_FILE_EXTENT_TYPES)) { + + fe_type = btrfs_file_extent_type(leaf, fi); + if (unlikely(fe_type >= BTRFS_NR_FILE_EXTENT_TYPES)) { file_extent_err(leaf, slot, "invalid type for file extent, have %u expect range [0, %u]", - btrfs_file_extent_type(leaf, fi), - BTRFS_NR_FILE_EXTENT_TYPES - 1); + fe_type, BTRFS_NR_FILE_EXTENT_TYPES - 1); return -EUCLEAN; } @@ -296,12 +297,51 @@ static int check_extent_data_item(struct extent_buffer *leaf, return 0; } - /* Regular or preallocated extent has fixed item size */ - if (unlikely(item_size != sizeof(*fi))) { - file_extent_err(leaf, slot, + if (policy == BTRFS_ENCRYPTION_FSCRYPT) { + size_t fe_size = sizeof(*fi) + + sizeof(struct btrfs_encryption_info); + u32 ctxsize; + + if (unlikely(item_size < fe_size)) { + file_extent_err(leaf, slot, + "invalid item size for encrypted file extent, have %u expect = %zu + size of u32", + item_size, sizeof(*fi)); + return -EUCLEAN; + } + + ctxsize = btrfs_file_extent_encryption_info_size(leaf, fi); + if (unlikely(item_size != (fe_size + ctxsize))) { + file_extent_err(leaf, slot, + "invalid item size for encrypted file extent, have %u expect = %zu + context of size %u", + item_size, fe_size, ctxsize); + return -EUCLEAN; + } + + if (unlikely(ctxsize > BTRFS_MAX_EXTENT_CTX_SIZE)) { + file_extent_err(leaf, slot, + "invalid file extent context size, have %u expect a maximum of %u", + ctxsize, BTRFS_MAX_EXTENT_CTX_SIZE); + return -EUCLEAN; + } + + /* + * Only regular and prealloc extents should have an encryption + * context. + */ + if (unlikely(fe_type != BTRFS_FILE_EXTENT_REG && + fe_type != BTRFS_FILE_EXTENT_PREALLOC)) { + file_extent_err(leaf, slot, + "invalid type for encrypted file extent, have %u", + btrfs_file_extent_type(leaf, fi)); + return -EUCLEAN; + } + } else { + if (unlikely(item_size != sizeof(*fi))) { + file_extent_err(leaf, slot, "invalid item size for reg/prealloc file extent, have %u expect %zu", - item_size, sizeof(*fi)); - return -EUCLEAN; + item_size, sizeof(*fi)); + return -EUCLEAN; + } } if (unlikely(CHECK_FE_ALIGNED(leaf, slot, fi, ram_bytes, sectorsize) || CHECK_FE_ALIGNED(leaf, slot, fi, disk_bytenr, sectorsize) || diff --git a/include/uapi/linux/btrfs_tree.h b/include/uapi/linux/btrfs_tree.h index af56a5eb3a00..4d352666b393 100644 --- a/include/uapi/linux/btrfs_tree.h +++ b/include/uapi/linux/btrfs_tree.h @@ -1073,12 +1073,24 @@ enum { BTRFS_NR_FILE_EXTENT_TYPES = 3, }; +/* + * Currently just the FSCRYPT_SET_CONTEXT_MAX_SIZE, which is larger than the + * current extent context size from fscrypt, so this should give us plenty of + * breathing room for expansion later. + */ +#define BTRFS_MAX_EXTENT_CTX_SIZE 40 + enum { BTRFS_ENCRYPTION_NONE, BTRFS_ENCRYPTION_FSCRYPT, BTRFS_NR_ENCRYPTION_TYPES, }; +struct btrfs_encryption_info { + __le32 size; + __u8 context[0]; +}; + struct btrfs_file_extent_item { /* * transaction id that created this extent @@ -1134,7 +1146,10 @@ struct btrfs_file_extent_item { * always reflects the size uncompressed and without encoding. */ __le64 num_bytes; - + /* + * the encryption info, if any + */ + struct btrfs_encryption_info encryption_info[0]; } __attribute__ ((__packed__)); struct btrfs_csum_item { From patchwork Fri Dec 1 22:11:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476516 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="sJUIBPvG" Received: from mail-yw1-x1142.google.com (mail-yw1-x1142.google.com [IPv6:2607:f8b0:4864:20::1142]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 86CFF10EF for ; Fri, 1 Dec 2023 14:12:34 -0800 (PST) Received: by mail-yw1-x1142.google.com with SMTP id 00721157ae682-5d3c7ef7b31so18902637b3.3 for ; Fri, 01 Dec 2023 14:12:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468753; x=1702073553; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=W2vJCSnextTkAMfB2fn+h0ylMQ7BXrKiMJBW4HR8n7Q=; b=sJUIBPvGF9C4zCaiW1YDSiCmXchY9n5KCqG3BewvF8Z4VRcOSLzMNwri7X4BmAHPUF 8GLPtIjU/P9UA138fVsbjBwZ21+EefJTC+RRaJoTuGK80B6oxawu7+WBRPo/81mbxp6O HQVi+ZkMAsl8o5Af0LDGUVqTa5nXHQpuH9ycqhI4DGhrBzGc9hnpWu+Oz9cTwhgLwNOu 2K643AMHLrP+c4BgYPYm4yN3YPYzZGTk9p7ZMWmTWxI5oYA3QHlzmRVe6NF3dz6We2uy 84bZFxUeJI7fe+dxSFq8nEiuH7I2l9NubNnhdPIDnncff9RicnilxhmvIjYiXKEXLGJ0 3RaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468753; x=1702073553; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=W2vJCSnextTkAMfB2fn+h0ylMQ7BXrKiMJBW4HR8n7Q=; b=OE5lzd2DRiWErsaKPi6+Nxd/J8rjFF+zxc/Nq7YOSSKj5RJEgeTdQXm9iLKDLrdXX/ B6bfVOXxydvtx9yjzKranacyfhJCg1O8EXCfGWJyMUUUYGLsJ8Jf5d/nvZ5NkSXdy7GC X6OGfNSfLHgz6g1EdKqVnArxKyf1cr4YsL21zEwGA2N7K07A/yVo4l0gRJa12oQw7mxu KnaUIdcUSM68uXWEl9E4g4opISnnLJLqSPpN4sQ2P/BLEHiOU4yOOuGTkwZeaCXFmWlB OAjmHoTUMiKTfnDfPCrIaIiJ33KomhKbRRmnnTXbLAEXiTWyWtKqRqZgli00LeZsOORF Lltw== X-Gm-Message-State: AOJu0Yz4QIDo1Yp9Ss0qMpJ8ix1oxoY3sSfPijAigHmqHgVsM6TuqalR 4sPd6Zo3FRanfYcoAzpO89vcDgOYd7GKWK/vtvdfbpsf X-Google-Smtp-Source: AGHT+IErvnh7DqYWygk5iM6eO/eA+iBXRY6VkL6b8Nxhb5ymZYwcUOkysn34g4vJgmukhdjr0d4hSQ== X-Received: by 2002:a05:690c:f93:b0:5d1:b53e:e6d3 with SMTP id df19-20020a05690c0f9300b005d1b53ee6d3mr383211ywb.45.1701468753599; Fri, 01 Dec 2023 14:12:33 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id c68-20020a0dc147000000b005d6f34893dfsm247563ywd.135.2023.12.01.14.12.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:33 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Cc: Sweet Tea Dorminy Subject: [PATCH v4 28/46] btrfs: explicitly track file extent length for replace and drop Date: Fri, 1 Dec 2023 17:11:25 -0500 Message-ID: <026b3752d912cf7da484c43c3dace5f4ed0419ed.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Sweet Tea Dorminy With the advent of storing fscrypt contexts with each encrypted extent, extents will have a variable length depending on encryption status. Make sure the replace and drop file extent item helpers encode this information so that everything gets updated properly. Signed-off-by: Sweet Tea Dorminy Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 2 ++ fs/btrfs/file.c | 4 ++-- fs/btrfs/inode.c | 7 +++++-- fs/btrfs/reflink.c | 1 + fs/btrfs/tree-log.c | 5 +++-- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 54fd4eb92745..ba73171fb8b0 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -367,6 +367,8 @@ struct btrfs_replace_extent_info { u64 file_offset; /* Pointer to a file extent item of type regular or prealloc. */ char *extent_buf; + /* The length of @extent_buf */ + u32 extent_buf_size; /* * Set to true when attempting to replace a file range with a new extent * described by this structure, set to false when attempting to clone an diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index b4a503731e79..87d07d7985ec 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -2262,14 +2262,14 @@ static int btrfs_insert_replace_extent(struct btrfs_trans_handle *trans, key.type = BTRFS_EXTENT_DATA_KEY; key.offset = extent_info->file_offset; ret = btrfs_insert_empty_item(trans, root, path, &key, - sizeof(struct btrfs_file_extent_item)); + extent_info->extent_buf_size); if (ret) return ret; leaf = path->nodes[0]; slot = path->slots[0]; write_extent_buffer(leaf, extent_info->extent_buf, btrfs_item_ptr_offset(leaf, slot), - sizeof(struct btrfs_file_extent_item)); + extent_info->extent_buf_size); extent = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); ASSERT(btrfs_file_extent_type(leaf, extent) != BTRFS_FILE_EXTENT_INLINE); btrfs_set_file_extent_offset(leaf, extent, extent_info->data_offset); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index dbdc01f25215..150ec68783c3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2913,6 +2913,7 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, u64 num_bytes = btrfs_stack_file_extent_num_bytes(stack_fi); u64 ram_bytes = btrfs_stack_file_extent_ram_bytes(stack_fi); struct btrfs_drop_extents_args drop_args = { 0 }; + size_t fscrypt_context_size = 0; int ret; path = btrfs_alloc_path(); @@ -2932,7 +2933,7 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, drop_args.start = file_pos; drop_args.end = file_pos + num_bytes; drop_args.replace_extent = true; - drop_args.extent_item_size = sizeof(*stack_fi); + drop_args.extent_item_size = sizeof(*stack_fi) + fscrypt_context_size; ret = btrfs_drop_extents(trans, root, inode, &drop_args); if (ret) goto out; @@ -2943,7 +2944,7 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, ins.type = BTRFS_EXTENT_DATA_KEY; ret = btrfs_insert_empty_item(trans, root, path, &ins, - sizeof(*stack_fi)); + sizeof(*stack_fi) + fscrypt_context_size); if (ret) goto out; } @@ -9717,6 +9718,7 @@ static struct btrfs_trans_handle *insert_prealloc_file_extent( u64 len = ins->offset; int qgroup_released; int ret; + size_t fscrypt_context_size = 0; memset(&stack_fi, 0, sizeof(stack_fi)); @@ -9749,6 +9751,7 @@ static struct btrfs_trans_handle *insert_prealloc_file_extent( extent_info.data_len = len; extent_info.file_offset = file_offset; extent_info.extent_buf = (char *)&stack_fi; + extent_info.extent_buf_size = sizeof(stack_fi) + fscrypt_context_size; extent_info.is_new_extent = true; extent_info.update_times = true; extent_info.qgroup_reserved = qgroup_released; diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c index c39de2a43a00..d01499d8bcf0 100644 --- a/fs/btrfs/reflink.c +++ b/fs/btrfs/reflink.c @@ -500,6 +500,7 @@ static int btrfs_clone(struct inode *src, struct inode *inode, clone_info.data_len = datal; clone_info.file_offset = new_key.offset; clone_info.extent_buf = buf; + clone_info.extent_buf_size = size; clone_info.is_new_extent = false; clone_info.update_times = !no_time_update; ret = btrfs_replace_file_extents(BTRFS_I(inode), path, diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 36063dc39443..580974153649 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -4627,6 +4627,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans, u64 extent_offset = em->start - em->orig_start; u64 block_len; int ret; + size_t fscrypt_context_size = 0; u8 encryption = BTRFS_ENCRYPTION_NONE; btrfs_set_stack_file_extent_generation(&fi, trans->transid); @@ -4669,7 +4670,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans, drop_args.start = em->start; drop_args.end = em->start + em->len; drop_args.replace_extent = true; - drop_args.extent_item_size = sizeof(fi); + drop_args.extent_item_size = sizeof(fi) + fscrypt_context_size; ret = btrfs_drop_extents(trans, log, inode, &drop_args); if (ret) return ret; @@ -4681,7 +4682,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans, key.offset = em->start; ret = btrfs_insert_empty_item(trans, log, path, &key, - sizeof(fi)); + sizeof(fi) + fscrypt_context_size); if (ret) return ret; } From patchwork Fri Dec 1 22:11:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476517 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="BcK3cMsI" Received: from mail-yw1-x112d.google.com (mail-yw1-x112d.google.com [IPv6:2607:f8b0:4864:20::112d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A305C10F3 for ; Fri, 1 Dec 2023 14:12:35 -0800 (PST) Received: by mail-yw1-x112d.google.com with SMTP id 00721157ae682-5d35a952943so24395207b3.3 for ; Fri, 01 Dec 2023 14:12:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468755; x=1702073555; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=LKWiCClPYuTfIaoXpNks8/BOy6SWwggGf9EcawY+RrU=; b=BcK3cMsIkHgjOv7nlVw8i3YO3ellxNcfuTeGWIv38NKDqjD0uzpt0XkLolvAXScHNR Ta6/AzXljNSdV9L1qManzmDCpU9eASvsbqt+84lb4y90gqK8c0RMPKbJPWMX1kp/KcQt RI7W96m62H4rA+Gee2vzaaqbXQ+IHOdXLrFM+Xs9WLjWrUsRZLcJ3fRSE+6cD8X5/v+w U3F8xj37ol5G6TuCe+ujH/ooC3xcLMRKTn48XlcD23EXRsythHLP3pK1p2nE/dVXWByx cwo8HCYgkmhqxDaIIjv8Avsi8RTibWHYtRydPluDxloM8gsKJTT+fcl0+r3+vLuvt/jR 7CHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468755; x=1702073555; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LKWiCClPYuTfIaoXpNks8/BOy6SWwggGf9EcawY+RrU=; b=mSPpHD7SInknaZGUqC3tYsE1SlC0HHZULFKI+HQFuy+YhYB4OWaFMwClYj236dGhEn viKCp7v8lxuxCb6zUIr4DdZ0a+6lfHJVCjbzVgwNTDDkhKRX9gITc8PeAYEO5XXU+0cB q6ccrwVhTL2oGpMZ/THsQVwb39T4lMXOuykL/5nzxCae7+W5/06PBaccnZHc3ihcxc+N Tjk1xLzDVfDX71Ew73+X3lhEAb+gjkQBvHQcgj8f3TIBkQsxlPJq3Cygt2R7ewQwhlHh /gD4EdF3Y7PG9ntngojQQXgXvBMiNBI2E1nS2hPIoV9LOpxXFyfhXZNEtYnllrSjJn5l VVng== X-Gm-Message-State: AOJu0YzF0J8oWqZ2MzD+P51fypnrXuTShmJICZ9rwaCNXJvzeGQw/Qbm 7kdNMkWc8VixsW0lqajl0CxM6V3PEiyUgrXpCuNi3g== X-Google-Smtp-Source: AGHT+IHgBGXs1lk7pQ/qnyaYCRqlIauDPMPv8C9tRRr6Oak6txsoTbpXMLAMZ1O04gknJYr6sj4v2w== X-Received: by 2002:a05:690c:fd1:b0:5d7:1941:ab5 with SMTP id dg17-20020a05690c0fd100b005d719410ab5mr271323ywb.80.1701468754716; Fri, 01 Dec 2023 14:12:34 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id r65-20020a819a44000000b005d3fecea56csm818014ywg.61.2023.12.01.14.12.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:34 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 29/46] btrfs: pass through fscrypt_extent_info to the file extent helpers Date: Fri, 1 Dec 2023 17:11:26 -0500 Message-ID: <921ee1a1728be513293488859d0060aca592e5be.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Now that we have the fscrypt_extnet_info in all of the supporting structures, pass this through and set the file extent encryption bit accordingly from the supporting structures. In subsequent patches code will be added to populate these appropriately. Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 18 +++++++++++------- fs/btrfs/tree-log.c | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 150ec68783c3..8bd5c7488055 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2897,7 +2897,9 @@ int btrfs_writepage_cow_fixup(struct page *page) } static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, - struct btrfs_inode *inode, u64 file_pos, + struct btrfs_inode *inode, + struct fscrypt_extent_info *fscrypt_info, + u64 file_pos, struct btrfs_file_extent_item *stack_fi, const bool update_inode_bytes, u64 qgroup_reserved) @@ -3029,8 +3031,7 @@ static int insert_ordered_extent_file_extent(struct btrfs_trans_handle *trans, btrfs_set_stack_file_extent_num_bytes(&stack_fi, num_bytes); btrfs_set_stack_file_extent_ram_bytes(&stack_fi, ram_bytes); btrfs_set_stack_file_extent_compression(&stack_fi, oe->compress_type); - btrfs_set_stack_file_extent_encryption(&stack_fi, - BTRFS_ENCRYPTION_NONE); + btrfs_set_stack_file_extent_encryption(&stack_fi, oe->encryption_type); /* Other encoding is reserved and always 0 */ /* @@ -3044,8 +3045,9 @@ static int insert_ordered_extent_file_extent(struct btrfs_trans_handle *trans, test_bit(BTRFS_ORDERED_TRUNCATED, &oe->flags); return insert_reserved_file_extent(trans, BTRFS_I(oe->inode), - oe->file_offset, &stack_fi, - update_inode_bytes, oe->qgroup_rsv); + oe->fscrypt_info, oe->file_offset, + &stack_fi, update_inode_bytes, + oe->qgroup_rsv); } /* @@ -9708,6 +9710,7 @@ static struct btrfs_trans_handle *insert_prealloc_file_extent( struct btrfs_trans_handle *trans_in, struct btrfs_inode *inode, struct btrfs_key *ins, + struct fscrypt_extent_info *fscrypt_info, u64 file_offset) { struct btrfs_file_extent_item stack_fi; @@ -9729,6 +9732,7 @@ static struct btrfs_trans_handle *insert_prealloc_file_extent( btrfs_set_stack_file_extent_ram_bytes(&stack_fi, len); btrfs_set_stack_file_extent_compression(&stack_fi, BTRFS_COMPRESS_NONE); btrfs_set_stack_file_extent_encryption(&stack_fi, + fscrypt_info ? BTRFS_ENCRYPTION_FSCRYPT : BTRFS_ENCRYPTION_NONE); /* Other encoding is reserved and always 0 */ @@ -9737,7 +9741,7 @@ static struct btrfs_trans_handle *insert_prealloc_file_extent( return ERR_PTR(qgroup_released); if (trans) { - ret = insert_reserved_file_extent(trans, inode, + ret = insert_reserved_file_extent(trans, inode, fscrypt_info, file_offset, &stack_fi, true, qgroup_released); if (ret) @@ -9831,7 +9835,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode, last_alloc = ins.offset; trans = insert_prealloc_file_extent(trans, BTRFS_I(inode), - &ins, cur_offset); + &ins, NULL, cur_offset); /* * Now that we inserted the prealloc extent we can finally * decrement the number of reservations in the block group. diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 580974153649..36cbc4d176c5 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -4628,7 +4628,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans, u64 block_len; int ret; size_t fscrypt_context_size = 0; - u8 encryption = BTRFS_ENCRYPTION_NONE; + u8 encryption = em->encryption_type; btrfs_set_stack_file_extent_generation(&fi, trans->transid); if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) From patchwork Fri Dec 1 22:11:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476518 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="TUJY6urd" Received: from mail-yb1-xb2a.google.com (mail-yb1-xb2a.google.com [IPv6:2607:f8b0:4864:20::b2a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A8EC7D63 for ; Fri, 1 Dec 2023 14:12:36 -0800 (PST) Received: by mail-yb1-xb2a.google.com with SMTP id 3f1490d57ef6-da7ea62e76cso1035559276.3 for ; Fri, 01 Dec 2023 14:12:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468756; x=1702073556; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=nBe2SByBGGZwnJKo5cDpxDIxZdLwl3MWb46l7m1eRCM=; b=TUJY6urdiF+q/GYGFcZ3OH9mhFfqDiaV484RDJqbhXZcpSCpk3qLrQAsWxBiRe1m4N nu0U095U4lnBGRejtqwW/BX3ocZ8gnJjF32qUhK4ppjnmhzHra1f/I3xwK9yalDr7SjZ 6ibnbbD/Vtzqx1rVF8rab3FqoA2vqHICMXbroyI3KQ0QYbTil5rv+VT7wRWl+Ob5A/SY zwojZuQDbwS0yLYXeuUzkmotk2qyTGgezi+1kwt68dx30iTFEeqvWqRBeSLT48+c2hhJ jqDmIjV3p2k+bu4Yc1g+BlcJrwto7agkDFHFCAjTsIuwiZblVpwDGnu+Ghcm7AJp/PX6 qhYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468756; x=1702073556; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=nBe2SByBGGZwnJKo5cDpxDIxZdLwl3MWb46l7m1eRCM=; b=a7bXZ1hk0LVWjZop0BW2L2RGVwlDGibr8kkmMcZ8GF7TUYSpiCBFlkOHXV75rROE/6 aljYryHT+FYlSkKqaYxq6/Ti70Jr8TuoinFzKLSlSZbUWzwo7KMnU0CRdYOCan4st1zj VBcABb8nLswZ79CsQVg661gem0aGA6A2ngsZVK1rpzCq4E8bjE0domM4kqUZppsLA0QT N0fhF6AehAarkNevrXrlYjhakJBqEQQsWnKtq2gVpj6P3vum60M0/1la6aYh1Gcsvra1 4YffGR7xySDn7DrFxS3gHFxODmp2KULc2Uw3rEKLf1rOZRcpJklId8VkVqBCDhDxPPyV OsOg== X-Gm-Message-State: AOJu0YyG3uMIDFLK2SEybssBCkS5f/JCXr8NQk+I0OktEViLQh7aw8lk 7WPJuwjRn6AXiFIBjXXsjx0SnY6zvMWle1R4pW+3CQ== X-Google-Smtp-Source: AGHT+IGLDjpnc3J07VZ8EZq6s54dsbVBs17DDHvoseuhxrchg5GwgyPv5+P5j1gz2qozr2uJUtrKbQ== X-Received: by 2002:a25:ae0a:0:b0:db5:4043:77ad with SMTP id a10-20020a25ae0a000000b00db5404377admr326712ybj.56.1701468755763; Fri, 01 Dec 2023 14:12:35 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id n75-20020a25da4e000000b00db7dcc2ab76sm21299ybf.34.2023.12.01.14.12.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:35 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 30/46] btrfs: pass the fscrypt_info through the replace extent infrastructure Date: Fri, 1 Dec 2023 17:11:27 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Prealloc uses the btrfs_replace_file_extents() infrastructure to insert its new extents. We need to set the fscrypt context on these extents, so pass this through the btrfs_replace_extent_info so it can be used in a later patch when we hook in this infrastructure. Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 2 ++ fs/btrfs/inode.c | 1 + 2 files changed, 3 insertions(+) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index ba73171fb8b0..9eb14b067e1f 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -369,6 +369,8 @@ struct btrfs_replace_extent_info { char *extent_buf; /* The length of @extent_buf */ u32 extent_buf_size; + /* The fscrypt_extent_info for a new extent. */ + struct fscrypt_extent_info *fscrypt_info; /* * Set to true when attempting to replace a file range with a new extent * described by this structure, set to false when attempting to clone an diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 8bd5c7488055..231d9fe6ff8a 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -9760,6 +9760,7 @@ static struct btrfs_trans_handle *insert_prealloc_file_extent( extent_info.update_times = true; extent_info.qgroup_reserved = qgroup_released; extent_info.insertions = 0; + extent_info.fscrypt_info = fscrypt_info; path = btrfs_alloc_path(); if (!path) { From patchwork Fri Dec 1 22:11:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476520 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="B6vkk6T5" Received: from mail-yw1-x1141.google.com (mail-yw1-x1141.google.com [IPv6:2607:f8b0:4864:20::1141]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 667F910D0 for ; Fri, 1 Dec 2023 14:12:38 -0800 (PST) Received: by mail-yw1-x1141.google.com with SMTP id 00721157ae682-5d3efc071e2so15436087b3.0 for ; Fri, 01 Dec 2023 14:12:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468757; x=1702073557; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=YYkeYf+z98OzU3pSQ70AVwvLkUld8GZ5RFcORDajeOI=; b=B6vkk6T5bmj1bYIivbpDyPeF+SJr0LSatZ4A0TMUds5j99QBWW1T/xuuQE4CHIN2Kp SozPTzhuHZQVkmVSjAwcgeuSVLVysZCqhwA+d0lwP57k94vu3AwPJG/NLnSfFujJqB5o ElaayOdBqvvOQ4qYTV+vc+9u1AgUK1rEP7UqRCqNQiDTOIMaNn8KXAOzvFTyUODS14qr pDUCqwLtf1wkfNJW2gFwcdVQQ6rg6Mp6hAj8mvRP/Bo7pCtNhEqdMMJfaTLeLniHkXt0 AK0kuigsU2MLCvr+irdwifRyDeBGw/PRZXZqKTO2kn9iyAuXKMJYP679P9m9HGW74BKV EKRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468757; x=1702073557; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=YYkeYf+z98OzU3pSQ70AVwvLkUld8GZ5RFcORDajeOI=; b=u0Z164TUZw+akqYmipPdw6pi0joDbO2WMArL4QxGvi+E6/ppBxlWgu6qHBl7R10hen YF+MUKHuSON9RzwcZEHOYv3/1MUGxEy/017I5g5H7T75Nzoo++xEhoOmCSYb7d3/kBAN 0IbUZQWxJFOWZSa8OxeJBQODn5rbVH/3Z4UlHLrb50e/glfAKvXD0p70442ihoY2qCik AS9XfKH1e6oNDabDdgqaWDbS6sqQ+FFOn9jl7WbNY9bvPMsgvaOiFQVt/dL1AWxjV/yV 4AFShOCO/Y4S3pcfxXH/cB9s82Dlw3dbpMQZgCJ189W/vydc0lifU7osPYvYcHs3iz0A 0DQA== X-Gm-Message-State: AOJu0Yw8MtdUz0LgJ4OVnF0L0W04dJVGdIPXrZzhndTtd2oVCHj+EE5/ RO2x4Qb5qBQO0j4SaDWL/zafV75iTjnOy8/d2AN0n2sU X-Google-Smtp-Source: AGHT+IEysAuZwXEDSyvO+UfroclnBMf4w9zvcUAteXHwi2BHXrVms7eJxF2xPlOA6fzR4HwAjq+ohw== X-Received: by 2002:a81:ae57:0:b0:5d7:1941:2c12 with SMTP id g23-20020a81ae57000000b005d719412c12mr209844ywk.63.1701468757411; Fri, 01 Dec 2023 14:12:37 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id g82-20020a0ddd55000000b005ca265f0c68sm1002173ywe.42.2023.12.01.14.12.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:36 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 31/46] btrfs: implement the fscrypt extent encryption hooks Date: Fri, 1 Dec 2023 17:11:28 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This patch implements the necessary hooks from fscrypt to support per-extent encryption. There's two main entry points btrfs_fscrypt_load_extent_info btrfs_fscrypt_save_extent_info btrfs_fscrypt_load_extent_info gets called when we create the extent maps from the file extent item at btrfs_get_extent() time. We read the extent context, and pass it into fscrypt to create the appropriate fscrypt_extent_info structure. This is then used on the bio's to make sure the encryption is done properly. btrfs_fscrypt_save_extent_info is used to generate the fscrypt context from fscrypt and save it into the file extent item when we create a new file extent item. Signed-off-by: Josef Bacik --- fs/btrfs/defrag.c | 10 ++++++++- fs/btrfs/file-item.c | 11 +++++++++- fs/btrfs/file-item.h | 5 ++++- fs/btrfs/file.c | 9 ++++++++ fs/btrfs/fscrypt.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/fscrypt.h | 31 ++++++++++++++++++++++++++++ fs/btrfs/inode.c | 22 +++++++++++++++++++- fs/btrfs/tree-log.c | 10 +++++++++ 8 files changed, 143 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/defrag.c b/fs/btrfs/defrag.c index 5244561e2016..f3b7438ddbc7 100644 --- a/fs/btrfs/defrag.c +++ b/fs/btrfs/defrag.c @@ -16,6 +16,7 @@ #include "defrag.h" #include "file-item.h" #include "super.h" +#include "fscrypt.h" static struct kmem_cache *btrfs_inode_defrag_cachep; @@ -631,9 +632,12 @@ static struct extent_map *defrag_get_extent(struct btrfs_inode *inode, struct btrfs_path path = { 0 }; struct extent_map *em; struct btrfs_key key; + struct btrfs_fscrypt_ctx ctx; u64 ino = btrfs_ino(inode); int ret; + ctx.size = 0; + em = alloc_extent_map(); if (!em) { ret = -ENOMEM; @@ -728,7 +732,7 @@ static struct extent_map *defrag_get_extent(struct btrfs_inode *inode, goto next; /* Now this extent covers @start, convert it to em */ - btrfs_extent_item_to_extent_map(inode, &path, fi, em); + btrfs_extent_item_to_extent_map(inode, &path, fi, em, &ctx); break; next: ret = btrfs_next_item(root, &path); @@ -738,6 +742,10 @@ static struct extent_map *defrag_get_extent(struct btrfs_inode *inode, goto not_found; } btrfs_release_path(&path); + + ret = btrfs_fscrypt_load_extent_info(inode, em, &ctx); + if (ret) + goto err; return em; not_found: diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 26f35c1baedc..35036fab58c4 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -21,6 +21,7 @@ #include "accessors.h" #include "file-item.h" #include "super.h" +#include "fscrypt.h" #define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \ sizeof(struct btrfs_item) * 2) / \ @@ -1264,7 +1265,8 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode, const struct btrfs_path *path, struct btrfs_file_extent_item *fi, - struct extent_map *em) + struct extent_map *em, + struct btrfs_fscrypt_ctx *ctx) { struct btrfs_fs_info *fs_info = inode->root->fs_info; struct btrfs_root *root = inode->root; @@ -1306,6 +1308,13 @@ void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode, set_bit(EXTENT_FLAG_PREALLOC, &em->flags); } em->encryption_type = btrfs_file_extent_encryption(leaf, fi); + if (em->encryption_type != BTRFS_ENCRYPTION_NONE) { + ctx->size = + btrfs_file_extent_encryption_ctx_size(leaf, fi); + read_extent_buffer(leaf, ctx->ctx, + btrfs_file_extent_encryption_ctx_offset(fi), + ctx->size); + } } else if (type == BTRFS_FILE_EXTENT_INLINE) { em->block_start = EXTENT_MAP_INLINE; em->start = extent_start; diff --git a/fs/btrfs/file-item.h b/fs/btrfs/file-item.h index 04bd2d34efb1..bb79014024bd 100644 --- a/fs/btrfs/file-item.h +++ b/fs/btrfs/file-item.h @@ -5,6 +5,8 @@ #include "accessors.h" +struct btrfs_fscrypt_ctx; + #define BTRFS_FILE_EXTENT_INLINE_DATA_START \ (offsetof(struct btrfs_file_extent_item, disk_bytenr)) @@ -63,7 +65,8 @@ int btrfs_lookup_csums_bitmap(struct btrfs_root *root, struct btrfs_path *path, void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode, const struct btrfs_path *path, struct btrfs_file_extent_item *fi, - struct extent_map *em); + struct extent_map *em, + struct btrfs_fscrypt_ctx *ctx); int btrfs_inode_clear_file_extent_range(struct btrfs_inode *inode, u64 start, u64 len); int btrfs_inode_set_file_extent_range(struct btrfs_inode *inode, u64 start, u64 len); diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 87d07d7985ec..30d509259922 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -38,6 +38,7 @@ #include "ioctl.h" #include "file.h" #include "super.h" +#include "fscrypt.h" /* simple helper to fault in pages and copy. This should go away * and be replaced with calls into generic code. @@ -2276,6 +2277,14 @@ static int btrfs_insert_replace_extent(struct btrfs_trans_handle *trans, btrfs_set_file_extent_num_bytes(leaf, extent, replace_len); if (extent_info->is_new_extent) btrfs_set_file_extent_generation(leaf, extent, trans->transid); + if (extent_info->fscrypt_info) { + ret = btrfs_fscrypt_save_extent_info(inode, path, + extent_info->fscrypt_info); + if (ret) { + btrfs_release_path(path); + return ret; + } + } btrfs_mark_buffer_dirty(trans, leaf); btrfs_release_path(path); diff --git a/fs/btrfs/fscrypt.c b/fs/btrfs/fscrypt.c index 2d037b105b5f..7a7272cb83ec 100644 --- a/fs/btrfs/fscrypt.c +++ b/fs/btrfs/fscrypt.c @@ -214,7 +214,56 @@ static struct block_device **btrfs_fscrypt_get_devices(struct super_block *sb, return devs; } +int btrfs_fscrypt_load_extent_info(struct btrfs_inode *inode, + struct extent_map *em, + struct btrfs_fscrypt_ctx *ctx) +{ + struct fscrypt_extent_info *info; + unsigned long nofs_flag; + + if (ctx->size == 0) + return 0; + + nofs_flag = memalloc_nofs_save(); + info = fscrypt_load_extent_info(&inode->vfs_inode, ctx->ctx, ctx->size); + memalloc_nofs_restore(nofs_flag); + if (IS_ERR(info)) + return PTR_ERR(info); + em->fscrypt_info = info; + return 0; +} + +int btrfs_fscrypt_save_extent_info(struct btrfs_inode *inode, + struct btrfs_path *path, + struct fscrypt_extent_info *info) +{ + struct btrfs_file_extent_item *ei; + u8 ctx[BTRFS_MAX_EXTENT_CTX_SIZE]; + ssize_t ctx_size; + + ei = btrfs_item_ptr(path->nodes[0], path->slots[0], + struct btrfs_file_extent_item); + + ctx_size = fscrypt_set_extent_context(&inode->vfs_inode, info, ctx); + if (ctx_size < 0) { + btrfs_err_rl(inode->root->fs_info, "invalid encrypt context\n"); + return (int)ctx_size; + } + write_extent_buffer(path->nodes[0], ctx, + btrfs_file_extent_encryption_ctx_offset(ei), + ctx_size); + btrfs_set_file_extent_encryption_ctx_size(path->nodes[0], ei, ctx_size); + return 0; +} + +size_t btrfs_fscrypt_extent_context_size(struct btrfs_inode *inode) +{ + return sizeof(struct btrfs_encryption_info) + + fscrypt_extent_context_size(&inode->vfs_inode); +} + const struct fscrypt_operations btrfs_fscrypt_ops = { + .has_per_extent_encryption = 1, .get_context = btrfs_fscrypt_get_context, .set_context = btrfs_fscrypt_set_context, .empty_dir = btrfs_fscrypt_empty_dir, diff --git a/fs/btrfs/fscrypt.h b/fs/btrfs/fscrypt.h index c08fd52c99b4..2882a4a9d978 100644 --- a/fs/btrfs/fscrypt.h +++ b/fs/btrfs/fscrypt.h @@ -8,6 +8,11 @@ #include "fs.h" +struct btrfs_fscrypt_ctx { + u8 ctx[BTRFS_MAX_EXTENT_CTX_SIZE]; + size_t size; +}; + #ifdef CONFIG_FS_ENCRYPTION int btrfs_fscrypt_get_disk_name(struct extent_buffer *leaf, struct btrfs_dir_item *di, @@ -16,8 +21,29 @@ int btrfs_fscrypt_get_disk_name(struct extent_buffer *leaf, bool btrfs_fscrypt_match_name(struct fscrypt_name *fname, struct extent_buffer *leaf, unsigned long de_name, u32 de_name_len); +int btrfs_fscrypt_load_extent_info(struct btrfs_inode *inode, + struct extent_map *em, + struct btrfs_fscrypt_ctx *ctx); +int btrfs_fscrypt_save_extent_info(struct btrfs_inode *inode, + struct btrfs_path *path, + struct fscrypt_extent_info *fi); +size_t btrfs_fscrypt_extent_context_size(struct btrfs_inode *inode); #else +static inline int btrfs_fscrypt_save_extent_info(struct btrfs_inode *inode, + struct btrfs_path *path, + struct fscrypt_extent_info *fi) +{ + return 0; +} + +static inline int btrfs_fscrypt_load_extent_info(struct btrfs_inode *inode, + struct extent_map *em, + struct btrfs_fscrypt_ctx *ctx) +{ + return 0; +} + static inline int btrfs_fscrypt_get_disk_name(struct extent_buffer *leaf, struct btrfs_dir_item *di, struct fscrypt_str *qstr) @@ -35,6 +61,11 @@ static inline bool btrfs_fscrypt_match_name(struct fscrypt_name *fname, return !memcmp_extent_buffer(leaf, fname->disk_name.name, de_name, de_name_len); } + +static inline size_t btrfs_fscrypt_extent_context_size(struct btrfs_inode *inode) +{ + return 0; +} #endif /* CONFIG_FS_ENCRYPTION */ extern const struct fscrypt_operations btrfs_fscrypt_ops; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 231d9fe6ff8a..dc24f11016d9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2918,6 +2918,9 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, size_t fscrypt_context_size = 0; int ret; + if (btrfs_stack_file_extent_encryption(stack_fi)) + fscrypt_context_size = btrfs_fscrypt_extent_context_size(inode); + path = btrfs_alloc_path(); if (!path) return -ENOMEM; @@ -2956,6 +2959,12 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans, btrfs_item_ptr_offset(leaf, path->slots[0]), sizeof(struct btrfs_file_extent_item)); + if (fscrypt_context_size) { + ret = btrfs_fscrypt_save_extent_info(inode, path, fscrypt_info); + if (ret) + goto out; + } + btrfs_mark_buffer_dirty(trans, leaf); btrfs_release_path(path); @@ -6889,6 +6898,7 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode, struct btrfs_key found_key; struct extent_map *em = NULL; struct extent_map_tree *em_tree = &inode->extent_tree; + struct btrfs_fscrypt_ctx ctx; read_lock(&em_tree->lock); em = lookup_extent_mapping(em_tree, start, len); @@ -6902,6 +6912,9 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode, else goto out; } + + ctx.size = 0; + em = alloc_extent_map(); if (!em) { ret = -ENOMEM; @@ -7006,7 +7019,7 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode, goto insert; } - btrfs_extent_item_to_extent_map(inode, path, item, em); + btrfs_extent_item_to_extent_map(inode, path, item, em, &ctx); if (extent_type == BTRFS_FILE_EXTENT_REG || extent_type == BTRFS_FILE_EXTENT_PREALLOC) { @@ -7051,6 +7064,10 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode, goto out; } + ret = btrfs_fscrypt_load_extent_info(inode, em, &ctx); + if (ret) + goto out; + write_lock(&em_tree->lock); ret = btrfs_add_extent_mapping(fs_info, em_tree, &em, start, len); write_unlock(&em_tree->lock); @@ -9749,6 +9766,9 @@ static struct btrfs_trans_handle *insert_prealloc_file_extent( return trans; } + if (fscrypt_info) + fscrypt_context_size = btrfs_fscrypt_extent_context_size(inode); + extent_info.disk_offset = start; extent_info.disk_len = len; extent_info.data_offset = 0; diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 36cbc4d176c5..53c2c58d0002 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -30,6 +30,7 @@ #include "file.h" #include "orphan.h" #include "tree-checker.h" +#include "fscrypt.h" #define MAX_CONFLICT_INODES 10 @@ -4630,6 +4631,9 @@ static int log_one_extent(struct btrfs_trans_handle *trans, size_t fscrypt_context_size = 0; u8 encryption = em->encryption_type; + if (encryption) + fscrypt_context_size = btrfs_fscrypt_extent_context_size(inode); + btrfs_set_stack_file_extent_generation(&fi, trans->transid); if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) btrfs_set_stack_file_extent_type(&fi, BTRFS_FILE_EXTENT_PREALLOC); @@ -4690,6 +4694,12 @@ static int log_one_extent(struct btrfs_trans_handle *trans, write_extent_buffer(leaf, &fi, btrfs_item_ptr_offset(leaf, path->slots[0]), sizeof(fi)); + if (fscrypt_context_size) { + ret = btrfs_fscrypt_save_extent_info(inode, path, + em->fscrypt_info); + if (ret) + return ret; + } btrfs_mark_buffer_dirty(trans, leaf); btrfs_release_path(path); From patchwork Fri Dec 1 22:11:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476519 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="zfUamOBk" Received: from mail-yw1-x1136.google.com (mail-yw1-x1136.google.com [IPv6:2607:f8b0:4864:20::1136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7A86510EF for ; Fri, 1 Dec 2023 14:12:39 -0800 (PST) Received: by mail-yw1-x1136.google.com with SMTP id 00721157ae682-5d34d85e610so25973017b3.3 for ; Fri, 01 Dec 2023 14:12:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468758; x=1702073558; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=/gVzeoeMQURNmpVvwynwfw94EyTjX18z8l6sVFepenU=; b=zfUamOBk1mZF62Y8pJofbqt6NsxqKT6LTQrnyfryWYlkHt4b1K8UVQH+aFV63uI8Pw bn11dFDN2FaGhb8xV8IBNoAm/QJs08+pqc7AodzvIyllyFGRu6fpY8EE34aDjywXreZl nZ8tPsougPMKYFAxVylIN6oNP6ScyR5Jl15MKd+yCs10ZS6MQH0KbL2/i8r5hwhk2VkU 2+x2O33dla8huYwszfQkjiNj3s6bYEyVGf2GcxL0sahbFXwEe49bm7QwV9bNyHmWrOFJ Ou5J4HU3/62Z20TQSSqt2KtF5KijdR5NAmcWMIWrriyFHsLkg2Go/XEgioOnHAizxuGV opMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468758; x=1702073558; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/gVzeoeMQURNmpVvwynwfw94EyTjX18z8l6sVFepenU=; b=qCQJgENbtm6mpA91RW081POrptNX3sFRdVLuNLXUMu6pqZroJEewqeOgqUaJKbfYnH kbW9obRLB7n+wStSllBaXpIdVywqWxRXuuWSVcc/1Pd1s9+vw2+TTTAlMTH+MiPug0su zdrb3wT2bN1wZy7bN2E+jh8zBBxbL+D7ifou3Lzc10+ydc7Egd7pzwWMRzl5ow1ahhBF +7aGD2QMna/trDc6egLoyFYNFSST78ThtHc+n3BQgN/kGI4rW2RGu8WuuFGbRROPEUZ0 eZyj58Tgm/wl+UIrDHn7Wt3oV6oHpODITShltZfJQMgfrpJFEcpvtc4Q7G2rPwAstqzq 8EEA== X-Gm-Message-State: AOJu0YybfDr3u1sHHvLFpT/YQakjPSPRg4oDRi4EUP21+bmf2PVFzbx9 F0LuU2YFDLMo+Ni8KryxLkL8Rdrft3hnIe7yR2jXqw== X-Google-Smtp-Source: AGHT+IH89hNyf6GR833XcK9wzFi9Ci0Mxcbcl+L3FWkFizNpJnJbUry42lg3AZACHMlWrF3lwLX8xQ== X-Received: by 2002:a05:690c:f85:b0:5d7:2c6b:625 with SMTP id df5-20020a05690c0f8500b005d72c6b0625mr45864ywb.34.1701468758582; Fri, 01 Dec 2023 14:12:38 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id z143-20020a0dd795000000b005af5bb5e840sm226ywd.34.2023.12.01.14.12.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:38 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 32/46] btrfs: setup fscrypt_extent_info for new extents Date: Fri, 1 Dec 2023 17:11:29 -0500 Message-ID: <506c404aac10482cf64b0fb5e34310a41316f637.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 New extents for encrypted inodes must have a fscrypt_extent_info, which has the necessary keys and does all the registration at the block layer for them. This is passed through all of the infrastructure we've previously added to make sure the context gets saved properly with the file extents. Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index dc24f11016d9..60d016da1fce 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7434,6 +7434,16 @@ static struct extent_map *create_io_em(struct btrfs_inode *inode, if (fscrypt_info) { em->encryption_type = BTRFS_ENCRYPTION_FSCRYPT; em->fscrypt_info = fscrypt_get_extent_info(fscrypt_info); + } else if (IS_ENCRYPTED(&inode->vfs_inode)) { + struct fscrypt_extent_info *fscrypt_info; + + em->encryption_type = BTRFS_ENCRYPTION_FSCRYPT; + fscrypt_info = fscrypt_prepare_new_extent(&inode->vfs_inode); + if (IS_ERR(fscrypt_info)) { + free_extent_map(em); + return ERR_CAST(fscrypt_info); + } + em->fscrypt_info = fscrypt_info; } else { em->encryption_type = BTRFS_ENCRYPTION_NONE; } @@ -9831,6 +9841,9 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode, if (trans) own_trans = false; while (num_bytes > 0) { + struct fscrypt_extent_info *fscrypt_info = NULL; + int encryption_type = BTRFS_ENCRYPTION_NONE; + cur_bytes = min_t(u64, num_bytes, SZ_256M); cur_bytes = max(cur_bytes, min_size); /* @@ -9845,6 +9858,20 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode, if (ret) break; + if (IS_ENCRYPTED(inode)) { + fscrypt_info = fscrypt_prepare_new_extent(inode); + if (IS_ERR(fscrypt_info)) { + btrfs_dec_block_group_reservations(fs_info, + ins.objectid); + btrfs_free_reserved_extent(fs_info, + ins.objectid, + ins.offset, 0); + ret = PTR_ERR(fscrypt_info); + break; + } + encryption_type = BTRFS_ENCRYPTION_FSCRYPT; + } + /* * We've reserved this space, and thus converted it from * ->bytes_may_use to ->bytes_reserved. Any error that happens @@ -9856,7 +9883,8 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode, last_alloc = ins.offset; trans = insert_prealloc_file_extent(trans, BTRFS_I(inode), - &ins, NULL, cur_offset); + &ins, fscrypt_info, + cur_offset); /* * Now that we inserted the prealloc extent we can finally * decrement the number of reservations in the block group. @@ -9866,6 +9894,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode, btrfs_dec_block_group_reservations(fs_info, ins.objectid); if (IS_ERR(trans)) { ret = PTR_ERR(trans); + fscrypt_put_extent_info(fscrypt_info); btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 0); break; @@ -9873,6 +9902,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode, em = alloc_extent_map(); if (!em) { + fscrypt_put_extent_info(fscrypt_info); btrfs_drop_extent_map_range(BTRFS_I(inode), cur_offset, cur_offset + ins.offset - 1, false); btrfs_set_inode_full_sync(BTRFS_I(inode)); @@ -9888,6 +9918,8 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode, em->ram_bytes = ins.offset; set_bit(EXTENT_FLAG_PREALLOC, &em->flags); em->generation = trans->transid; + em->fscrypt_info = fscrypt_info; + em->encryption_type = encryption_type; ret = btrfs_replace_extent_map_range(BTRFS_I(inode), em, true); free_extent_map(em); From patchwork Fri Dec 1 22:11:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476521 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="2fwTnhvt" Received: from mail-yw1-x112e.google.com (mail-yw1-x112e.google.com [IPv6:2607:f8b0:4864:20::112e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 89FEB10F3 for ; Fri, 1 Dec 2023 14:12:40 -0800 (PST) Received: by mail-yw1-x112e.google.com with SMTP id 00721157ae682-5d3c7ef7b31so18903417b3.3 for ; Fri, 01 Dec 2023 14:12:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468759; x=1702073559; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=1p5Yi6ojA7mTkKHgcDln1Jm49x5iVqCKOwjX8lstC10=; b=2fwTnhvtnY/f+caeCr8GtL1s0VD0NWxGuNdtY8p5Hz5jx19KuJWYpfthiK371T2Ocm yxp9pBoQqoI2l151JgULKGeLmFe5rqZsXkrPIMbNE3w7hrL4Wsqd6hK4mCnMQi0xLLC+ xjoy5s3Hk/GT7CY2NhKUorUg7BVrcEDcmQvuW75F1DmSrdG+qprGnpegk2MLiIHh7mu/ aSq69NPufbuLMslqCZW8m8S1hZbOjmbDY5LgQsWpFHxUEgEFSWtfNZrkeRnARrbwpDXb SdgTyWM80ZzXc9GWGKvYS2saQg1WPLMvjV0p8jE76QnySojf7N2IKfxj6HmlJz3BemP4 P4jA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468759; x=1702073559; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1p5Yi6ojA7mTkKHgcDln1Jm49x5iVqCKOwjX8lstC10=; b=ijPTBbFulVtoINIxGGuv0LOt6nDhGCPUZKqssJqcwN65BwkUSnDshxdMzyLCwJfyfa OZ6Bp/1qSu+L1/B9o9AcV2IGJblQtmpIcZzHIk7uDwJizusl0QWZ7vrjc2jEO81fKcJT NN+0Uhf+E8pPR1b9AsreAlCWsocxuFkR5+ExMf25uiJNDZlptx4Qbqpe/bVkbDF+c+dw 6q5lJ7hP1ETDGN7O0+t7cSju8Xp4V+QMAVPMOE8dKhGd6uEgV67c+vGDT7OQP2LXcddY 6wN9IwpKSKv5HZyJSC+WXS9wT0TtrwtG0eLsSj3v/UvfebbU4WMUidYQMxrEcdT7wXwN kslg== X-Gm-Message-State: AOJu0YwhFpL3Hzg/Xvk/0GVh3OG6Q6M1jclQx8WuMn25C31SsPs1O6SV J1EZv4aRffH8L0a0oF1exD4a/a/SZgCdNDl4ot/HRg== X-Google-Smtp-Source: AGHT+IF5QEaC3YRRAZNc7SjvT/tYGEj/RGHPe0RSXTibDhPYDPgkQ8ZhID16UR2qozaergXP7NZG9A== X-Received: by 2002:a81:af68:0:b0:5d3:4b91:4ba5 with SMTP id x40-20020a81af68000000b005d34b914ba5mr313212ywj.33.1701468759621; Fri, 01 Dec 2023 14:12:39 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id c68-20020a0dc147000000b005d6f34893dfsm247620ywd.135.2023.12.01.14.12.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:39 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 33/46] btrfs: populate ordered_extent with the orig offset Date: Fri, 1 Dec 2023 17:11:30 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 For extent encryption we have to use a logical block nr as input for the IV. For btrfs we're using the offset into the extent we're operating on. For most ordered extents this is the same as the file_offset, however for prealloc and NOCOW we have to use the original offset. Add this as an argument and plumb it through everywhere, this will be used when setting up the bio. Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 15 ++++++++++----- fs/btrfs/ordered-data.c | 32 ++++++++++++++++++++++---------- fs/btrfs/ordered-data.h | 12 +++++++++--- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 60d016da1fce..3dce53601915 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1175,6 +1175,7 @@ static void submit_one_async_extent(struct async_chunk *async_chunk, ordered = btrfs_alloc_ordered_extent(inode, em->fscrypt_info, start, /* file_offset */ + start, /* orig_start */ async_extent->ram_size, /* num_bytes */ async_extent->ram_size, /* ram_bytes */ ins.objectid, /* disk_bytenr */ @@ -1438,8 +1439,8 @@ static noinline int cow_file_range(struct btrfs_inode *inode, } ordered = btrfs_alloc_ordered_extent(inode, em->fscrypt_info, - start, ram_size, ram_size, ins.objectid, - cur_alloc_size, 0, + start, start, ram_size, ram_size, + ins.objectid, cur_alloc_size, 0, 1 << BTRFS_ORDERED_REGULAR, BTRFS_COMPRESS_NONE); free_extent_map(em); @@ -2193,7 +2194,9 @@ static noinline int run_delalloc_nocow(struct btrfs_inode *inode, } ordered = btrfs_alloc_ordered_extent(inode, fscrypt_info, - cur_offset, nocow_args.num_bytes, + cur_offset, + found_key.offset - nocow_args.extent_offset, + nocow_args.num_bytes, nocow_args.num_bytes, nocow_args.disk_bytenr, nocow_args.num_bytes, 0, is_prealloc @@ -7113,8 +7116,9 @@ static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode, fscrypt_info = em->fscrypt_info; } - ordered = btrfs_alloc_ordered_extent(inode, fscrypt_info, start, len, - len, block_start, block_len, 0, + ordered = btrfs_alloc_ordered_extent(inode, fscrypt_info, start, + orig_start, len, len, block_start, + block_len, 0, (1 << type) | (1 << BTRFS_ORDERED_DIRECT), BTRFS_COMPRESS_NONE); @@ -10655,6 +10659,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from, } ordered = btrfs_alloc_ordered_extent(inode, em->fscrypt_info, start, + start - encoded->unencoded_offset, num_bytes, ram_bytes, ins.objectid, ins.offset, encoded->unencoded_offset, (1 << BTRFS_ORDERED_ENCODED) | diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index ee3138a6d11e..a9c9d9cc6ee3 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -148,9 +148,9 @@ static inline struct rb_node *ordered_tree_search(struct btrfs_inode *inode, static struct btrfs_ordered_extent *alloc_ordered_extent( struct btrfs_inode *inode, struct fscrypt_extent_info *fscrypt_info, - u64 file_offset, u64 num_bytes, u64 ram_bytes, - u64 disk_bytenr, u64 disk_num_bytes, u64 offset, - unsigned long flags, int compress_type) + u64 file_offset, u64 orig_offset, u64 num_bytes, + u64 ram_bytes, u64 disk_bytenr, u64 disk_num_bytes, + u64 offset, unsigned long flags, int compress_type) { struct btrfs_ordered_extent *entry; int ret; @@ -175,6 +175,7 @@ static struct btrfs_ordered_extent *alloc_ordered_extent( return ERR_PTR(-ENOMEM); entry->file_offset = file_offset; + entry->orig_offset = orig_offset; entry->num_bytes = num_bytes; entry->ram_bytes = ram_bytes; entry->disk_bytenr = disk_bytenr; @@ -253,6 +254,7 @@ static void insert_ordered_extent(struct btrfs_ordered_extent *entry) * @inode: Inode that this extent is for. * @fscrypt_info: The fscrypt_extent_info for this extent, if necessary. * @file_offset: Logical offset in file where the extent starts. + * @orig_offset: Logical offset of the original extent (PREALLOC or NOCOW) * @num_bytes: Logical length of extent in file. * @ram_bytes: Full length of unencoded data. * @disk_bytenr: Offset of extent on disk. @@ -270,17 +272,17 @@ static void insert_ordered_extent(struct btrfs_ordered_extent *entry) struct btrfs_ordered_extent *btrfs_alloc_ordered_extent( struct btrfs_inode *inode, struct fscrypt_extent_info *fscrypt_info, - u64 file_offset, u64 num_bytes, u64 ram_bytes, - u64 disk_bytenr, u64 disk_num_bytes, u64 offset, - unsigned long flags, int compress_type) + u64 file_offset, u64 orig_offset, u64 num_bytes, + u64 ram_bytes, u64 disk_bytenr, u64 disk_num_bytes, + u64 offset, unsigned long flags, int compress_type) { struct btrfs_ordered_extent *entry; ASSERT((flags & ~BTRFS_ORDERED_TYPE_FLAGS) == 0); entry = alloc_ordered_extent(inode, fscrypt_info, file_offset, - num_bytes, ram_bytes, disk_bytenr, - disk_num_bytes, offset, flags, + orig_offset, num_bytes, ram_bytes, + disk_bytenr, disk_num_bytes, offset, flags, compress_type); if (!IS_ERR(entry)) insert_ordered_extent(entry); @@ -1174,8 +1176,8 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent( return ERR_PTR(-EINVAL); new = alloc_ordered_extent(inode, ordered->fscrypt_info, file_offset, - len, len, disk_bytenr, len, 0, flags, - ordered->compress_type); + ordered->orig_offset, len, len, disk_bytenr, + len, 0, flags, ordered->compress_type); if (IS_ERR(new)) return new; @@ -1196,6 +1198,16 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent( ordered->num_bytes -= len; ordered->disk_num_bytes -= len; + /* + * ->orig_offset is the original offset of the original extent, which + * for PREALLOC or NOCOW stays the same, but if we're a regular extent + * that means this is a new extent and thus ->orig_offset must equal + * ->file_offset. This is only important for encryption as we only use + * it for setting the offset for the bio encryption context. + */ + if (test_bit(BTRFS_ORDERED_REGULAR, &ordered->flags)) + ordered->orig_offset = ordered->file_offset; + if (test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags)) { ASSERT(ordered->bytes_left == 0); new->bytes_left = 0; diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 57ca8ce6eb6d..a8ce181288f7 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h @@ -83,6 +83,12 @@ struct btrfs_ordered_extent { /* logical offset in the file */ u64 file_offset; + /* + * The original logical offset of the extent, this is for NOCOW and + * PREALLOC extents, otherwise it'll be the same as file_offset. + */ + u64 orig_offset; + /* * These fields directly correspond to the same fields in * btrfs_file_extent_item. @@ -165,9 +171,9 @@ bool btrfs_dec_test_ordered_pending(struct btrfs_inode *inode, struct btrfs_ordered_extent *btrfs_alloc_ordered_extent( struct btrfs_inode *inode, struct fscrypt_extent_info *fscrypt_info, - u64 file_offset, u64 num_bytes, u64 ram_bytes, - u64 disk_bytenr, u64 disk_num_bytes, u64 offset, - unsigned long flags, int compress_type); + u64 file_offset, u64 orig_offset, u64 num_bytes, + u64 ram_bytes, u64 disk_bytenr, u64 disk_num_bytes, + u64 offset, unsigned long flags, int compress_type); void btrfs_add_ordered_sum(struct btrfs_ordered_extent *entry, struct btrfs_ordered_sum *sum); struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct btrfs_inode *inode, From patchwork Fri Dec 1 22:11:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476523 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="YCSDwGDw" Received: from mail-oi1-x232.google.com (mail-oi1-x232.google.com [IPv6:2607:f8b0:4864:20::232]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BDDFFD63 for ; Fri, 1 Dec 2023 14:12:42 -0800 (PST) Received: by mail-oi1-x232.google.com with SMTP id 5614622812f47-3b8412723c4so680382b6e.0 for ; Fri, 01 Dec 2023 14:12:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468762; x=1702073562; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=v1CXtGZj8aSs4z9SIQWwUOQcwGx+Gif/0Em+QUOV9hY=; b=YCSDwGDwcI8uSIj7zZuOR4t4LVp99HovpLccGfdJ+6JyPiKUXWok8K9MEEpAa7FCUu s0XPjVkNJZ3HN82tFLwdGolBDw/7URMJqYYzU35lw75BZj+f7f9dVqdSJYHSX8CLwlre lbpdaM2UpBPNkP17COrN9H9QlzUHzX2hjFB/gZE85FDY/l3KZJVQG2OFKMBJl9LwfHzH HGwX9SdbXsw4u5Fgb4Hhwzh5BMQB2ETXR8OHmQ+b+2RWls4mlji73sL86mDrCgJPfDcZ 5G7WFlvI+D9YwdzDNPbCiw+dz+PwZq39EmqUz2M9RNnHawblH6YCP5m/vPxFk9ttGxVD BkPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468762; x=1702073562; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=v1CXtGZj8aSs4z9SIQWwUOQcwGx+Gif/0Em+QUOV9hY=; b=EImjiKzRr815mjhXGPve94HK1Ck0fwSftK8GdQYeBb6cXTBdf5gMC2GwFZ1uyZOhh7 22eABUWZ8ppb/WT6vqOTOHWfwqKDhXZqB2mQLkZj6AuowvOL+l5M1K6n0gK/dbih+zAU CXeerYhdcq1Uad8cZViFAKTWQQzO2s/mdNpIJwYdfCGoGyFyHu7tp+BlugJnMGbkCFKa LHU2qzryhAneTgGlBQmq2OT3zODVtwgzCbhw/J3Jtop7KItgBwDxGqGjiZLb7MzDdq91 upd80E96XYSmjJyN3yPcEgj2XQXl2pn3k7L7BtU2kkod3k4g7Pfi1g7cW1pzDkQmGkwx rTkA== X-Gm-Message-State: AOJu0Yw8K4bt/2SP6uqPxUzBLGMKF2nDUrlZLyBlhyIrUKQLh54sIB7q jfWYNi1a/0q0JHIslnOHuSSuXJzYqPZ34ATQYAG6Jg== X-Google-Smtp-Source: AGHT+IGmK971rBsW1VRYTTXnV7cJUDtBlM2T7O/hse/3XKOvVh6tKvC4KObxrGlz18VvEQeUulw6wg== X-Received: by 2002:a54:4014:0:b0:3b8:9025:57d7 with SMTP id x20-20020a544014000000b003b8902557d7mr214732oie.3.1701468760678; Fri, 01 Dec 2023 14:12:40 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id d3-20020a256803000000b00d9ca9243ad5sm640348ybc.38.2023.12.01.14.12.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:40 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 34/46] btrfs: set the bio fscrypt context when applicable Date: Fri, 1 Dec 2023 17:11:31 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Now that we have the fscrypt_info plumbed through everywhere, add the code to setup the bio encryption context from the extent context. We use the per-extent fscrypt_extent_info for encryption/decryption. We use the offset into the extent as the lblk for fscrypt. So the start of the extent has the lblk of 0, 4k into the extent has the lblk of 4k, etc. This is done to allow things like relocation to continue to work properly. Signed-off-by: Josef Bacik --- fs/btrfs/compression.c | 6 ++++ fs/btrfs/extent_io.c | 76 +++++++++++++++++++++++++++++++++++++++++- fs/btrfs/fscrypt.c | 36 ++++++++++++++++++++ fs/btrfs/fscrypt.h | 22 ++++++++++++ fs/btrfs/inode.c | 10 ++++++ 5 files changed, 149 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 05595d113ff8..a71614359c33 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -37,6 +37,7 @@ #include "zoned.h" #include "file-item.h" #include "super.h" +#include "fscrypt.h" static struct bio_set btrfs_compressed_bioset; @@ -396,6 +397,9 @@ void btrfs_submit_compressed_write(struct btrfs_ordered_extent *ordered, cb->bbio.ordered = ordered; btrfs_add_compressed_bio_pages(cb); + btrfs_set_bio_crypt_ctx_from_extent(&cb->bbio.bio, inode, + ordered->fscrypt_info, 0); + btrfs_submit_bio(&cb->bbio, 0); } @@ -599,6 +603,8 @@ void btrfs_submit_compressed_read(struct btrfs_bio *bbio) cb->compress_type = em->compress_type; cb->orig_bbio = bbio; + btrfs_set_bio_crypt_ctx_from_extent(&cb->bbio.bio, inode, + em->fscrypt_info, 0); free_extent_map(em); cb->nr_pages = DIV_ROUND_UP(compressed_len, PAGE_SIZE); diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 42544c0d9ee1..9824dd356e3c 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -36,6 +36,7 @@ #include "dev-replace.h" #include "super.h" #include "transaction.h" +#include "fscrypt.h" static struct kmem_cache *extent_buffer_cache; @@ -102,6 +103,10 @@ struct btrfs_bio_ctrl { blk_opf_t opf; btrfs_bio_end_io_t end_io_func; struct writeback_control *wbc; + + /* This is set for reads and we have encryption. */ + struct fscrypt_extent_info *fscrypt_info; + u64 orig_start; }; static void submit_one_bio(struct btrfs_bio_ctrl *bio_ctrl) @@ -708,10 +713,31 @@ static bool btrfs_bio_is_contig(struct btrfs_bio_ctrl *bio_ctrl, struct page *page, u64 disk_bytenr, unsigned int pg_offset) { - struct bio *bio = &bio_ctrl->bbio->bio; + struct inode *inode = page->mapping->host; + struct btrfs_bio *bbio = bio_ctrl->bbio; + struct bio *bio = &bbio->bio; struct bio_vec *bvec = bio_last_bvec_all(bio); const sector_t sector = disk_bytenr >> SECTOR_SHIFT; + if (IS_ENCRYPTED(inode)) { + u64 file_offset = page_offset(page) + pg_offset; + u64 offset = 0; + struct fscrypt_extent_info *fscrypt_info = NULL; + + /* bio_ctrl->fscrypt_info is only set in the READ case. */ + if (bio_ctrl->fscrypt_info) { + offset = file_offset - bio_ctrl->orig_start; + fscrypt_info = bio_ctrl->fscrypt_info; + } else if (bbio->ordered) { + fscrypt_info = bbio->ordered->fscrypt_info; + offset = file_offset - bbio->ordered->orig_offset; + } + + if (!btrfs_mergeable_encrypted_bio(bio, inode, fscrypt_info, + offset)) + return false; + } + if (bio_ctrl->compress_type != BTRFS_COMPRESS_NONE) { /* * For compression, all IO should have its logical bytenr set @@ -742,6 +768,8 @@ static void alloc_new_bio(struct btrfs_inode *inode, { struct btrfs_fs_info *fs_info = inode->root->fs_info; struct btrfs_bio *bbio; + struct fscrypt_extent_info *fscrypt_info = NULL; + u64 offset = 0; bbio = btrfs_bio_alloc(BIO_MAX_VECS, bio_ctrl->opf, fs_info, bio_ctrl->end_io_func, NULL); @@ -761,6 +789,8 @@ static void alloc_new_bio(struct btrfs_inode *inode, ordered->file_offset + ordered->disk_num_bytes - file_offset); bbio->ordered = ordered; + fscrypt_info = ordered->fscrypt_info; + offset = file_offset - ordered->orig_offset; } /* @@ -771,7 +801,13 @@ static void alloc_new_bio(struct btrfs_inode *inode, */ bio_set_dev(&bbio->bio, fs_info->fs_devices->latest_dev->bdev); wbc_init_bio(bio_ctrl->wbc, &bbio->bio); + } else { + fscrypt_info = bio_ctrl->fscrypt_info; + offset = file_offset - bio_ctrl->orig_start; } + + btrfs_set_bio_crypt_ctx_from_extent(&bbio->bio, inode, fscrypt_info, + offset); } /* @@ -815,6 +851,19 @@ static void submit_extent_page(struct btrfs_bio_ctrl *bio_ctrl, len = bio_ctrl->len_to_oe_boundary; } + /* + * Encryption has to allocate bounce buffers to encrypt the bio, + * and we need to make sure that it doesn't split the bio so we + * retain all of our special info in the btrfs_bio, so submit + * any bio that gets up to BIO_MAX_VECS worth of segments. + */ + if (IS_ENCRYPTED(&inode->vfs_inode) && + bio_data_dir(&bio_ctrl->bbio->bio) == WRITE && + bio_segments(&bio_ctrl->bbio->bio) == BIO_MAX_VECS) { + submit_one_bio(bio_ctrl); + continue; + } + if (bio_add_page(&bio_ctrl->bbio->bio, page, len, pg_offset) != len) { /* bio full: move on to a new one */ submit_one_bio(bio_ctrl); @@ -1008,6 +1057,8 @@ static int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, bool force_bio_submit = false; u64 disk_bytenr; + bio_ctrl->fscrypt_info = NULL; + ASSERT(IS_ALIGNED(cur, fs_info->sectorsize)); if (cur >= last_byte) { iosize = PAGE_SIZE - pg_offset; @@ -1082,6 +1133,22 @@ static int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, if (prev_em_start) *prev_em_start = em->start; + /* + * We use the extent offset for the IV when decrypting the page, + * so we have to set the extent_offset based on the orig_start + * for this extent. Also save the fscrypt_info so the bio ctx + * can be set properly. If this inode isn't encrypted this + * won't do anything. + * + * If we're compressed we'll handle all of this in + * btrfs_submit_compressed_read. + */ + if (compress_type == BTRFS_COMPRESS_NONE) { + bio_ctrl->orig_start = em->orig_start; + bio_ctrl->fscrypt_info = + fscrypt_get_extent_info(em->fscrypt_info); + } + free_extent_map(em); em = NULL; @@ -1093,6 +1160,9 @@ static int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, end_page_read(page, true, cur, iosize); cur = cur + iosize; pg_offset += iosize; + + /* This shouldn't be set, but clear it just in case. */ + fscrypt_put_extent_info(bio_ctrl->fscrypt_info); continue; } /* the get_extent function already copied into the page */ @@ -1101,6 +1171,9 @@ static int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, end_page_read(page, true, cur, iosize); cur = cur + iosize; pg_offset += iosize; + + /* This shouldn't be set, but clear it just in case. */ + fscrypt_put_extent_info(bio_ctrl->fscrypt_info); continue; } @@ -1113,6 +1186,7 @@ static int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, submit_one_bio(bio_ctrl); submit_extent_page(bio_ctrl, disk_bytenr, page, iosize, pg_offset); + fscrypt_put_extent_info(bio_ctrl->fscrypt_info); cur = cur + iosize; pg_offset += iosize; } diff --git a/fs/btrfs/fscrypt.c b/fs/btrfs/fscrypt.c index 7a7272cb83ec..726cb6121934 100644 --- a/fs/btrfs/fscrypt.c +++ b/fs/btrfs/fscrypt.c @@ -262,6 +262,42 @@ size_t btrfs_fscrypt_extent_context_size(struct btrfs_inode *inode) fscrypt_extent_context_size(&inode->vfs_inode); } +void btrfs_set_bio_crypt_ctx_from_extent(struct bio *bio, + struct btrfs_inode *inode, + struct fscrypt_extent_info *fi, + u64 logical_offset) +{ + if (!fi) + return; + + /* + * fscrypt uses bytes >> s_blocksize_bits for the block numbers, so we + * have to adjust everything based on our sectorsize so that the DUN + * calculations are correct. + */ + logical_offset = div64_u64(logical_offset, + inode->root->fs_info->sectorsize); + fscrypt_set_bio_crypt_ctx_from_extent(bio, &inode->vfs_inode, fi, + logical_offset, GFP_NOFS); +} + +bool btrfs_mergeable_encrypted_bio(struct bio *bio, struct inode *inode, + struct fscrypt_extent_info *fi, + u64 logical_offset) +{ + if (!fi) + return true; + + /* + * fscrypt uses bytes >> s_blocksize_bits for the block numbers, so we + * have to adjust everything based on our sectorsize so that the DUN + * calculations are correct. + */ + logical_offset = div64_u64(logical_offset, + BTRFS_I(inode)->root->fs_info->sectorsize); + return fscrypt_mergeable_extent_bio(bio, inode, fi, logical_offset); +} + const struct fscrypt_operations btrfs_fscrypt_ops = { .has_per_extent_encryption = 1, .get_context = btrfs_fscrypt_get_context, diff --git a/fs/btrfs/fscrypt.h b/fs/btrfs/fscrypt.h index 2882a4a9d978..756375ade0b6 100644 --- a/fs/btrfs/fscrypt.h +++ b/fs/btrfs/fscrypt.h @@ -28,6 +28,13 @@ int btrfs_fscrypt_save_extent_info(struct btrfs_inode *inode, struct btrfs_path *path, struct fscrypt_extent_info *fi); size_t btrfs_fscrypt_extent_context_size(struct btrfs_inode *inode); +void btrfs_set_bio_crypt_ctx_from_extent(struct bio *bio, + struct btrfs_inode *inode, + struct fscrypt_extent_info *fi, + u64 logical_offset); +bool btrfs_mergeable_encrypted_bio(struct bio *bio, struct inode *inode, + struct fscrypt_extent_info *fi, + u64 logical_offset); #else static inline int btrfs_fscrypt_save_extent_info(struct btrfs_inode *inode, @@ -66,6 +73,21 @@ static inline size_t btrfs_fscrypt_extent_context_size(struct btrfs_inode *inode { return 0; } + +static inline void btrfs_set_bio_crypt_ctx_from_extent(struct bio *bio, + struct btrfs_inode *inode, + struct fscrypt_extent_info *fi, + u64 logical_offset) +{ +} + +static inline bool btrfs_mergeable_encrypted_bio(struct bio *bio, + struct inode *inode, + struct fscrypt_extent_info *fi, + u64 logical_offset) +{ + return true; +} #endif /* CONFIG_FS_ENCRYPTION */ extern const struct fscrypt_operations btrfs_fscrypt_ops; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3dce53601915..c5878da937d3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7932,6 +7932,8 @@ static void btrfs_dio_submit_io(const struct iomap_iter *iter, struct bio *bio, struct btrfs_dio_private *dip = container_of(bbio, struct btrfs_dio_private, bbio); struct btrfs_dio_data *dio_data = iter->private; + struct fscrypt_extent_info *fscrypt_info = NULL; + u64 offset = 0; btrfs_bio_init(bbio, BTRFS_I(iter->inode)->root->fs_info, btrfs_dio_end_io, bio->bi_private); @@ -7953,6 +7955,9 @@ static void btrfs_dio_submit_io(const struct iomap_iter *iter, struct bio *bio, if (iter->flags & IOMAP_WRITE) { int ret; + offset = file_offset - dio_data->ordered->orig_offset; + fscrypt_info = dio_data->ordered->fscrypt_info; + ret = btrfs_extract_ordered_extent(bbio, dio_data->ordered); if (ret) { btrfs_finish_ordered_extent(dio_data->ordered, NULL, @@ -7962,8 +7967,13 @@ static void btrfs_dio_submit_io(const struct iomap_iter *iter, struct bio *bio, iomap_dio_bio_end_io(bio); return; } + } else { + fscrypt_info = dio_data->fscrypt_info; + offset = file_offset - dio_data->orig_start; } + btrfs_set_bio_crypt_ctx_from_extent(&bbio->bio, bbio->inode, + fscrypt_info, offset); btrfs_submit_bio(bbio, 0); } From patchwork Fri Dec 1 22:11:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476522 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="dawyIGX+" Received: from mail-yw1-x1142.google.com (mail-yw1-x1142.google.com [IPv6:2607:f8b0:4864:20::1142]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8344B128 for ; Fri, 1 Dec 2023 14:12:42 -0800 (PST) Received: by mail-yw1-x1142.google.com with SMTP id 00721157ae682-5d226f51f71so29289837b3.3 for ; Fri, 01 Dec 2023 14:12:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468761; x=1702073561; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=L4BaCdes/ph+FBDRPrYEBu7SdLjcMrWxDC5DvBg0S2c=; b=dawyIGX+/j59Fp3QrYmEvDcVaU+x2kXvhW57+7o2teFoRRIUe5UUg4PP1GMybleo8h bdTOZJ560HzLFn4sjfMrSTYQZojfoTzgRjcodOdyWIVaK/wApesL8uHs6Ed8LC3XNGfO TSnyNBzT38z7BhtFCG9S0+3B2l+oIl3EjO8XvCeDwCCIdBRar/j9akjTgEbsGLfZv7OE xlHBi/Ble4+ZQLacQc57d0hqUhw1x6Wz2x1wxWJsNGHPazp1ywwXOx0igi47gootvv2h QgkTOcOwjlYtpqbsOBgwLxhEq/N6JOAwBaIemaqnBw3Mil6Fd4ZHWPljw/Vh3RXR30LI mApQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468761; x=1702073561; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=L4BaCdes/ph+FBDRPrYEBu7SdLjcMrWxDC5DvBg0S2c=; b=netzY62Fco7of00HyAjB31tDw7eRrT7eD7q8KcfjR8TMB9f7qARUUw30vk5Nu5dYqE 1j/jHxMtSREqWWlKj+md6V6xyNizvAfP/4eSfzX26jcor5cq5PDVDg+UEd6q13Vrwmoh lBFKvC778287gStfX0Qk+LRdkBgl/RBggsU/OHWRv65NVZIXdTAO/LxZK7lm2TkEUU2u Bk4TOlDfwnx58KCMcvvW5ulo4ug7S1O8+KNCxiQ+ZGJk0f9tuNadNGtr/NVTI7kagy+9 AUk0pwMY8tubv2vKeQDOqKRKa01FwomKJDPSyYM+tM3wfWdWszhnFg9U3ObMQDXvOGy7 wRCg== X-Gm-Message-State: AOJu0Yxfbc9HBrbfNmF2QM3Y5eceF9z3eU/ikxBXuNdM49pZi2oV8Ke/ hAEHPTctU7JXpOyRkSi+WkQas7V/HRtiEMM27uQWOep7 X-Google-Smtp-Source: AGHT+IHv1vmVGzBHq4wlGFfWaZrQW10oFqCawez4SOwK+6gJ8tnHa9ANJDCH21YK3W74zvVznRBvSQ== X-Received: by 2002:a05:690c:3607:b0:5d0:edf:9bc4 with SMTP id ft7-20020a05690c360700b005d00edf9bc4mr339063ywb.18.1701468761646; Fri, 01 Dec 2023 14:12:41 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id y16-20020a81a110000000b005cf1ce8b96dsm1040981ywg.5.2023.12.01.14.12.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:41 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 35/46] btrfs: add a bio argument to btrfs_csum_one_bio Date: Fri, 1 Dec 2023 17:11:32 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We only ever needed the bbio in btrfs_csum_one_bio, since that has the bio embedded in it. However with encryption we'll have a different bio with the encrypted data in it, and the original bbio. Update btrfs_csum_one_bio to take the bio we're going to csum as an argument, which will allow us to csum the encrypted bio and stuff the csums into the corresponding bbio to be used later when the IO completes. Signed-off-by: Josef Bacik --- fs/btrfs/bio.c | 2 +- fs/btrfs/file-item.c | 3 +-- fs/btrfs/file-item.h | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c index 4f3b693a16b1..90e4d4709fa3 100644 --- a/fs/btrfs/bio.c +++ b/fs/btrfs/bio.c @@ -533,7 +533,7 @@ static blk_status_t btrfs_bio_csum(struct btrfs_bio *bbio) { if (bbio->bio.bi_opf & REQ_META) return btree_csum_one_bio(bbio); - return btrfs_csum_one_bio(bbio); + return btrfs_csum_one_bio(bbio, &bbio->bio); } /* diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 35036fab58c4..d925d6d98bf4 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -730,13 +730,12 @@ int btrfs_lookup_csums_bitmap(struct btrfs_root *root, struct btrfs_path *path, /* * Calculate checksums of the data contained inside a bio. */ -blk_status_t btrfs_csum_one_bio(struct btrfs_bio *bbio) +blk_status_t btrfs_csum_one_bio(struct btrfs_bio *bbio, struct bio *bio) { struct btrfs_ordered_extent *ordered = bbio->ordered; struct btrfs_inode *inode = bbio->inode; struct btrfs_fs_info *fs_info = inode->root->fs_info; SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); - struct bio *bio = &bbio->bio; struct btrfs_ordered_sum *sums; char *data; struct bvec_iter iter; diff --git a/fs/btrfs/file-item.h b/fs/btrfs/file-item.h index bb79014024bd..e52d5d71d533 100644 --- a/fs/btrfs/file-item.h +++ b/fs/btrfs/file-item.h @@ -51,7 +51,7 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_ordered_sum *sums); -blk_status_t btrfs_csum_one_bio(struct btrfs_bio *bbio); +blk_status_t btrfs_csum_one_bio(struct btrfs_bio *bbio, struct bio *bio); blk_status_t btrfs_alloc_dummy_sum(struct btrfs_bio *bbio); int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, struct list_head *list, int search_commit, From patchwork Fri Dec 1 22:11:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476524 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="kxYEW1Q9" Received: from mail-yw1-x1143.google.com (mail-yw1-x1143.google.com [IPv6:2607:f8b0:4864:20::1143]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B3F7610D0 for ; Fri, 1 Dec 2023 14:12:43 -0800 (PST) Received: by mail-yw1-x1143.google.com with SMTP id 00721157ae682-5d05ff42db0so29833237b3.2 for ; Fri, 01 Dec 2023 14:12:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468763; x=1702073563; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=tBfJ5LP4cPRaU4wHupG+Ey+k+InOBSbHn6NRjNRvG6k=; b=kxYEW1Q9EMIICWnG/QkP9Jt/iGyJdm8Dq3iO+I5fa7wgJnmBYuGN/zqu7DHxQTQ9gi Vwv7E0YBoVzeEgDEyF8ysdP+QPT4KfLqt4UuHlRLr1ExJznjNFy3m4WDZCxuMZOhupkL 0DGmhucMYXlM+viFUhBmKUoO2Whyphrou73kvTQynE+AGDvJAbvLckTeM9mTzfsOWYcL JVdYYl3iyTafE0QuHBgvuvpkwU8vQ9QSbAIaiIAmSI/VrMowvf1kEFJ4gokmNACgLc/R gcMS/l1EIiqGUsgI55JBPjen5k/IaMmyThO79ulXF5wDYg5PlM7DAaXXFp6t6PQFAO/5 iWOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468763; x=1702073563; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tBfJ5LP4cPRaU4wHupG+Ey+k+InOBSbHn6NRjNRvG6k=; b=sVD8WAWbd186TulnZrtduF9hUGeIOoums/70A+IYG2qRvflkqHd1vUv03V0Y2CCloV KxWu7g16iWtRzWPwR3Ls038HgFoVgG/WmdhD1ZSuVaO/298WXydrtov6urma4UIoreO2 VC9xxwP3EvSyRbhFoW7lMPf2Gh10V7wB8n6R4d3ks8Os6i7pEjA1KrqSzc5XsQMcJ9Vw 5fwlHrUrg5ZTrDzS0ha+IoGgi/Wg1NSfBrjOK5AzIIKcMFpRouby5P8RAOr5cu1Zfni7 CJHodAr+iwYJcCJOzzKxCad4M/ZueaMeXAuWc5jnpHBdvLDTgylTlYFm3EXVwrLHOqPl zeuA== X-Gm-Message-State: AOJu0Yw/FVggjCrTOYaB46Zs1mcG2N31Rm3rEelyi6LAG1hhEOwVk/sU Q4DJzn0lv784LWkc8jnzPltFBuZdgy3tYlJlRajfRI9L X-Google-Smtp-Source: AGHT+IGi+2G+GsDsi7vKKAg8Gt5OHvNPUGxhK0AXWDsRkrstC8LCZFqZHvQtkSYYZeOORiW5/ur+Ng== X-Received: by 2002:a81:57d8:0:b0:5d3:adfd:ff7d with SMTP id l207-20020a8157d8000000b005d3adfdff7dmr272703ywb.12.1701468762767; Fri, 01 Dec 2023 14:12:42 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id p67-20020a819846000000b005d379110c89sm1235459ywg.8.2023.12.01.14.12.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:42 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 36/46] btrfs: add orig_logical to btrfs_bio Date: Fri, 1 Dec 2023 17:11:33 -0500 Message-ID: <26716dcde48fe6abde781dbe2a1f4c0d99f6c4b0.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 When checksumming the encrypted bio on writes we need to know which logical address this checksum is for. At the point where we get the encrypted bio the bi_sector is the physical location on the target disk, so we need to save the original logical offset in the btrfs_bio. Then we can use this when csum'ing the bio instead of the bio->iter.bi_sector. Signed-off-by: Josef Bacik --- fs/btrfs/bio.c | 10 ++++++++++ fs/btrfs/bio.h | 3 +++ fs/btrfs/file-item.c | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c index 90e4d4709fa3..52f027877aaa 100644 --- a/fs/btrfs/bio.c +++ b/fs/btrfs/bio.c @@ -96,6 +96,8 @@ static struct btrfs_bio *btrfs_split_bio(struct btrfs_fs_info *fs_info, if (bbio_has_ordered_extent(bbio)) { refcount_inc(&orig_bbio->ordered->refs); bbio->ordered = orig_bbio->ordered; + bbio->orig_logical = orig_bbio->orig_logical; + orig_bbio->orig_logical += map_length; } atomic_inc(&orig_bbio->pending_ios); return bbio; @@ -674,6 +676,14 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num) goto fail; } + /* + * For fscrypt writes we will get the encrypted bio after we've remapped + * our bio to the physical disk location, so we need to save the + * original bytenr so we know what we're checksumming. + */ + if (bio_op(bio) == REQ_OP_WRITE && is_data_bbio(bbio)) + bbio->orig_logical = logical; + map_length = min(map_length, length); if (use_append) map_length = min(map_length, fs_info->max_zone_append_size); diff --git a/fs/btrfs/bio.h b/fs/btrfs/bio.h index ca79decee060..5d3f53dcd6d5 100644 --- a/fs/btrfs/bio.h +++ b/fs/btrfs/bio.h @@ -54,11 +54,14 @@ struct btrfs_bio { * - pointer to the checksums for this bio * - original physical address from the allocator * (for zone append only) + * - original logical address, used for checksumming fscrypt + * bios. */ struct { struct btrfs_ordered_extent *ordered; struct btrfs_ordered_sum *sums; u64 orig_physical; + u64 orig_logical; }; /* For metadata reads: parentness verification. */ diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index d925d6d98bf4..26e3bc602655 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -756,7 +756,7 @@ blk_status_t btrfs_csum_one_bio(struct btrfs_bio *bbio, struct bio *bio) sums->len = bio->bi_iter.bi_size; INIT_LIST_HEAD(&sums->list); - sums->logical = bio->bi_iter.bi_sector << SECTOR_SHIFT; + sums->logical = bbio->orig_logical; index = 0; shash->tfm = fs_info->csum_shash; From patchwork Fri Dec 1 22:11:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476525 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="iiXXfmFR" Received: from mail-yw1-x1142.google.com (mail-yw1-x1142.google.com [IPv6:2607:f8b0:4864:20::1142]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0289410EF for ; Fri, 1 Dec 2023 14:12:45 -0800 (PST) Received: by mail-yw1-x1142.google.com with SMTP id 00721157ae682-5d40c728fc4so10050447b3.1 for ; Fri, 01 Dec 2023 14:12:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468764; x=1702073564; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=5v0XMPAwxYBm92FM0C0pU/Uz9MIFNdU5pAo7nP1a6gE=; b=iiXXfmFRfENd23CP4W9p77HZ+NYMcmSVgMk0Nyb4qkh5EgToo7UutZjK7QnPRewDAj RFDsawRKh2HxVwLRo4LwVfYRHdQIsn5TLD5WnVyaWfKqtpnB7ElUN7/S9bRruqeaMoQY UNMfFzqLkJGocG3wc0hI+tWufmutS8YpZjEXcRGoj5V6Vk8e3I6UQD72d+XpyDzjgNit 50EsOgqm8AgemCEJEqF0pDQlwzPtNPI5CSKhpjLyyOopo4vv+cTRq03/jdX4oVsutLgE qhaD1aVkRs7JBeLwCcUUd+clLzA1T6kya9U2lUEQZSjdzk5U/1AQ4ucy6vi8NJJBXxZo iCpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468764; x=1702073564; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5v0XMPAwxYBm92FM0C0pU/Uz9MIFNdU5pAo7nP1a6gE=; b=YhTGEcNz6ug2wJijNJwknu12fvtBHurDwupRClO1ge7ZQy8l2T+v1ThwoO+jO798NQ axlgQXg22xbj2/oA64BSlMGY1RSa2mMO6TwF0uwmlEjRN88r23XPlqWU2nsQiPUOjTJQ zZPeqhwOfZYDCMQQEWJT50vUodUM+zmc8AchV773WP8gbQqqLIU3mTFL5YP/YUbPcuzC 6Rz9bZX12EL6IkVF8+2vVssa4KhjSopva8GxBJZFa4yFu0TMBdA4UtQrBKD6l17Q5lXz 4fqdFO4rKipUI6PHAieSPKhpRexO49coB9tu0cttPZ02uYu5DedcSz3Y4m2BIfuY1OoM ICwQ== X-Gm-Message-State: AOJu0YzvewBdrChnmrHAV/i7Fe1SWeEVlL0om1sse15MCmXKpZo+KXb3 sC3HyLDL0VDXKYtQ/Hmeg9Bnm12wUka2j8jIQrl3gxwY X-Google-Smtp-Source: AGHT+IFkvM3XUrtssH9qZKSM42wRJBebPHfPbVTfdNsm9seGvGySxoGqGonv/o2sWC2ZwYE4uYErMg== X-Received: by 2002:a05:690c:1b:b0:5d7:1a33:5ae4 with SMTP id bc27-20020a05690c001b00b005d71a335ae4mr140740ywb.49.1701468764068; Fri, 01 Dec 2023 14:12:44 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id q2-20020a815c02000000b005a23fc389d8sm1381537ywb.103.2023.12.01.14.12.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:43 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 37/46] btrfs: limit encrypted writes to 256 segments Date: Fri, 1 Dec 2023 17:11:34 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 For the fallback encrypted writes it allocates a bounce buffer to encrypt, and if the bio is larger than 256 segments it splits the bio we send down. This wreaks havoc on us because we need our actual original bio to be passed into the process_cb callback in order to get at our ordered extent. With the split we'll get some cloned bio that has none of our information. Handle this by returning the length we need to be truncated to and then splitting ourselves, which will handle giving us the correct btrfs_bio that we need. Signed-off-by: Josef Bacik --- fs/btrfs/bio.c | 29 ++++++++++++++++++++++++++++- fs/btrfs/fscrypt.c | 24 ++++++++++++++++++++++++ fs/btrfs/fscrypt.h | 6 ++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c index 52f027877aaa..ef3f98b3ec3f 100644 --- a/fs/btrfs/bio.c +++ b/fs/btrfs/bio.c @@ -15,6 +15,7 @@ #include "zoned.h" #include "file-item.h" #include "raid-stripe-tree.h" +#include "fscrypt.h" static struct bio_set btrfs_bioset; static struct bio_set btrfs_clone_bioset; @@ -660,6 +661,7 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num) u64 logical = bio->bi_iter.bi_sector << SECTOR_SHIFT; u64 length = bio->bi_iter.bi_size; u64 map_length = length; + u64 max_bio_len = length; bool use_append = btrfs_use_zone_append(bbio); struct btrfs_io_context *bioc = NULL; struct btrfs_io_stripe smap; @@ -669,6 +671,31 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num) smap.is_scrub = !bbio->inode; btrfs_bio_counter_inc_blocked(fs_info); + + /* + * The blk-crypto-fallback limits bio sizes to 256 segments, because it + * has no way of controlling the pages it gets for the bounce bio it + * submits. + * + * If we don't pre-split our bio blk-crypto-fallback will do it for us, + * and then call into our checksum callback with a random cloned bio + * that isn't a btrfs_bio. + * + * To account for this we must truncate the bio ourselves, so we need to + * get our length at 256 segments and return that. We must do this + * before btrfs_map_block because the RAID5/6 code relies on having + * properly stripe aligned things, so we return the truncated length + * here so that btrfs_map_block() does the correct thing. Further down + * we actually truncate map_length to map_bio_len because map_length + * will be set to whatever the mapping length is for the underlying + * geometry. This will work properly with RAID5/6 as it will have + * already setup everything for the expected length, and everything else + * can handle with a truncated map_length. + */ + if (bio_has_crypt_ctx(bio)) + max_bio_len = btrfs_fscrypt_bio_length(bio, map_length); + + map_length = max_bio_len; error = btrfs_map_block(fs_info, btrfs_op(bio), logical, &map_length, &bioc, &smap, &mirror_num); if (error) { @@ -684,7 +711,7 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num) if (bio_op(bio) == REQ_OP_WRITE && is_data_bbio(bbio)) bbio->orig_logical = logical; - map_length = min(map_length, length); + map_length = min(map_length, max_bio_len); if (use_append) map_length = min(map_length, fs_info->max_zone_append_size); diff --git a/fs/btrfs/fscrypt.c b/fs/btrfs/fscrypt.c index 726cb6121934..419b0f6d8629 100644 --- a/fs/btrfs/fscrypt.c +++ b/fs/btrfs/fscrypt.c @@ -298,6 +298,30 @@ bool btrfs_mergeable_encrypted_bio(struct bio *bio, struct inode *inode, return fscrypt_mergeable_extent_bio(bio, inode, fi, logical_offset); } +/* + * The block crypto stuff allocates bounce buffers for encryption, so splits at + * BIO_MAX_VECS worth of segments. If we are larger than that number of + * segments then we need to limit the size to the size that BIO_MAX_VECS covers. + */ +int btrfs_fscrypt_bio_length(struct bio *bio, u64 map_length) +{ + unsigned int i = 0; + struct bio_vec bv; + struct bvec_iter iter; + u64 segments_length = 0; + + if (bio_op(bio) != REQ_OP_WRITE) + return map_length; + + bio_for_each_segment(bv, bio, iter) { + segments_length += bv.bv_len; + if (++i == BIO_MAX_VECS) + return segments_length; + } + + return map_length; +} + const struct fscrypt_operations btrfs_fscrypt_ops = { .has_per_extent_encryption = 1, .get_context = btrfs_fscrypt_get_context, diff --git a/fs/btrfs/fscrypt.h b/fs/btrfs/fscrypt.h index 756375ade0b6..c4a327be0eeb 100644 --- a/fs/btrfs/fscrypt.h +++ b/fs/btrfs/fscrypt.h @@ -35,6 +35,7 @@ void btrfs_set_bio_crypt_ctx_from_extent(struct bio *bio, bool btrfs_mergeable_encrypted_bio(struct bio *bio, struct inode *inode, struct fscrypt_extent_info *fi, u64 logical_offset); +int btrfs_fscrypt_bio_length(struct bio *bio, u64 map_length); #else static inline int btrfs_fscrypt_save_extent_info(struct btrfs_inode *inode, @@ -88,6 +89,11 @@ static inline bool btrfs_mergeable_encrypted_bio(struct bio *bio, { return true; } + +static inline u64 btrfs_fscrypt_bio_length(struct bio *bio, u64 map_length) +{ + return map_length; +} #endif /* CONFIG_FS_ENCRYPTION */ extern const struct fscrypt_operations btrfs_fscrypt_ops; From patchwork Fri Dec 1 22:11:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476526 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="dDyXAWAr" Received: from mail-yb1-xb44.google.com (mail-yb1-xb44.google.com [IPv6:2607:f8b0:4864:20::b44]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0439510D for ; Fri, 1 Dec 2023 14:12:46 -0800 (PST) Received: by mail-yb1-xb44.google.com with SMTP id 3f1490d57ef6-dafe04717baso992490276.1 for ; Fri, 01 Dec 2023 14:12:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468765; x=1702073565; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=NcN10ZukHzvXtGLikAWaW+PN73UabSkdq95rYCkOREY=; b=dDyXAWArS/r6i3q8gXSfP2sMZ1xMeV5n7EcKBeW0wxdbL0oUt7zJ78hHr92BNrNRoX BcsbJYE0/fS1Jdl8npp8zxDoENPYOk8+vDQTKidThFx4F11S5qx+9X3Ftks+cFsbST5E 8ZKqO4XT0vLBeZrmeu+NTx5vbz28PUzn4Vxtz++vsnHXg6D46ZPQOsuP+Z0WCfEcv8M3 dyE1mhEUf1rW9MmvJd+8FjXqNzAusnroE5dM4PtaUKcbtaBDRNfGMAdoyzobqQGYGXEo iaXzQbkdve618h79bhTc0e5zfruHt68cuujhuAXwoOF0go1iMSx476kvzrfj29APmCHJ CRxA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468765; x=1702073565; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NcN10ZukHzvXtGLikAWaW+PN73UabSkdq95rYCkOREY=; b=V1F/C7svmKex8s0M7Qz8EK0tz/BbqRysJFCu6k5Y6t2FOlfSo6zB/vYdAFRkdvaNEe g81877R7EM3mKu0lgKiVqk6jpqKSuYdfmlWiFvCJNmIsVSMRC4hxBM2gp02Kng8dyWjj dozJ6vdY43FMONdUZlj4Jsisy7B75/EWT9XU3UWbBFZiAaZYPri14Leai+rhpDTSvw/5 QVvMGfBl2ZidmZSlc5pj/hOU6zZcjvM/EuUifu9RV6Z/i/sY60Ge5z0d8NShIHNLIh1F Jkgx9lt3VDi4IfHlmfjC+3hYUbDzlzOrk8yyxdsIREa+oEVjbB4phcVhQWpU/30EpYUa PCyw== X-Gm-Message-State: AOJu0Yyd1uzCBXbOef28XuXumU8TSKbP/94aYC44QRbZ4K2/jK66kRas CePCO4XR5Vm6DfeXHKNHh4fYLdXXFWsbs/h3T//1L/JX X-Google-Smtp-Source: AGHT+IGRxL5QDtjRhHUSGIEwY5tp/SmY4vl8W5gVcz79mjyNqKo4FBLtFZK3vQmACXmbpwabqNbw/Q== X-Received: by 2002:a25:ccd5:0:b0:db7:dacf:6ff4 with SMTP id l204-20020a25ccd5000000b00db7dacf6ff4mr146647ybf.124.1701468765014; Fri, 01 Dec 2023 14:12:45 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id z17-20020a25bb11000000b00d8679407796sm615186ybg.48.2023.12.01.14.12.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:44 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 38/46] btrfs: implement process_bio cb for fscrypt Date: Fri, 1 Dec 2023 17:11:35 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We are going to be checksumming the encrypted data, so we have to implement the ->process_bio fscrypt callback. This will provide us with the original bio and the encrypted bio to do work on. For WRITE's this will happen after the encrypted bio has been encrypted. For READ's this will happen after the read has completed and before the decryption step is done. For write's this is straightforward, we can just pass in the encrypted bio to btrfs_csum_one_bio and then the csums will be added to the bbio as normal. For read's this is relatively straightforward, but requires some care. We assume (because that's how it works currently) that the encrypted bio match the original bio, this is important because we save the iter of the bio before we submit. If this changes in the future we'll need a hook to give us the bi_iter of the decryption bio before it's submitted. We check the csums before decryption. If it doesn't match we simply error out and we let the normal path handle the repair work. Signed-off-by: Josef Bacik --- fs/btrfs/bio.c | 34 +++++++++++++++++++++++++++++++++- fs/btrfs/bio.h | 3 +++ fs/btrfs/fscrypt.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c index ef3f98b3ec3f..494b3ba05f7a 100644 --- a/fs/btrfs/bio.c +++ b/fs/btrfs/bio.c @@ -282,6 +282,34 @@ static struct btrfs_failed_bio *repair_one_sector(struct btrfs_bio *failed_bbio, return fbio; } +blk_status_t btrfs_check_encrypted_read_bio(struct btrfs_bio *bbio, + struct bio *enc_bio) +{ + struct btrfs_inode *inode = bbio->inode; + struct btrfs_fs_info *fs_info = inode->root->fs_info; + u32 sectorsize = fs_info->sectorsize; + struct bvec_iter iter = bbio->saved_iter; + struct btrfs_device *dev = bbio->bio.bi_private; + u32 offset = 0; + + /* + * We have to use a copy of iter in case there's an error, + * btrfs_check_read_bio will handle submitting the repair bios. + */ + while (iter.bi_size) { + struct bio_vec bv = bio_iter_iovec(enc_bio, iter); + + bv.bv_len = min(bv.bv_len, sectorsize); + if (!btrfs_data_csum_ok(bbio, dev, offset, &bv)) + return BLK_STS_IOERR; + bio_advance_iter_single(enc_bio, &iter, sectorsize); + offset += sectorsize; + } + + bbio->csum_done = true; + return BLK_STS_OK; +} + static void btrfs_check_read_bio(struct btrfs_bio *bbio, struct btrfs_device *dev) { struct btrfs_inode *inode = bbio->inode; @@ -307,6 +335,10 @@ static void btrfs_check_read_bio(struct btrfs_bio *bbio, struct btrfs_device *de /* Clear the I/O error. A failed repair will reset it. */ bbio->bio.bi_status = BLK_STS_OK; + /* This was an encrypted bio and we've already done the csum check. */ + if (status == BLK_STS_OK && bbio->csum_done) + goto out; + while (iter->bi_size) { struct bio_vec bv = bio_iter_iovec(&bbio->bio, *iter); @@ -317,7 +349,7 @@ static void btrfs_check_read_bio(struct btrfs_bio *bbio, struct btrfs_device *de bio_advance_iter_single(&bbio->bio, iter, sectorsize); offset += sectorsize; } - +out: if (bbio->csum != bbio->csum_inline) kfree(bbio->csum); diff --git a/fs/btrfs/bio.h b/fs/btrfs/bio.h index 5d3f53dcd6d5..393ef32f5321 100644 --- a/fs/btrfs/bio.h +++ b/fs/btrfs/bio.h @@ -45,6 +45,7 @@ struct btrfs_bio { struct { u8 *csum; u8 csum_inline[BTRFS_BIO_INLINE_CSUM_SIZE]; + bool csum_done; struct bvec_iter saved_iter; }; @@ -110,5 +111,7 @@ void btrfs_submit_repair_write(struct btrfs_bio *bbio, int mirror_num, bool dev_ int btrfs_repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start, u64 length, u64 logical, struct page *page, unsigned int pg_offset, int mirror_num); +blk_status_t btrfs_check_encrypted_read_bio(struct btrfs_bio *bbio, + struct bio *enc_bio); #endif diff --git a/fs/btrfs/fscrypt.c b/fs/btrfs/fscrypt.c index 419b0f6d8629..85b596711371 100644 --- a/fs/btrfs/fscrypt.c +++ b/fs/btrfs/fscrypt.c @@ -15,6 +15,7 @@ #include "transaction.h" #include "volumes.h" #include "xattr.h" +#include "file-item.h" /* * From a given location in a leaf, read a name into a qstr (usually a @@ -214,6 +215,33 @@ static struct block_device **btrfs_fscrypt_get_devices(struct super_block *sb, return devs; } +static blk_status_t btrfs_process_encrypted_bio(struct bio *orig_bio, + struct bio *enc_bio) +{ + struct btrfs_bio *bbio; + + /* + * If our bio is from the normal fs_bio_set then we know this is a + * mirror split and we can skip it, we'll get the real bio on the last + * mirror and we can process that one. + */ + if (orig_bio->bi_pool == &fs_bio_set) + return BLK_STS_OK; + + bbio = btrfs_bio(orig_bio); + + if (bio_op(orig_bio) == REQ_OP_READ) { + /* + * We have ->saved_iter based on the orig_bio, so if the block + * layer changes we need to notice this asap so we can update + * our code to handle the new world order. + */ + ASSERT(orig_bio == enc_bio); + return btrfs_check_encrypted_read_bio(bbio, enc_bio); + } + return btrfs_csum_one_bio(bbio, enc_bio); +} + int btrfs_fscrypt_load_extent_info(struct btrfs_inode *inode, struct extent_map *em, struct btrfs_fscrypt_ctx *ctx) @@ -328,4 +356,5 @@ const struct fscrypt_operations btrfs_fscrypt_ops = { .set_context = btrfs_fscrypt_set_context, .empty_dir = btrfs_fscrypt_empty_dir, .get_devices = btrfs_fscrypt_get_devices, + .process_bio = btrfs_process_encrypted_bio, }; From patchwork Fri Dec 1 22:11:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476528 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="Flj7Hs77" Received: from mail-yw1-x112b.google.com (mail-yw1-x112b.google.com [IPv6:2607:f8b0:4864:20::112b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3A47210F1 for ; Fri, 1 Dec 2023 14:12:47 -0800 (PST) Received: by mail-yw1-x112b.google.com with SMTP id 00721157ae682-5d3758fdd2eso23685737b3.0 for ; Fri, 01 Dec 2023 14:12:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468766; x=1702073566; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=orFc9ft3N/UoPwsjthsVKSwuN6/TtsfGvyUWZy1WZBs=; b=Flj7Hs77LD2rT4kfqxsPY0crWkFboQ4aWQfViy/PqG6Ha1BzjD/hfeiSZsXNLni2B/ 4ZDNnBHlPBODBRHJ6DcKAvOFOzj5r4SNHsvAc0fPORmRiC5wYBPCld1X10fA98ca3Al6 8vov20qgTN/70LShg9bCTfRbEx8dQ3o77LG0M04Pr4tQjkk08i0MBL2u6e5eARaYN26S 8Ic1PJrjO0/9FG+g4pD+WLi1FFkWrXp3/c7KTBgn5uGNB2p2xnWt1Q0Pu3MedNW1UdrH oSvogocXCXcXPFZbYpfdYc6wRE0uDeVn1Ou/ZTft4GSvqvEG2Hxl8zMHyVkuLObMF9jO CKLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468766; x=1702073566; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=orFc9ft3N/UoPwsjthsVKSwuN6/TtsfGvyUWZy1WZBs=; b=DIAGxlNhV+VDWi+TkWw1Pbe0gamnHnZ6jKneKgH9UB0EeYPAZ4X14e1nGQhSLVq65s zM22d81IJYr+wC9z1WwG1ee+NdM7WaouN4m5OWkGLbBCtRl9Sp80YHV5PZSGGeZyvqCk OSLg0ryen5sMAxbhRiAwjXOSW+deXqjbKgDsosz+QMLJe2xm25g0dbX8FP0UMmfImBfx Fbvp9EuBH0HHhhhyzBCo+UlyHHFsvZFcQzvm57V02QTdTldu6p2ezcr7SXSQjLKibFh9 mTxh5nxQ2cUKqn8UikiZgY0C2rPQ7odzNN08NBGSJ3f72bdb0JyPAvY9LVkGf+/XM17w SysA== X-Gm-Message-State: AOJu0YzViFh7xQMAgbq07mSnOGnj/w+nGUwuVEkEFicQLzsPJpwaGUEY LIIo5sqdYOR4R8VbW5EdzZoaKLyTiBxJeHxMaNp15g== X-Google-Smtp-Source: AGHT+IFuUAzLwk16Snq+KtsWjvULMLCdbsTWTAPfoHJhjL6e4RFJJa1D8aicRDwIsxQRCQnLxBqJ4Q== X-Received: by 2002:a05:690c:708:b0:5d3:55ae:90db with SMTP id bs8-20020a05690c070800b005d355ae90dbmr6409047ywb.20.1701468766288; Fri, 01 Dec 2023 14:12:46 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id q128-20020a819986000000b005ce93212c47sm1388975ywg.134.2023.12.01.14.12.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:45 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 39/46] btrfs: add test_dummy_encryption support Date: Fri, 1 Dec 2023 17:11:36 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In order to enable more thorough testing of fscrypt enable the test_dummy_encryption mount option. This is used by fscrypt users to easily enable fscrypt on the file system for testing without needing to do the key setup and everything. The only deviation from other file systems we make is we only support the fsparam_flag version of this mount option, as it defaults to v2. We don't want to have to bother with rejecting v1 related mount options. Signed-off-by: Josef Bacik --- fs/btrfs/disk-io.c | 1 + fs/btrfs/fs.h | 3 +++ fs/btrfs/fscrypt.c | 6 +++++ fs/btrfs/super.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 719245d73b99..aedd8a0e4962 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1272,6 +1272,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info) kfree(fs_info->super_copy); kfree(fs_info->super_for_commit); kfree(fs_info->subpage_info); + fscrypt_free_dummy_policy(&fs_info->dummy_enc_policy); kvfree(fs_info); } diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h index 1340e71d026c..74752204f3ab 100644 --- a/fs/btrfs/fs.h +++ b/fs/btrfs/fs.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "extent-io-tree.h" #include "extent_map.h" #include "async-thread.h" @@ -189,6 +190,7 @@ enum { BTRFS_MOUNT_IGNOREDATACSUMS = (1UL << 28), BTRFS_MOUNT_NODISCARD = (1UL << 29), BTRFS_MOUNT_NOSPACECACHE = (1UL << 30), + BTRFS_MOUNT_TEST_DUMMY_ENCRYPTION = (1UL << 31), }; /* @@ -828,6 +830,7 @@ struct btrfs_fs_info { spinlock_t eb_leak_lock; struct list_head allocated_ebs; #endif + struct fscrypt_dummy_policy dummy_enc_policy; }; static inline u64 btrfs_get_fs_generation(const struct btrfs_fs_info *fs_info) diff --git a/fs/btrfs/fscrypt.c b/fs/btrfs/fscrypt.c index 85b596711371..2fbceec62dc7 100644 --- a/fs/btrfs/fscrypt.c +++ b/fs/btrfs/fscrypt.c @@ -242,6 +242,11 @@ static blk_status_t btrfs_process_encrypted_bio(struct bio *orig_bio, return btrfs_csum_one_bio(bbio, enc_bio); } +static const union fscrypt_policy *btrfs_get_dummy_policy(struct super_block *sb) +{ + return btrfs_sb(sb)->dummy_enc_policy.policy; +} + int btrfs_fscrypt_load_extent_info(struct btrfs_inode *inode, struct extent_map *em, struct btrfs_fscrypt_ctx *ctx) @@ -357,4 +362,5 @@ const struct fscrypt_operations btrfs_fscrypt_ops = { .empty_dir = btrfs_fscrypt_empty_dir, .get_devices = btrfs_fscrypt_get_devices, .process_bio = btrfs_process_encrypted_bio, + .get_dummy_policy = btrfs_get_dummy_policy, }; diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 462a23db26af..2a7789519a6c 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -88,6 +88,7 @@ struct btrfs_fs_context { unsigned long compress_type:4; unsigned int compress_level; refcount_t refs; + struct fscrypt_dummy_policy dummy_enc_policy; }; enum { @@ -122,6 +123,7 @@ enum { Opt_thread_pool, Opt_treelog, Opt_user_subvol_rm_allowed, + Opt_test_dummy_encryption, /* Rescue options */ Opt_rescue, @@ -255,6 +257,13 @@ static const struct fs_parameter_spec btrfs_fs_parameters[] = { fsparam_flag_no("enospc_debug", Opt_enospc_debug), #ifdef CONFIG_BTRFS_DEBUG fsparam_enum("fragment", Opt_fragment, btrfs_parameter_fragment), + + /* + * With -o test_dummy_encryption we default to v2, only allow the flag + * version, since we don't support v1. + */ + fsparam_flag("test_dummy_encryption", Opt_test_dummy_encryption), + #endif #ifdef CONFIG_BTRFS_FS_REF_VERIFY fsparam_flag("ref_verify", Opt_ref_verify), @@ -268,6 +277,7 @@ static int btrfs_parse_param(struct fs_context *fc, struct btrfs_fs_context *ctx = fc->fs_private; struct fs_parse_result result; int opt; + int ret; opt = fs_parse(fc, btrfs_fs_parameters, param, &result); if (opt < 0) @@ -598,6 +608,13 @@ static int btrfs_parse_param(struct fs_context *fc, return -EINVAL; } break; + case Opt_test_dummy_encryption: + btrfs_set_opt(ctx->mount_opt, TEST_DUMMY_ENCRYPTION); + ret = fscrypt_parse_test_dummy_encryption(param, + &ctx->dummy_enc_policy); + if (ret) + return ret; + break; #endif #ifdef CONFIG_BTRFS_FS_REF_VERIFY case Opt_ref_verify: @@ -946,6 +963,9 @@ static int btrfs_fill_super(struct super_block *sb, return err; } + if (fscrypt_is_dummy_policy_set(&fs_info->dummy_enc_policy)) + btrfs_set_fs_incompat(fs_info, ENCRYPT); + if (btrfs_fs_incompat(fs_info, ENCRYPT)) { if (IS_ENABLED(CONFIG_FS_ENCRYPTION_INLINE_CRYPT)) { sb->s_flags |= SB_INLINECRYPT; @@ -1112,6 +1132,9 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry) #endif if (btrfs_test_opt(info, REF_VERIFY)) seq_puts(seq, ",ref_verify"); + if (btrfs_test_opt(info, TEST_DUMMY_ENCRYPTION)) + fscrypt_show_test_dummy_encryption(seq, ',', dentry->d_sb); + seq_printf(seq, ",subvolid=%llu", BTRFS_I(d_inode(dentry))->root->root_key.objectid); subvol_name = btrfs_get_subvol_name_from_objectid(info, @@ -1384,6 +1407,18 @@ static void btrfs_ctx_to_info(struct btrfs_fs_info *fs_info, fs_info->mount_opt = ctx->mount_opt; fs_info->compress_type = ctx->compress_type; fs_info->compress_level = ctx->compress_level; + + /* + * If there's nothing set, or if the fs_info already has one set, don't + * do anything. If the fs_info is set we'll free the dummy one when we + * free the ctx. + */ + if (!fscrypt_is_dummy_policy_set(&ctx->dummy_enc_policy) || + fscrypt_is_dummy_policy_set(&fs_info->dummy_enc_policy)) + return; + + fs_info->dummy_enc_policy = ctx->dummy_enc_policy; + memset(&ctx->dummy_enc_policy, 0, sizeof(ctx->dummy_enc_policy)); } static void btrfs_info_to_ctx(struct btrfs_fs_info *fs_info, @@ -1436,6 +1471,7 @@ static void btrfs_emit_options(struct btrfs_fs_info *info, btrfs_info_if_set(info, old, USEBACKUPROOT, "trying to use backup root at mount time"); btrfs_info_if_set(info, old, IGNOREBADROOTS, "ignoring bad roots"); btrfs_info_if_set(info, old, IGNOREDATACSUMS, "ignoring data csums"); + btrfs_info_if_set(info, old, TEST_DUMMY_ENCRYPTION, "test dummy encryption mode enabled"); btrfs_info_if_unset(info, old, NODATACOW, "setting datacow"); btrfs_info_if_unset(info, old, SSD, "not using ssd optimizations"); @@ -1467,6 +1503,23 @@ static void btrfs_emit_options(struct btrfs_fs_info *info, info->max_inline); } +static bool btrfs_check_test_dummy_encryption(struct fs_context *fc) +{ + struct btrfs_fs_context *ctx = fc->fs_private; + struct btrfs_fs_info *fs_info = btrfs_sb(fc->root->d_sb); + + if (!fscrypt_is_dummy_policy_set(&ctx->dummy_enc_policy)) + return true; + + if (fscrypt_dummy_policies_equal(&fs_info->dummy_enc_policy, + &ctx->dummy_enc_policy)) + return true; + + btrfs_warn(fs_info, + "Can't set or change test_dummy_encryption on remount"); + return false; +} + static int btrfs_reconfigure(struct fs_context *fc) { struct super_block *sb = fc->root->d_sb; @@ -1485,6 +1538,10 @@ static int btrfs_reconfigure(struct fs_context *fc) !btrfs_check_options(fs_info, &ctx->mount_opt, fc->sb_flags)) return -EINVAL; + if (!mount_reconfigure && + !btrfs_check_test_dummy_encryption(fc)) + return -EINVAL; + ret = btrfs_check_features(fs_info, !(fc->sb_flags & SB_RDONLY)); if (ret < 0) return ret; @@ -2121,6 +2178,7 @@ static void btrfs_free_fs_context(struct fs_context *fc) btrfs_free_fs_info(fs_info); if (ctx && refcount_dec_and_test(&ctx->refs)) { + fscrypt_free_dummy_policy(&ctx->dummy_enc_policy); kfree(ctx->subvol_name); kfree(ctx); } From patchwork Fri Dec 1 22:11:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476527 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="nXq/jpGg" Received: from mail-yw1-x1129.google.com (mail-yw1-x1129.google.com [IPv6:2607:f8b0:4864:20::1129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A3A010D0 for ; Fri, 1 Dec 2023 14:12:48 -0800 (PST) Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-5cce5075bd6so22789527b3.0 for ; Fri, 01 Dec 2023 14:12:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468767; x=1702073567; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=To9jP0OMafmtyLxtyQVvx+ygcdRboZeNuphRs/ixeY8=; b=nXq/jpGgGjxBm+1QKNolaeO9Y8lufuyJhGNZc76zgik9xFJsEqtn2/AwCp7scRx+x9 m7vFP5WAvInqiDFC1DDwycAq96jw9J6g6fziPN5/mV9H4QDf34syUBgVERQUKPkkLU6z u44jhIKwc/7v6dApofBHVk7bhGV6XioHTewbRmE91KnvUH3/lWR3d2492c6kCXYJ0dtd SNufcoY9xpNXjrg5ck6+kgTmc80IlcN/rZJhvupuuu/nczZ6L5YUFt6HY0MmtuvI/MRU r1zpgtzSWuS7c8Z79os3jQ5iLK63d92g9HgXap4hTCSZprPnl7r71VVs4zUAl4q2BhkB ooLg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468767; x=1702073567; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=To9jP0OMafmtyLxtyQVvx+ygcdRboZeNuphRs/ixeY8=; b=iEMw8M0eE5rCxzsq7ySSYqCFMiKibHJwVX6RpDPbIF0MOx0bjcjn2LotQo7IogySke Te6Gf4efRg6SxC8ei7/rKyU2Qf7oSh/LigVHyh/gQ5g9RvVYMgTnSVb71Ef8g6huiYJ7 cho7ICBpT8ze/TZpdC7zWNrYlV12oCvmyVFoCvjhIetI8KE1WYamgynisiJCG6BDCrKO Cvw1qeMazHzfON+vaSUM6n5H6W9RCsRPe0afBIqR8eb8LDP57LLke6MbChj8s7a3J4Lh 0oz2vy3il/run73MMp8AdB+sz5KAq4wbqTu5cMdRFe4IGdKes7PGXmfUHx+FXqN5H+xD YskQ== X-Gm-Message-State: AOJu0YzXPiqjzqzfMNzjMpyMDOt+GpGzkaTPZ0ZrmrNeDpIAEzcvM7nu SoRcj8kd99JF5n9xLfK7aedVhmKRu+7pdq4dbIqkPw== X-Google-Smtp-Source: AGHT+IEV7qvQUvQ7dVIdOHP6KIEg+8A7r1mAJ4GyXkJqOBWmRFWrg/2XHdgckyDW2CK0/l4ADvT8AA== X-Received: by 2002:a05:690c:3709:b0:5cd:fdfd:dc28 with SMTP id fv9-20020a05690c370900b005cdfdfddc28mr306324ywb.7.1701468767224; Fri, 01 Dec 2023 14:12:47 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id n16-20020a819c50000000b005ccb2d17ba7sm270329ywa.101.2023.12.01.14.12.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:46 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 40/46] btrfs: don't rewrite ret from inode_permission Date: Fri, 1 Dec 2023 17:11:37 -0500 Message-ID: <060bf2d2a9f5eea2675f82ac0a7cc22bba8b4665.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In our user safe ino resolve ioctl we'll just turn any ret into -EACCES from inode_permission. This is redundant, and could potentially be wrong if we had an ENOMEM in the security layer or some such other error, so simply return the actual return value. Signed-off-by: Josef Bacik --- fs/btrfs/ioctl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 48d751011d07..2f4f9f812616 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1977,10 +1977,8 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap, ret = inode_permission(idmap, temp_inode, MAY_READ | MAY_EXEC); iput(temp_inode); - if (ret) { - ret = -EACCES; + if (ret) goto out_put; - } if (key.offset == upper_limit.objectid) break; From patchwork Fri Dec 1 22:11:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476529 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="x2lSjB0T" Received: from mail-yw1-x112a.google.com (mail-yw1-x112a.google.com [IPv6:2607:f8b0:4864:20::112a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1596210DB for ; Fri, 1 Dec 2023 14:12:49 -0800 (PST) Received: by mail-yw1-x112a.google.com with SMTP id 00721157ae682-5cce5075bd6so22789617b3.0 for ; Fri, 01 Dec 2023 14:12:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468768; x=1702073568; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=HNzP1vT2MMiAz4RLg2RxHLY9i1rfgpPqOOdGqsEPy8U=; b=x2lSjB0T3qZ4eCdC+jrA7XI2Eje/EQpnWQtbCJ4wGFMYr9HwNXvSpAIuGXqBS5x+8m G+pvMyW3Ir7HfGZNyeHG22IO8ui9hVeecJdpb73rzqtR2NmTrunimIMConidZMA7itZp 6vUbaed1T7lzTGJppkNcZgjdR2cdP5mFedBo0o8Sr8++yL0cBaTCHOc2kemNJEi/RsCk ulwv2Si/eMptzj6EBf6Jal7I9ut5hFOLZDhA5pHSme0/+vVXhDdkKcs6zb83kwAkyS0j i/CO7MTfSdUTklmgkcmsHLaqx6xAH6NqL7pkIUCr3cKOxqsLd521ooykCx3vbX0jsfmB s5hQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468768; x=1702073568; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HNzP1vT2MMiAz4RLg2RxHLY9i1rfgpPqOOdGqsEPy8U=; b=XK8k6T1WYSXHzkDHOgMcYi93+20RRy0vKsYRfqPYEIq155BWn9R+iYDO4l9dnmBH7V jhEfFSyR/ycO6Iqy7f74MK1f46hdn2g+soKPvLFd8F32HzJgl5RrFf4qzrM1QsuFJlMe zfsNrstVSsya0Mi5gIQq/tv3PuTa2s5luSW3nHfW8VYnXeyVzlkFcmYC56cBdz+iFbon XEYKS6u/T8KoUfInrgBoJlzn0dGy88EbQXraHEDIg6TJ0xIZ/pJ4/OmdE8PrRmiyp4PT QS/cdz17I9K6sSFRTN7LU2ZEhboMqCWhz4Y3LloxU1Vu7iZ68G1dkC5HBy7r7/rnp9lG KP6Q== X-Gm-Message-State: AOJu0Yx64KZogvxh7yqIO9vdMFyvBrFJgz5sJ7Y83rtxNjHAQ6CogUrk bLo3cpTdkKznpqdkdX7y81AGwII71upog5noi5imZw== X-Google-Smtp-Source: AGHT+IFwWPI7hv4vRSmcqpd3J+W/DuiDZgkzRZsnuFD1zb8SSLMs9GuVdwO1oAeXjx9/JJ6xRTYUpg== X-Received: by 2002:a81:a184:0:b0:5d3:b71b:4d30 with SMTP id y126-20020a81a184000000b005d3b71b4d30mr305795ywg.17.1701468768158; Fri, 01 Dec 2023 14:12:48 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id z83-20020a814c56000000b005d3c950160csm1011189ywa.4.2023.12.01.14.12.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:47 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 41/46] btrfs: move inode_to_path higher in backref.c Date: Fri, 1 Dec 2023 17:11:38 -0500 Message-ID: <3ff858fdc4b3b4b3735289999ba652939b2343ab.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We have a prototype and then the definition lower below, we don't need to do this, simply move the function to where the prototype is. Signed-off-by: Josef Bacik --- fs/btrfs/backref.c | 69 ++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index beed7e459dab..f58fe7c745c2 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -2578,8 +2578,40 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info, build_ino_list, ctx); } +/* + * returns 0 if the path could be dumped (probably truncated) + * returns <0 in case of an error + */ static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off, - struct extent_buffer *eb, struct inode_fs_paths *ipath); + struct extent_buffer *eb, struct inode_fs_paths *ipath) +{ + char *fspath; + char *fspath_min; + int i = ipath->fspath->elem_cnt; + const int s_ptr = sizeof(char *); + u32 bytes_left; + + bytes_left = ipath->fspath->bytes_left > s_ptr ? + ipath->fspath->bytes_left - s_ptr : 0; + + fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr; + fspath = btrfs_ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, + name_off, eb, inum, fspath_min, bytes_left); + if (IS_ERR(fspath)) + return PTR_ERR(fspath); + + if (fspath > fspath_min) { + ipath->fspath->val[i] = (u64)(unsigned long)fspath; + ++ipath->fspath->elem_cnt; + ipath->fspath->bytes_left = fspath - fspath_min; + } else { + ++ipath->fspath->elem_missed; + ipath->fspath->bytes_missing += fspath_min - fspath; + ipath->fspath->bytes_left = 0; + } + + return 0; +} static int iterate_inode_refs(u64 inum, struct inode_fs_paths *ipath) { @@ -2704,41 +2736,6 @@ static int iterate_inode_extrefs(u64 inum, struct inode_fs_paths *ipath) return ret; } -/* - * returns 0 if the path could be dumped (probably truncated) - * returns <0 in case of an error - */ -static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off, - struct extent_buffer *eb, struct inode_fs_paths *ipath) -{ - char *fspath; - char *fspath_min; - int i = ipath->fspath->elem_cnt; - const int s_ptr = sizeof(char *); - u32 bytes_left; - - bytes_left = ipath->fspath->bytes_left > s_ptr ? - ipath->fspath->bytes_left - s_ptr : 0; - - fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr; - fspath = btrfs_ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, - name_off, eb, inum, fspath_min, bytes_left); - if (IS_ERR(fspath)) - return PTR_ERR(fspath); - - if (fspath > fspath_min) { - ipath->fspath->val[i] = (u64)(unsigned long)fspath; - ++ipath->fspath->elem_cnt; - ipath->fspath->bytes_left = fspath - fspath_min; - } else { - ++ipath->fspath->elem_missed; - ipath->fspath->bytes_missing += fspath_min - fspath; - ipath->fspath->bytes_left = 0; - } - - return 0; -} - /* * this dumps all file system paths to the inode into the ipath struct, provided * is has been created large enough. each path is zero-terminated and accessed From patchwork Fri Dec 1 22:11:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476530 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="iUxucSfU" Received: from mail-yb1-xb42.google.com (mail-yb1-xb42.google.com [IPv6:2607:f8b0:4864:20::b42]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6AEFD128 for ; Fri, 1 Dec 2023 14:12:50 -0800 (PST) Received: by mail-yb1-xb42.google.com with SMTP id 3f1490d57ef6-dafe04717baso992534276.1 for ; Fri, 01 Dec 2023 14:12:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468769; x=1702073569; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=WKlRH2ypxEsgnl3Oxcw1hajqFTRK349usgZrBtFH+kI=; b=iUxucSfU9i2hov/990KJHFShpQ+0pUpf8htHjLEPq6m0V+ssSX1r5G3PpT6fvX/IVf cj1+3wDvmVLQwo0SJaFXXjiCgieG9AcuUapYfLbhcWFj1jUgXavSRa63O/TFcatVHdds VSrQSbgAZZyhVffb5zDCOGAj6lTSHw1ai6l9ezEtrlHxfLek2JUB9fGp40ZzgIvOWIt+ wx+RutUcWtCgbygyrJk+tMUApMs01SbP2Iv1b7cn2KL3PJ12xWznxZtVbYdfPvoy7Tzs BOnUbuMcbQQa9+UKJ7x9rGi5TE97blnwEaykZZa6csN2OyPoz1GOf4pJ77fQPiL5uhXo UaCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468769; x=1702073569; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=WKlRH2ypxEsgnl3Oxcw1hajqFTRK349usgZrBtFH+kI=; b=Q7oH5EZaSznxIYWALmKzhzGblfo6KuPMm2SaioIOAdMPdEZ9h38yqkeaLUZJMrB25g uINDcrcDyfS684n/U+Jgz+o7Nh5/oTtfKNvVNydrv3B08TXc5fU4MtrzmS9zu5A2Z/5O nsXUPcIq43TbJmy3yIbSVMJV0PJJ4vxqvJa/hfagNUNDpucQZgRsD7aKnrPG8UQyfNT9 ASChcXlljo/Q36ilH9jS/vn2UVjdOt4eW+Rhhs1/wvYQo4gFwmMg/qW88zkwBmBMYAES xrGGu998DoelAV1KQu8ygf+hle0z6UQs0J02WBxOZdDFV2pEhyuziCwwBG4hM57YuMFM VB1Q== X-Gm-Message-State: AOJu0YzT6/JNAW8AC09WRsidQ1HUDlS8fJBswaqvUSZg20qgg+Ji7t2D E9hO4XBnrue3wM4GRLMEChfD/feVPbUjPTyzZCcdj4j0 X-Google-Smtp-Source: AGHT+IFa78UTB3MkuGoDEKdy6FU/NSfdtRCrhlnDeB+gknUqL92NWjcGklFcXclqxw7I+TphLq8SIw== X-Received: by 2002:a05:6902:1008:b0:db7:dacf:6fd4 with SMTP id w8-20020a056902100800b00db7dacf6fd4mr183217ybt.92.1701468769440; Fri, 01 Dec 2023 14:12:49 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id l14-20020a25ad4e000000b00d9cb47932a0sm635243ybe.25.2023.12.01.14.12.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:48 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 42/46] btrfs: make btrfs_ref_to_path handle encrypted filenames Date: Fri, 1 Dec 2023 17:11:39 -0500 Message-ID: <82bed4f199c177455b1a0bdf6b246a8a6047ed33.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We use this helper for inode-resolve and path resolution in send, so update this helper to properly decrypt any encrypted names it finds. Signed-off-by: Josef Bacik --- fs/btrfs/backref.c | 45 +++++++++++++++++++++++++++++++++++++++++---- fs/btrfs/fscrypt.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/fscrypt.h | 11 +++++++++++ 3 files changed, 98 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index f58fe7c745c2..9ed854b9f3fc 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -20,6 +20,7 @@ #include "extent-tree.h" #include "relocation.h" #include "tree-checker.h" +#include "fscrypt.h" /* Just arbitrary numbers so we can be sure one of these happened. */ #define BACKREF_FOUND_SHARED 6 @@ -2117,6 +2118,42 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, return ret; } +static int copy_resolved_iref_to_buf(struct btrfs_root *fs_root, + struct extent_buffer *eb, + char *dest, u64 parent, + unsigned long name_off, u32 name_len, + s64 *bytes_left) +{ + struct btrfs_fs_info *fs_info = fs_root->fs_info; + struct fscrypt_str fname = FSTR_INIT(NULL, 0); + int ret; + + /* No encryption, just copy the name in. */ + if (!btrfs_fs_incompat(fs_info, ENCRYPT)) { + *bytes_left -= name_len; + if (*bytes_left >= 0) + read_extent_buffer(eb, dest + *bytes_left, + name_off, name_len); + return 0; + } + + ret = fscrypt_fname_alloc_buffer(BTRFS_NAME_LEN, &fname); + if (ret) + return ret; + + ret = btrfs_decrypt_name(fs_root, eb, name_off, name_len, parent, + &fname); + if (ret) + goto out; + + *bytes_left -= fname.len; + if (*bytes_left >= 0) + memcpy(dest + *bytes_left, fname.name, fname.len); +out: + fscrypt_fname_free_buffer(&fname); + return ret; +} + /* * this iterates to turn a name (from iref/extref) into a full filesystem path. * Elements of the path are separated by '/' and the path is guaranteed to be @@ -2148,10 +2185,10 @@ char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, dest[bytes_left] = '\0'; while (1) { - bytes_left -= name_len; - if (bytes_left >= 0) - read_extent_buffer(eb, dest + bytes_left, - name_off, name_len); + ret = copy_resolved_iref_to_buf(fs_root, eb, dest, parent, + name_off, name_len, &bytes_left); + if (ret) + break; if (eb != eb_in) { if (!path->skip_locking) btrfs_tree_read_unlock(eb); diff --git a/fs/btrfs/fscrypt.c b/fs/btrfs/fscrypt.c index 2fbceec62dc7..6211fa17bf79 100644 --- a/fs/btrfs/fscrypt.c +++ b/fs/btrfs/fscrypt.c @@ -355,6 +355,52 @@ int btrfs_fscrypt_bio_length(struct bio *bio, u64 map_length) return map_length; } +int btrfs_decrypt_name(struct btrfs_root *root, struct extent_buffer *eb, + unsigned long name_off, u32 name_len, + u64 parent_ino, struct fscrypt_str *name) +{ + struct btrfs_fs_info *fs_info = root->fs_info; + struct inode *dir; + struct fscrypt_str iname = FSTR_INIT(NULL, 0); + int ret; + + ASSERT(name_len <= BTRFS_NAME_LEN); + + ret = fscrypt_fname_alloc_buffer(name_len, &iname); + if (ret) + return ret; + + dir = btrfs_iget(fs_info->sb, parent_ino, root); + if (IS_ERR(dir)) { + ret = PTR_ERR(dir); + goto out; + } + + /* + * Directory isn't encrypted, the name isn't encrypted, we can just copy + * it into the buffer. + */ + if (!IS_ENCRYPTED(dir)) { + read_extent_buffer(eb, name->name, name_off, name_len); + name->len = name_len; + goto out_inode; + } + + read_extent_buffer(eb, iname.name, name_off, name_len); + + ret = fscrypt_prepare_readdir(dir); + if (ret) + goto out_inode; + + ASSERT(dir->i_crypt_info); + ret = fscrypt_fname_disk_to_usr(dir, 0, 0, &iname, name); +out_inode: + iput(dir); +out: + fscrypt_fname_free_buffer(&iname); + return ret; +} + const struct fscrypt_operations btrfs_fscrypt_ops = { .has_per_extent_encryption = 1, .get_context = btrfs_fscrypt_get_context, diff --git a/fs/btrfs/fscrypt.h b/fs/btrfs/fscrypt.h index c4a327be0eeb..aba01bacc165 100644 --- a/fs/btrfs/fscrypt.h +++ b/fs/btrfs/fscrypt.h @@ -36,6 +36,9 @@ bool btrfs_mergeable_encrypted_bio(struct bio *bio, struct inode *inode, struct fscrypt_extent_info *fi, u64 logical_offset); int btrfs_fscrypt_bio_length(struct bio *bio, u64 map_length); +int btrfs_decrypt_name(struct btrfs_root *root, struct extent_buffer *eb, + unsigned long name_off, u32 name_len, + u64 parent_ino, struct fscrypt_str *name); #else static inline int btrfs_fscrypt_save_extent_info(struct btrfs_inode *inode, @@ -94,6 +97,14 @@ static inline u64 btrfs_fscrypt_bio_length(struct bio *bio, u64 map_length) { return map_length; } + +static inline int btrfs_decrypt_name(struct btrfs_root *root, + struct extent_buffer *eb, + unsigned long name_off, u32 name_len, + u64 parent_ino, struct fscrypt_str *name) +{ + return -EINVAL; +} #endif /* CONFIG_FS_ENCRYPTION */ extern const struct fscrypt_operations btrfs_fscrypt_ops; From patchwork Fri Dec 1 22:11:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476531 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="Ga/edRcc" Received: from mail-yw1-x1130.google.com (mail-yw1-x1130.google.com [IPv6:2607:f8b0:4864:20::1130]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4A7EB10F3 for ; Fri, 1 Dec 2023 14:12:51 -0800 (PST) Received: by mail-yw1-x1130.google.com with SMTP id 00721157ae682-5c08c47c055so29084847b3.1 for ; Fri, 01 Dec 2023 14:12:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468770; x=1702073570; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=k/eg7ajMuqgjQeP8qD+Hv5GpTf3d4PaEZrFPInKscKQ=; b=Ga/edRccOIK6Zu5jOf+kr8irUYnN69sexSQrr29hjTW+Ps0PKxmkW0CeDWHqnxMO+L BnF7qK7n0pDFOxyDTB2e5ioOJzxMYbzZbok20ij1Ru+fDnPFy3ww+MoCK4r09vPg9UJc 5MqmjvExHqI66XI1FkCQklqtqnZ091wWApF0Spn/1gLE29FEz2rcn24r7hCUj7X4Z4+9 LaOtYj8cOgFdFSzMxXsccVWBokyuqxKXwSG5CZaenUDTQSyOJOiJhrE0BlsZ76gOduvO r400/UgncqJKrqHcfXxvzNroo1fmngVOJA1tFQdn29N92KIQC5sBuTHNu8P9Z6X9lior gsLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468770; x=1702073570; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=k/eg7ajMuqgjQeP8qD+Hv5GpTf3d4PaEZrFPInKscKQ=; b=a2RpzuK5zYq6dFldLiNTubyIb3Va7CYpM5wRAtz0v2viFUVoB5eazpGBOB3WMEWO6j 1y3bpPeIptqZIstPoYye/vQDgatTDCVUgOMKonUt+a3+nAe+0Ii4LXn1COhfbBLADVOQ 1fiAVfKBK1c/vNqhQAW/YbnnN2wr2b1Cp8nB4vkZacOQlgQ7WyrymkFz0+Qdt3aZ/WU4 9Y2WlYWLvIysmPyhE0vC2HEv04CdSbCoAOE8wge98duKzM/pt34R1cvtb76wNrT7WbWM FIiiAsfhxnwLw/7lY6Q6jmL1zMJTF799TYtXbBWhQdhX9f8UzxFRORIG+Yx2ZTkX3yZK 6vWQ== X-Gm-Message-State: AOJu0Yy2MEaI7IlFts12+RpCDYAzo2b4SBg+TQ/Ps3ZktZYNKOzv6yep 3ZFq8MJ+2MRP0hlaw65mpe7BmbykAnaPJx+XiiTDNw== X-Google-Smtp-Source: AGHT+IETrSOuPq4vhgw8mrhZqpaEq81Wiak+hseLz8tSf2Q7lwNTWc1puQ6QUytY7XsPGv1WtuqT8Q== X-Received: by 2002:a81:994f:0:b0:5d7:1940:53de with SMTP id q76-20020a81994f000000b005d7194053demr159596ywg.86.1701468770380; Fri, 01 Dec 2023 14:12:50 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id q8-20020a815c08000000b005d0494763c1sm1380242ywb.140.2023.12.01.14.12.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:50 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 43/46] btrfs: don't search back for dir inode item in INO_LOOKUP_USER Date: Fri, 1 Dec 2023 17:11:40 -0500 Message-ID: <9f2b9f7ac00fbd6bdd2150b7cc91d63c528f1c0a.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We don't need to search back to the inode item, the directory inode number is in key.offset, so simply use that. If we can't find the directory we'll get an ENOENT at the iget. Signed-off-by: Josef Bacik --- fs/btrfs/ioctl.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 2f4f9f812616..7634ba23d046 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1890,7 +1890,7 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap, struct btrfs_root_ref *rref; struct btrfs_root *root = NULL; struct btrfs_path *path; - struct btrfs_key key, key2; + struct btrfs_key key; struct extent_buffer *leaf; struct inode *temp_inode; char *ptr; @@ -1944,24 +1944,6 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap, read_extent_buffer(leaf, ptr, (unsigned long)(iref + 1), len); - /* Check the read+exec permission of this directory */ - ret = btrfs_previous_item(root, path, dirid, - BTRFS_INODE_ITEM_KEY); - if (ret < 0) { - goto out_put; - } else if (ret > 0) { - ret = -ENOENT; - goto out_put; - } - - leaf = path->nodes[0]; - slot = path->slots[0]; - btrfs_item_key_to_cpu(leaf, &key2, slot); - if (key2.objectid != dirid) { - ret = -ENOENT; - goto out_put; - } - /* * We don't need the path anymore, so release it and * avoid deadlocks and lockdep warnings in case @@ -1969,11 +1951,12 @@ static int btrfs_search_path_in_tree_user(struct mnt_idmap *idmap, * btree and lock the same leaf. */ btrfs_release_path(path); - temp_inode = btrfs_iget(sb, key2.objectid, root); + temp_inode = btrfs_iget(sb, key.offset, root); if (IS_ERR(temp_inode)) { ret = PTR_ERR(temp_inode); goto out_put; } + /* Check the read+exec permission of this directory */ ret = inode_permission(idmap, temp_inode, MAY_READ | MAY_EXEC); iput(temp_inode); From patchwork Fri Dec 1 22:11:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476532 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="xlYeo6ze" Received: from mail-yw1-x1135.google.com (mail-yw1-x1135.google.com [IPv6:2607:f8b0:4864:20::1135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 410ED10D0 for ; Fri, 1 Dec 2023 14:12:52 -0800 (PST) Received: by mail-yw1-x1135.google.com with SMTP id 00721157ae682-5d3c7ef7b31so18905307b3.3 for ; Fri, 01 Dec 2023 14:12:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468771; x=1702073571; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=G65+p44mGmrcw3g1ylziU5NRee9dMbEGAa4uRdfp8o0=; b=xlYeo6zeg6wvHGuyfMi6+kUoUr36OpIiUzbo6jF4dRRUb612Z0GBkiFqCtsLQ9EsLU iSlkXZw9+AkieZ4VIcLIemcf+VIQJWo1plVAJ/U5zQJ4SYliLFe+FGqgGmq6W2O/2onf KUdMXBTls6kgKsixpPIuGSSF5TwuiksnlyL9tfRIcyh+5AXEho1wwW6cEyoHKT48LeKj kwpdx7fqLnKRA6txVhxcHNYNa2iRNMEgF8awX/ZkXsfg0E42EExcaAUwkMZKqoMM9hFm oUlgFpOqsIsdZxl9nrZw4ffAnjNMp6blLZu+kX/Ud2yoo3A4jk5OnasBiAgLet8W66ER //tA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468771; x=1702073571; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=G65+p44mGmrcw3g1ylziU5NRee9dMbEGAa4uRdfp8o0=; b=c4gLuvqEE4UVNAfNAlivCnbqhY6GxwpkWDjuCMnRC71RyPdichcFv6KHHWDpKo5+mA lr5Q0ypNF0d6rYzCcqsLQZeTZ1dABpnX4CnTafNSBO1irxpxKsFntZMCF9UBz4C4/JDY 99e5pW3HKLTX0dRlZ+XzHPvSoeMzjT/v291t2ydXiRsyxxwxrUxD09/Gjl96Hg0fItK/ xKtb2bNN6iJaIk5oaxuPlLFDdt2ulxHcMCAKwTTraQNhm+hI5VCB2bXJWMXDcUxvCmSn z8LqfLtOoa76Rp0ADarb6UbsDb9n/BUpE7Z75sdU4eJWWJ/4UaAuaVgJc4IpBPNkOowE cruQ== X-Gm-Message-State: AOJu0Yyc0iTSWmzu5L5KMMxM+a0Raq1SWOkbuyoS8EWZKYAMblg1F0LA yD9Xqps8wE20aNPQlswjlqC99CbCIW6pztGSIVJQRQ== X-Google-Smtp-Source: AGHT+IGMXu8ydshCa8rJ4v/ERWlHQ7MaV6TkNFrUdf8axRijnNw6x9bzA6o3POz87QqdoN+lC3Ssrw== X-Received: by 2002:a05:690c:3381:b0:5d7:1941:356d with SMTP id fl1-20020a05690c338100b005d71941356dmr196783ywb.84.1701468771338; Fri, 01 Dec 2023 14:12:51 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id r20-20020a0de814000000b005d39c874019sm1143201ywe.66.2023.12.01.14.12.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:51 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 44/46] btrfs: deal with encrypted symlinks in send Date: Fri, 1 Dec 2023 17:11:41 -0500 Message-ID: <4ef9ff7d8238e0ed0995ae4ed65e8de276ebcbd3.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Send needs to send the decrypted value of the symlinks, handle the case where the inode is encrypted and decrypt the symlink name into a buffer and copy this buffer into our fs_path struct. Signed-off-by: Josef Bacik --- fs/btrfs/send.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 3b929f0e8f04..ee5ea16423bb 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -1732,9 +1732,8 @@ static int find_extent_clone(struct send_ctx *sctx, return ret; } -static int read_symlink(struct btrfs_root *root, - u64 ino, - struct fs_path *dest) +static int read_symlink_unencrypted(struct btrfs_root *root, u64 ino, + struct fs_path *dest) { int ret; struct btrfs_path *path; @@ -1800,6 +1799,48 @@ static int read_symlink(struct btrfs_root *root, return ret; } +static int read_symlink_encrypted(struct btrfs_root *root, u64 ino, + struct fs_path *dest) +{ + DEFINE_DELAYED_CALL(done); + const char *buf; + struct page *page; + struct inode *inode; + int ret = 0; + + inode = btrfs_iget(root->fs_info->sb, ino, root); + if (IS_ERR(inode)) + return PTR_ERR(inode); + + page = read_mapping_page(inode->i_mapping, 0, NULL); + if (IS_ERR(page)) { + ret = PTR_ERR(page); + goto out; + } + + buf = fscrypt_get_symlink(inode, page_address(page), + BTRFS_MAX_INLINE_DATA_SIZE(root->fs_info), + &done); + if (IS_ERR(buf)) + goto out_page; + ret = fs_path_add(dest, buf, strlen(buf)); +out_page: + put_page(page); + do_delayed_call(&done); +out: + iput(inode); + return ret; +} + + +static int read_symlink(struct btrfs_root *root, u64 ino, + struct fs_path *dest) +{ + if (btrfs_fs_incompat(root->fs_info, ENCRYPT)) + return read_symlink_encrypted(root, ino, dest); + return read_symlink_unencrypted(root, ino, dest); +} + /* * Helper function to generate a file name that is unique in the root of * send_root and parent_root. This is used to generate names for orphan inodes. From patchwork Fri Dec 1 22:11:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476534 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="KN8r0N3Z" Received: from mail-yw1-x1142.google.com (mail-yw1-x1142.google.com [IPv6:2607:f8b0:4864:20::1142]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5FA7B10EA for ; Fri, 1 Dec 2023 14:12:53 -0800 (PST) Received: by mail-yw1-x1142.google.com with SMTP id 00721157ae682-5cbcfdeaff3so30098747b3.0 for ; Fri, 01 Dec 2023 14:12:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468772; x=1702073572; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=UnBFsSJF3IsR7DnmwzCPuaucSteetnKny36hQz4x9Tc=; b=KN8r0N3ZyGwFepUQuSKlKaHl9V5mCT2yLnm636K/gn2OtfyIpO5rbJOQ81KKm1d7Lt NWgoz192ZtLxPWxeVpZPBBehKGLFXaOxTWEjHMEg3aPWVMJaEgVTqLNxa2p1lHuO6P0W ocy6c7zGUuHlOjfwmPpnHfK9eJYvPQgFjETf1hPps7KpDOzIfNH1oe7U9nmJxIX9Pztg x2gzGFfgpIFYQgSVUXnzFf96NiuyAOxc8Oxz9cbaPget362mXF2yXrHAWTvLVOZWHsHk ttwErjhMAbPkmIcA2dzutT4xBBs5ol7fzGojNzTe6NdrVaPNZAgdaHmds3MgNc9Hh5AD ZThw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468772; x=1702073572; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=UnBFsSJF3IsR7DnmwzCPuaucSteetnKny36hQz4x9Tc=; b=URunszhU2vAXQ3RydrTwSToJfqas29/O63hz9oszfmf0YT3rKbBr1WpZAk+XgnK0U0 XBj+CRUjDvdvPpsFsxTxPwSXPNfKpJFtTBlMCaxtFDldQAGmydntAGJnA4j2CRsOV4I9 /lYmhlBDhSdRcFCweYEw5Q4ARj1dQwrnMOmN/jdS/oit4pGayC0ELTWTPWg+5du/+xi2 31Vehfthj5KZHbhnVxi5ZvUZnxt4nX3kL9ywHaAzQHRmJtTLiYOPXRrD6WGYqeELJF6j ikyZAY18pQ9ZJRmHb1TUtfYslRGgxIwdvwcAPwGeVe2+TWT5WY2NjBr6hWylJ3l9fIM7 UKig== X-Gm-Message-State: AOJu0YzbTM5TsxJEaWnKR37IKxN1JzZZ4nv5rBuBti9QMv2Zh+aG9D0E atXs48Q/o334kyeQ6fpgO892sugYCjWKh9waX7IvSXC1 X-Google-Smtp-Source: AGHT+IFHE/NvnM2BVqABU7Hu3PtQOXzgb9ekQXJwRFI8JzofsueQL+LkwFcUZdc+HgFvkpWH16Xy2g== X-Received: by 2002:a05:690c:711:b0:5d4:3013:25d2 with SMTP id bs17-20020a05690c071100b005d4301325d2mr324407ywb.12.1701468772305; Fri, 01 Dec 2023 14:12:52 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id i190-20020a0dc6c7000000b005d25be5c7f4sm1385122ywd.73.2023.12.01.14.12.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:52 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 45/46] btrfs: decrypt file names for send Date: Fri, 1 Dec 2023 17:11:42 -0500 Message-ID: X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In send we're going to be looking up file names from back references and putting them into the send stream. If we are encrypted use the helper for decrypting names and copy the decrypted name into the buffer. Signed-off-by: Josef Bacik --- fs/btrfs/send.c | 51 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index ee5ea16423bb..de77321777f4 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -33,6 +33,7 @@ #include "ioctl.h" #include "verity.h" #include "lru_cache.h" +#include "fscrypt.h" /* * Maximum number of references an extent can have in order for us to attempt to @@ -585,13 +586,42 @@ static int fs_path_add_path(struct fs_path *p, struct fs_path *p2) return ret; } -static int fs_path_add_from_extent_buffer(struct fs_path *p, +static int fs_path_add_from_encrypted(struct btrfs_root *root, + struct fs_path *p, + struct extent_buffer *eb, + unsigned long off, int len, + u64 parent_ino) +{ + struct fscrypt_str fname = FSTR_INIT(NULL, 0); + int ret; + + ret = fscrypt_fname_alloc_buffer(BTRFS_NAME_LEN, &fname); + if (ret) + return ret; + + ret = btrfs_decrypt_name(root, eb, off, len, parent_ino, &fname); + if (ret) + goto out; + + ret = fs_path_add(p, fname.name, fname.len); +out: + fscrypt_fname_free_buffer(&fname); + return ret; +} + +static int fs_path_add_from_extent_buffer(struct btrfs_root *root, + struct fs_path *p, struct extent_buffer *eb, - unsigned long off, int len) + unsigned long off, int len, + u64 parent_ino) { int ret; char *prepared; + if (root && btrfs_fs_incompat(root->fs_info, ENCRYPT)) + return fs_path_add_from_encrypted(root, p, eb, off, len, + parent_ino); + ret = fs_path_prepare_for_add(p, len, &prepared); if (ret < 0) goto out; @@ -1074,8 +1104,8 @@ static int iterate_inode_ref(struct btrfs_root *root, struct btrfs_path *path, } p->start = start; } else { - ret = fs_path_add_from_extent_buffer(p, eb, name_off, - name_len); + ret = fs_path_add_from_extent_buffer(root, p, eb, name_off, + name_len, dir); if (ret < 0) goto out; } @@ -1792,7 +1822,7 @@ static int read_symlink_unencrypted(struct btrfs_root *root, u64 ino, off = btrfs_file_extent_inline_start(ei); len = btrfs_file_extent_ram_bytes(path->nodes[0], ei); - ret = fs_path_add_from_extent_buffer(dest, path->nodes[0], off, len); + ret = fs_path_add_from_extent_buffer(NULL, dest, path->nodes[0], off, len, 0); out: btrfs_free_path(path); @@ -2090,18 +2120,19 @@ static int get_first_ref(struct btrfs_root *root, u64 ino, iref = btrfs_item_ptr(path->nodes[0], path->slots[0], struct btrfs_inode_ref); len = btrfs_inode_ref_name_len(path->nodes[0], iref); - ret = fs_path_add_from_extent_buffer(name, path->nodes[0], - (unsigned long)(iref + 1), - len); parent_dir = found_key.offset; + ret = fs_path_add_from_extent_buffer(root, name, path->nodes[0], + (unsigned long)(iref + 1), + len, parent_dir); } else { struct btrfs_inode_extref *extref; extref = btrfs_item_ptr(path->nodes[0], path->slots[0], struct btrfs_inode_extref); len = btrfs_inode_extref_name_len(path->nodes[0], extref); - ret = fs_path_add_from_extent_buffer(name, path->nodes[0], - (unsigned long)&extref->name, len); parent_dir = btrfs_inode_extref_parent(path->nodes[0], extref); + ret = fs_path_add_from_extent_buffer(root, name, path->nodes[0], + (unsigned long)&extref->name, len, + parent_dir); } if (ret < 0) goto out; From patchwork Fri Dec 1 22:11:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13476533 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=toxicpanda-com.20230601.gappssmtp.com header.i=@toxicpanda-com.20230601.gappssmtp.com header.b="eXSmI8Ob" Received: from mail-yw1-x1133.google.com (mail-yw1-x1133.google.com [IPv6:2607:f8b0:4864:20::1133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5AF38128 for ; Fri, 1 Dec 2023 14:12:54 -0800 (PST) Received: by mail-yw1-x1133.google.com with SMTP id 00721157ae682-5d4f71f7e9fso10521277b3.0 for ; Fri, 01 Dec 2023 14:12:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20230601.gappssmtp.com; s=20230601; t=1701468773; x=1702073573; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=AJQANW9MIFcPX8D7eKOvMwDwipmxgT+JsIthXMaRo9o=; b=eXSmI8ObEOYIHci6CSQDiLPxnG7aJ+lotlVP2RinbrS+D7UbGHrmHbrtAB8YtkVXue 5mLeELpN/VMc8O7KcwFkJ4S3w5+mHPw8Wm7LwVuoibO6+MAJb4z0Refyefnfh4OfRT55 JBZJoQse21kAnplCSIPG6CHvMyQpPMS56hqOKGuhN9Pn5A3Tnjvji3Ddvqx6nUd8LTZL po4wotH/iqXyDr8BKzkHAp9sXN0NPagDLRvxQnKoJPEnklvek98e8ilXEV/n15rLqgSg 5FVL3ITwmR8AjrqrBcCadOMgA2ruAH18y5AyiuwLfZcyhKJhY+68lsgV6WClel5fV0U4 qNfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701468773; x=1702073573; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=AJQANW9MIFcPX8D7eKOvMwDwipmxgT+JsIthXMaRo9o=; b=tYKO/2s3hujZcelK5Su+/SG3bXoLPuozvfHGvkHuAytY3N1Z9OHYYJ/XuFfkJ80zGY 0MezIic0EsBQvDtyplEogmDP2CWroARqkKjTcLViyFwtI/KLgY/saMbCll2t4c9ark9U 6b9PM5U2qNiF1l3Ep9SdoW4e5+lP4NO/aicVLgpJeEOxriNGApfCmSy9kB1FnaqZA5tl wYppl39t6/h7pCoRZhqCvH7Zx7j3AOQj36DaGQFA8yx62x1iFZmRN0N7uxP+/31uj5eB rG7uy46sTJtlyzBf2hspTpVXOWsQWocXfwY3I+89CLDiFXESdseAinxtwp8zax+OPDaP gUdA== X-Gm-Message-State: AOJu0Yw2JjnUtMsDoL67knfe0EWAmODnuLMVUjNJe8XBW+RWU+aRF1k4 bfdikIMKCW1bY0kUdMhG8Lievu0rGPxZrZs2sI37ag== X-Google-Smtp-Source: AGHT+IF9G1WFmCesqs2EQp0J9KXdyomJKnzntzpVggcdssX2aaGBN29uWVBdrRVM3IVVaBt+6+rkjw== X-Received: by 2002:a05:690c:d8f:b0:5ce:aad2:3d6a with SMTP id da15-20020a05690c0d8f00b005ceaad23d6amr267494ywb.14.1701468773395; Fri, 01 Dec 2023 14:12:53 -0800 (PST) Received: from localhost (076-182-020-124.res.spectrum.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id o188-20020a8173c5000000b005d647048e54sm504048ywc.111.2023.12.01.14.12.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 Dec 2023 14:12:53 -0800 (PST) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com, linux-fsdevel@vger.kernel.org Subject: [PATCH v4 46/46] btrfs: load the inode context before sending writes Date: Fri, 1 Dec 2023 17:11:43 -0500 Message-ID: <99694dd7249ea1edefcf13b9842447e530fc3f6f.1701468306.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 For send we will read the pages and copy them into our buffer. Use the fscrypt_inode_open helper to make sure the key is loaded properly before trying to read from the inode so the contents are properly decrypted. Signed-off-by: Josef Bacik --- fs/btrfs/send.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index de77321777f4..3475b4cea09d 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -5392,6 +5392,37 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len) return ret; } +static int load_fscrypt_context(struct send_ctx *sctx) +{ + struct btrfs_root *root = sctx->send_root; + struct name_cache_entry *nce; + struct inode *dir; + int ret; + + if (!IS_ENCRYPTED(sctx->cur_inode)) + return 0; + + /* + * We're encrypted, we need to load the parent inode in order to make + * sure the encryption context is loaded, we use this after calling + * get_cur_path() so our nce for the current inode should be here. If + * not handle it, but ASSERT() for developers. + */ + nce = name_cache_search(sctx, sctx->cur_ino, sctx->cur_inode_gen); + if (!nce) { + ASSERT(nce); + return -EINVAL; + } + + dir = btrfs_iget(root->fs_info->sb, nce->parent_ino, root); + if (IS_ERR(dir)) + return PTR_ERR(dir); + + ret = fscrypt_inode_open(dir, sctx->cur_inode); + iput(dir); + return ret; +} + /* * Read some bytes from the current inode/file and send a write command to * user space. @@ -5415,7 +5446,9 @@ static int send_write(struct send_ctx *sctx, u64 offset, u32 len) ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p); if (ret < 0) goto out; - + ret = load_fscrypt_context(sctx); + if (ret < 0) + goto out; TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p); TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); ret = put_file_data(sctx, offset, len);