Found by syzbot (https://syzkaller.appspot.com/bug?extid=340581ba9dceb7e06fb3)
log (6.6.61):
EXT4-fs (loop0): encrypted files will use data=ordered instead of data journaling mode EXT4-fs (loop0): 1 truncate cleaned up EXT4-fs (loop0): mounted filesystem 00000000-0000-0000-0000-000000000000 r/w without journal. Quota mode: none. fscrypt: AES-256-CTS-CBC using implementation "cts-cbc-aes-aesni" ------------[ cut here ]------------ WARNING: CPU: 0 PID: 3775 at fs/crypto/fname.c:567 fscrypt_fname_siphash (fs/crypto/fname.c:567) CPU: 0 PID: 3775 Comm: fscrypt_fname_s Not tainted 6.6.61-un-def-alt1.kasan #1 RIP: 0010:fscrypt_fname_siphash (fs/crypto/fname.c:567 (discriminator 1)) Call Trace: <TASK> __ext4fs_dirhash (fs/ext4/hash.c:268) ext4fs_dirhash (fs/ext4/hash.c:322) htree_dirblock_to_tree (fs/ext4/namei.c:1127) ext4_htree_fill_tree (fs/ext4/namei.c:1222) ext4_readdir (fs/ext4/dir.c:608 fs/ext4/dir.c:142) iterate_dir (fs/readdir.c:106) __x64_sys_getdents64 (fs/readdir.c:406 fs/readdir.c:390 fs/readdir.c:390) do_syscall_64 (arch/x86/entry/common.c:51 arch/x86/entry/common.c:81) ... </TASK>
These patches address a warning encountered when mounting ext4 filesystems with the default hash version set to SIPHASH while the casefold feature is not enabled. The warning occurs due to incorrect error handling and setup of the default hash version.
[PATCH 1/2] ext4: filesystems without casefold feature cannot be mounted with siphash Ensures that ext4 filesystems with the default hash set to SIPHASH cannot be mounted if the casefold feature is not enabled.
[PATCH 2/2] ext4: fix error message when rejecting the default hash Corrects the error message logic for rejecting filesystems with the default SIPHASH hash version, ensuring the error message doesn't incorrectly reference the casefold setup. Also moves the check to ext4_hash_info_init to ensure consistency.
From: Lizhi Xu lizhi.xu@windriver.com
[ Upstream commit 985b67cd86392310d9e9326de941c22fc9340eec ]
When mounting the ext4 filesystem, if the default hash version is set to DX_HASH_SIPHASH but the casefold feature is not set, exit the mounting.
Reported-by: syzbot+340581ba9dceb7e06fb3@syzkaller.appspotmail.com Signed-off-by: Lizhi Xu lizhi.xu@windriver.com Link: https://patch.msgid.link/20240605012335.44086-1-lizhi.xu@windriver.com Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Vasiliy Kovalev kovalev@altlinux.org --- fs/ext4/super.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index cf2c8cf507780..68070b1859803 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3559,6 +3559,14 @@ int ext4_feature_set_ok(struct super_block *sb, int readonly) } #endif
+ if (EXT4_SB(sb)->s_es->s_def_hash_version == DX_HASH_SIPHASH && + !ext4_has_feature_casefold(sb)) { + ext4_msg(sb, KERN_ERR, + "Filesystem without casefold feature cannot be " + "mounted with siphash"); + return 0; + } + if (readonly) return 1;
From: Gabriel Krisman Bertazi krisman@suse.de
[ Upstream commit a2187431c395cdfbf144e3536f25468c64fc7cfa ]
Commit 985b67cd8639 ("ext4: filesystems without casefold feature cannot be mounted with siphash") properly rejects volumes where s_def_hash_version is set to DX_HASH_SIPHASH, but the check and the error message should not look into casefold setup - a filesystem should never have DX_HASH_SIPHASH as the default hash. Fix it and, since we are there, move the check to ext4_hash_info_init.
Fixes:985b67cd8639 ("ext4: filesystems without casefold feature cannot be mounted with siphash")
Signed-off-by: Gabriel Krisman Bertazi krisman@suse.de Link: https://patch.msgid.link/87jzg1en6j.fsf_-_@mailhost.krisman.be Signed-off-by: Theodore Ts'o tytso@mit.edu Signed-off-by: Vasiliy Kovalev kovalev@altlinux.org --- fs/ext4/ext4.h | 1 + fs/ext4/super.c | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 72abb8d6caf75..d5706aedf4fef 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2449,6 +2449,7 @@ static inline __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize) #define DX_HASH_HALF_MD4_UNSIGNED 4 #define DX_HASH_TEA_UNSIGNED 5 #define DX_HASH_SIPHASH 6 +#define DX_HASH_LAST DX_HASH_SIPHASH
static inline u32 ext4_chksum(struct ext4_sb_info *sbi, u32 crc, const void *address, unsigned int length) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 68070b1859803..3e4b9bf101454 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3559,14 +3559,6 @@ int ext4_feature_set_ok(struct super_block *sb, int readonly) } #endif
- if (EXT4_SB(sb)->s_es->s_def_hash_version == DX_HASH_SIPHASH && - !ext4_has_feature_casefold(sb)) { - ext4_msg(sb, KERN_ERR, - "Filesystem without casefold feature cannot be " - "mounted with siphash"); - return 0; - } - if (readonly) return 1;
@@ -5050,16 +5042,27 @@ static int ext4_load_super(struct super_block *sb, ext4_fsblk_t *lsb, return ret; }
-static void ext4_hash_info_init(struct super_block *sb) +static int ext4_hash_info_init(struct super_block *sb) { struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_super_block *es = sbi->s_es; unsigned int i;
+ sbi->s_def_hash_version = es->s_def_hash_version; + + if (sbi->s_def_hash_version > DX_HASH_LAST) { + ext4_msg(sb, KERN_ERR, + "Invalid default hash set in the superblock"); + return -EINVAL; + } else if (sbi->s_def_hash_version == DX_HASH_SIPHASH) { + ext4_msg(sb, KERN_ERR, + "SIPHASH is not a valid default hash value"); + return -EINVAL; + } + for (i = 0; i < 4; i++) sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
- sbi->s_def_hash_version = es->s_def_hash_version; if (ext4_has_feature_dir_index(sb)) { i = le32_to_cpu(es->s_flags); if (i & EXT2_FLAGS_UNSIGNED_HASH) @@ -5077,6 +5080,7 @@ static void ext4_hash_info_init(struct super_block *sb) #endif } } + return 0; }
static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) @@ -5234,7 +5238,9 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb)); sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
- ext4_hash_info_init(sb); + err = ext4_hash_info_init(sb); + if (err) + goto failed_mount;
if (ext4_handle_clustersize(sb)) goto failed_mount;
linux-stable-mirror@lists.linaro.org