summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-10-29 14:00:23 -1000
committerLinus Torvalds <torvalds@linux-foundation.org>2026-10-29 14:00:23 -1000
commitd89e1d186ec9271bf78e62771779e9fc03bf0fc3 (patch)
tree0c40997edac11ec31e84c61c0f291df109f7288f
parent0ff8f40110872ecd3a9918e56ddd0ff1b46fb10e (diff)
parenta5e894bc87b76fd980075892ba77e6bdeeb5e4d0 (diff)
downloadlinux-d89e1d186ec9271bf78e62771779e9fc03bf0fc3.tar.gz
linux-d89e1d186ec9271bf78e62771779e9fc03bf0fc3.zip
Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux
Pull fscrypt fixes from Eric Biggers: - Add more checks to prevent encryption on "large block size" ext4 filesystems (s_blocksize > PAGE_SIZE), which isn't supported yet. There was already a mount-time check, but it wasn't enough. - Add missing memory barrier to fscrypt_find_mode_key() - Add missing zeroization in an error path * tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux: ext4: reject encrypted inodes when block size > page size ext4: refuse encryption when block size > page size fscrypt: Fix missing barrier in fscrypt_find_mode_key() fscrypt: Explicitly zeroize sw_secret in error path
-rw-r--r--fs/crypto/keyring.c4
-rw-r--r--fs/crypto/keysetup.c8
-rw-r--r--fs/ext4/crypto.c9
-rw-r--r--fs/ext4/inode.c6
4 files changed, 25 insertions, 2 deletions
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);
/*
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;
}
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;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index b4d581aa5ee1..10cd85d4c721 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -6571,6 +6571,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);