diff --git a/patches.kernel.org/6.3.3-232-ext4-improve-error-handling-from-ext4_dirhash.patch b/patches.kernel.org/6.3.3-232-ext4-improve-error-handling-from-ext4_dirhash.patch new file mode 100644 index 0000000..f7dd9ab --- /dev/null +++ b/patches.kernel.org/6.3.3-232-ext4-improve-error-handling-from-ext4_dirhash.patch @@ -0,0 +1,164 @@ +From: Theodore Ts'o +Date: Sat, 6 May 2023 11:59:13 -0400 +Subject: [PATCH] ext4: improve error handling from ext4_dirhash() +References: bsc#1012628 +Patch-mainline: 6.3.3 +Git-commit: 4b3cb1d108bfc2aebb0d7c8a52261a53cf7f5786 + +commit 4b3cb1d108bfc2aebb0d7c8a52261a53cf7f5786 upstream. + +The ext4_dirhash() will *almost* never fail, especially when the hash +tree feature was first introduced. However, with the addition of +support of encrypted, casefolded file names, that function can most +certainly fail today. + +So make sure the callers of ext4_dirhash() properly check for +failures, and reflect the errors back up to their callers. + +Cc: stable@kernel.org +Link: https://lore.kernel.org/r/20230506142419.984260-1-tytso@mit.edu +Reported-by: syzbot+394aa8a792cb99dbc837@syzkaller.appspotmail.com +Reported-by: syzbot+344aaa8697ebd232bfc8@syzkaller.appspotmail.com +Link: https://syzkaller.appspot.com/bug?id=db56459ea4ac4a676ae4b4678f633e55da005a9b +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Jiri Slaby +--- + fs/ext4/hash.c | 6 +++++- + fs/ext4/namei.c | 53 ++++++++++++++++++++++++++++++++++--------------- + 2 files changed, 42 insertions(+), 17 deletions(-) + +diff --git a/fs/ext4/hash.c b/fs/ext4/hash.c +index 147b5241..46c3423d 100644 +--- a/fs/ext4/hash.c ++++ b/fs/ext4/hash.c +@@ -277,7 +277,11 @@ static int __ext4fs_dirhash(const struct inode *dir, const char *name, int len, + } + default: + hinfo->hash = 0; +- return -1; ++ hinfo->minor_hash = 0; ++ ext4_warning(dir->i_sb, ++ "invalid/unsupported hash tree version %u", ++ hinfo->hash_version); ++ return -EINVAL; + } + hash = hash & ~1; + if (hash == (EXT4_HTREE_EOF_32BIT << 1)) +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index a5010b5b..45b57980 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -674,7 +674,7 @@ static struct stats dx_show_leaf(struct inode *dir, + len = de->name_len; + if (!IS_ENCRYPTED(dir)) { + /* Directory is not encrypted */ +- ext4fs_dirhash(dir, de->name, ++ (void) ext4fs_dirhash(dir, de->name, + de->name_len, &h); + printk("%*.s:(U)%x.%u ", len, + name, h.hash, +@@ -709,8 +709,9 @@ static struct stats dx_show_leaf(struct inode *dir, + if (IS_CASEFOLDED(dir)) + h.hash = EXT4_DIRENT_HASH(de); + else +- ext4fs_dirhash(dir, de->name, +- de->name_len, &h); ++ (void) ext4fs_dirhash(dir, ++ de->name, ++ de->name_len, &h); + printk("%*.s:(E)%x.%u ", len, name, + h.hash, (unsigned) ((char *) de + - base)); +@@ -720,7 +721,8 @@ static struct stats dx_show_leaf(struct inode *dir, + #else + int len = de->name_len; + char *name = de->name; +- ext4fs_dirhash(dir, de->name, de->name_len, &h); ++ (void) ext4fs_dirhash(dir, de->name, ++ de->name_len, &h); + printk("%*.s:%x.%u ", len, name, h.hash, + (unsigned) ((char *) de - base)); + #endif +@@ -849,8 +851,14 @@ dx_probe(struct ext4_filename *fname, struct inode *dir, + hinfo->seed = EXT4_SB(dir->i_sb)->s_hash_seed; + /* hash is already computed for encrypted casefolded directory */ + if (fname && fname_name(fname) && +- !(IS_ENCRYPTED(dir) && IS_CASEFOLDED(dir))) +- ext4fs_dirhash(dir, fname_name(fname), fname_len(fname), hinfo); ++ !(IS_ENCRYPTED(dir) && IS_CASEFOLDED(dir))) { ++ int ret = ext4fs_dirhash(dir, fname_name(fname), ++ fname_len(fname), hinfo); ++ if (ret < 0) { ++ ret_err = ERR_PTR(ret); ++ goto fail; ++ } ++ } + hash = hinfo->hash; + + if (root->info.unused_flags & 1) { +@@ -1111,7 +1119,12 @@ static int htree_dirblock_to_tree(struct file *dir_file, + hinfo->minor_hash = 0; + } + } else { +- ext4fs_dirhash(dir, de->name, de->name_len, hinfo); ++ err = ext4fs_dirhash(dir, de->name, ++ de->name_len, hinfo); ++ if (err < 0) { ++ count = err; ++ goto errout; ++ } + } + if ((hinfo->hash < start_hash) || + ((hinfo->hash == start_hash) && +@@ -1313,8 +1326,12 @@ static int dx_make_map(struct inode *dir, struct buffer_head *bh, + if (de->name_len && de->inode) { + if (ext4_hash_in_dirent(dir)) + h.hash = EXT4_DIRENT_HASH(de); +- else +- ext4fs_dirhash(dir, de->name, de->name_len, &h); ++ else { ++ int err = ext4fs_dirhash(dir, de->name, ++ de->name_len, &h); ++ if (err < 0) ++ return err; ++ } + map_tail--; + map_tail->hash = h.hash; + map_tail->offs = ((char *) de - base)>>2; +@@ -1452,10 +1469,9 @@ int ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname, + hinfo->hash_version = DX_HASH_SIPHASH; + hinfo->seed = NULL; + if (cf_name->name) +- ext4fs_dirhash(dir, cf_name->name, cf_name->len, hinfo); ++ return ext4fs_dirhash(dir, cf_name->name, cf_name->len, hinfo); + else +- ext4fs_dirhash(dir, iname->name, iname->len, hinfo); +- return 0; ++ return ext4fs_dirhash(dir, iname->name, iname->len, hinfo); + } + #endif + +@@ -2298,10 +2314,15 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname, + fname->hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; + + /* casefolded encrypted hashes are computed on fname setup */ +- if (!ext4_hash_in_dirent(dir)) +- ext4fs_dirhash(dir, fname_name(fname), +- fname_len(fname), &fname->hinfo); +- ++ if (!ext4_hash_in_dirent(dir)) { ++ int err = ext4fs_dirhash(dir, fname_name(fname), ++ fname_len(fname), &fname->hinfo); ++ if (err < 0) { ++ brelse(bh2); ++ brelse(bh); ++ return err; ++ } ++ } + memset(frames, 0, sizeof(frames)); + frame = frames; + frame->entries = entries; +-- +2.35.3 + diff --git a/series.conf b/series.conf index ccc17e3..bb6c841 100644 --- a/series.conf +++ b/series.conf @@ -965,6 +965,7 @@ patches.kernel.org/6.3.3-229-ext4-avoid-deadlock-in-fs-reclaim-with-page-wri.patch patches.kernel.org/6.3.3-230-ext4-check-iomap-type-only-if-ext4_iomap_begin-.patch patches.kernel.org/6.3.3-231-ext4-improve-error-recovery-code-paths-in-__ext.patch + patches.kernel.org/6.3.3-232-ext4-improve-error-handling-from-ext4_dirhash.patch ######################################################## # Build fixes that apply to the vanilla kernel too.