From 2c3afbb5c7a23886aa960dfab7a8d87235620e49 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Wed, 21 Oct 2026 22:44:31 +0000 Subject: [PATCH 1/4] fscrypt: Explicitly zeroize sw_secret in error path Explicitly zeroize the sw_secret array in the case where fscrypt_derive_sw_secret() fails, in case anything was written to it. Doesn't really matter, but this came up in a code review. Link: https://patch.msgid.link/20261021224431.2353673-1-ebiggers@kernel.org Signed-off-by: Eric Biggers --- fs/crypto/keyring.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index 874cc183ee62..09364fddcb7a 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -561,8 +561,10 @@ static int add_master_key(struct super_block *sb, if (secret->is_hw_wrapped) { err = fscrypt_derive_sw_secret(sb, secret->bytes, secret->size, sw_secret); - if (err) + if (err) { + memzero_explicit(sw_secret, sizeof(sw_secret)); return err; + } kdf_key = sw_secret; kdf_key_size = sizeof(sw_secret); /* From cf66375465b9ca531f5c294f468db1df293c178c Mon Sep 17 00:00:00 2001 From: Baokun Li Date: Sat, 24 Oct 2026 18:43:50 +0800 Subject: [PATCH 2/4] fscrypt: Fix missing barrier in fscrypt_find_mode_key() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fscrypt_find_mode_key() walks an RCU list and hands out a per-mode key without an acquire: setup task ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ setup_per_mode_enc_key() ├─ fscrypt_prepare_key() │ └─ fscrypt_prepare_inline_crypt_key() │ └─ blk_crypto_start_using_key() │ └─ blk_crypto_fallback_start_using_mode() │ ├─ init profile, keyslots, tfms[] │ └─ smp_store_release(tfms_inited[mode]) # init order └─ list_add_tail_rcu(&new_node->link, ...) # release -> finder finding task (later submits the I/O itself) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ fscrypt_find_mode_key() ├─ list_for_each_entry_rcu(node, ...) └─ return &node->key # no acquire, chain breaks ... blk_crypto_fallback_bio_prep() # WRITE path ├─ tfms_inited[mode] # addr-dep, reads true ├─ blk_crypto_fallback_profile # no dependency ├─ blk_crypto_keyslots # no dependency └─ slotp->tfms[mode] # no dependency RCU publishes the node and the key reachable from it, so tfms_inited[mode] reads true through the address dependency. The independent fallback globals are not covered by it and can be read as uninitialized. On a weakly ordered machine, a WRITE bio can crash in blk_crypto_get_keyslot() or crypto_sync_skcipher_setkey(). Other tasks reach the key through fscrypt_inode_info's cmpxchg_release()/smp_load_acquire(), which is already ordered after the list walk; only the finding task's own later I/O was not. Fix this by upgrading the control dependency to an acquire with smp_acquire__after_ctrl_dep() once a matching entry has been found. Fixes: dd015b566d50 ("fscrypt: Fix key setup in edge case with multiple data unit sizes") Cc: stable@vger.kernel.org Suggested-by: Eric Biggers Link: https://lore.kernel.org/r/20261014161153.GC322435@quark Signed-off-by: Baokun Li Link: https://patch.msgid.link/20261024104350.2257313-1-libaokun@linux.alibaba.com Signed-off-by: Eric Biggers --- fs/crypto/keysetup.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index 892044ebcaca..a77b889d7578 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -205,8 +205,14 @@ fscrypt_find_mode_key(struct fscrypt_master_key *mk, u8 hkdf_context, if (node->hkdf_context == hkdf_context && node->mode_num == mode_num && node->data_unit_bits == ci->ci_data_unit_bits && - fscrypt_is_key_prepared(&node->key, ci)) + fscrypt_is_key_prepared(&node->key, ci)) { + /* + * Upgrade the RCU dereference to a full ACQUIRE, so + * that blk-crypto global state is seen as initialized. + */ + smp_acquire__after_ctrl_dep(); return &node->key; + } } return NULL; } From 0e341d1d29db11c29211d2b8870a515c26589d5a Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Fri, 25 Sep 2026 16:19:18 +0200 Subject: [PATCH 3/4] ext4: refuse encryption when block size > page size Encryption is not supported when a filesystem's block size is larger than the page size, and commit 709f0f1f1bf5 ("ext4: add checks for large folio incompatibilities when BS > PS") added a check to refuse mounting such a filesystem. However, it is also possible to enable the "encrypt" feature on a filesystem that is already mounted (with tune2fs -O encrypt). Once that happens it won't be possible to mount the filesystem again in the future, but there is nothing preventing the user from setting an encryption policy while the filesystem is still mounted. Fix this by refusing to set an fscrypt context in ext4_set_context() when the block size is larger than the page size. Fixes: 709f0f1f1bf5 ("ext4: add checks for large folio incompatibilities when BS > PS") Cc: stable@vger.kernel.org # v6.19+ Signed-off-by: Alberto Garcia Reviewed-by: Baokun Li Reviewed-by: Eric Biggers Link: https://patch.msgid.link/093b40e9df29fc102907092f4ff73461f4cfcbfd.1790343958.git.berto@igalia.com Signed-off-by: Eric Biggers --- fs/ext4/crypto.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c index 1a0fccb084ef..318b2eaea741 100644 --- a/fs/ext4/crypto.c +++ b/fs/ext4/crypto.c @@ -156,6 +156,15 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len, if (ext4_test_inode_flag(inode, EXT4_INODE_DAX)) return -EOPNOTSUPP; + /* + * Encryption is not supported when the block size is larger + * than the page size. This is rejected at mount time by + * ext4_check_large_folio(), and this check here is for the case + * when the 'encrypt' feature is enabled on a mounted filesystem. + */ + if (inode->i_sb->s_blocksize > PAGE_SIZE) + return -EOPNOTSUPP; + res = ext4_convert_inline_data(inode); if (res) return res; From a5e894bc87b76fd980075892ba77e6bdeeb5e4d0 Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Fri, 25 Sep 2026 16:19:19 +0200 Subject: [PATCH 4/4] ext4: reject encrypted inodes when block size > page size Encryption is not supported when a filesystem's block size is larger than the page size. ext4_check_large_folio() refuses to mount a filesystem like that if the "encrypt" feature is already enabled, and ext4_set_context() refuses to create encrypted inodes if the feature is enabled after mounting. However, a corrupted or hand-crafted filesystem can still have encrypted inodes even if the "encrypt" feature is not set, and those inodes can be unlocked if they're using v1 policies. Check this in __ext4_iget() and reject them as corrupted. Fixes: 709f0f1f1bf5 ("ext4: add checks for large folio incompatibilities when BS > PS") Suggested-by: Eric Biggers Cc: stable@vger.kernel.org # v6.19+ Signed-off-by: Alberto Garcia Reviewed-by: Baokun Li Reviewed-by: Eric Biggers Link: https://patch.msgid.link/aeb8efa8beb72721fb4b13cffe6eb22c795ec33f.1790343958.git.berto@igalia.com Signed-off-by: Eric Biggers --- fs/ext4/inode.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 9a9ec02dce9f..46138245d773 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5671,6 +5671,12 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, ret = -EFSCORRUPTED; goto bad_inode; } + if (IS_ENCRYPTED(inode) && sb->s_blocksize > PAGE_SIZE) { + ext4_error_inode(inode, function, line, 0, + "encrypted inode with block size larger than page size"); + ret = -EFSCORRUPTED; + goto bad_inode; + } ext4_set_inode_mapping_order(inode);