--- /dev/null
+From a164f3a432aae62ca23d03e6d926b122ee5b860d Mon Sep 17 00:00:00 2001
+From: Baokun Li <libaokun1@huawei.com>
+Date: Thu, 22 Aug 2024 10:35:26 +0800
+Subject: ext4: aovid use-after-free in ext4_ext_insert_extent()
+
+From: Baokun Li <libaokun1@huawei.com>
+
+commit a164f3a432aae62ca23d03e6d926b122ee5b860d upstream.
+
+As Ojaswin mentioned in Link, in ext4_ext_insert_extent(), if the path is
+reallocated in ext4_ext_create_new_leaf(), we'll use the stale path and
+cause UAF. Below is a sample trace with dummy values:
+
+ext4_ext_insert_extent
+ path = *ppath = 2000
+ ext4_ext_create_new_leaf(ppath)
+ ext4_find_extent(ppath)
+ path = *ppath = 2000
+ if (depth > path[0].p_maxdepth)
+ kfree(path = 2000);
+ *ppath = path = NULL;
+ path = kcalloc() = 3000
+ *ppath = 3000;
+ return path;
+ /* here path is still 2000, UAF! */
+ eh = path[depth].p_hdr
+
+==================================================================
+BUG: KASAN: slab-use-after-free in ext4_ext_insert_extent+0x26d4/0x3330
+Read of size 8 at addr ffff8881027bf7d0 by task kworker/u36:1/179
+CPU: 3 UID: 0 PID: 179 Comm: kworker/u6:1 Not tainted 6.11.0-rc2-dirty #866
+Call Trace:
+ <TASK>
+ ext4_ext_insert_extent+0x26d4/0x3330
+ ext4_ext_map_blocks+0xe22/0x2d40
+ ext4_map_blocks+0x71e/0x1700
+ ext4_do_writepages+0x1290/0x2800
+[...]
+
+Allocated by task 179:
+ ext4_find_extent+0x81c/0x1f70
+ ext4_ext_map_blocks+0x146/0x2d40
+ ext4_map_blocks+0x71e/0x1700
+ ext4_do_writepages+0x1290/0x2800
+ ext4_writepages+0x26d/0x4e0
+ do_writepages+0x175/0x700
+[...]
+
+Freed by task 179:
+ kfree+0xcb/0x240
+ ext4_find_extent+0x7c0/0x1f70
+ ext4_ext_insert_extent+0xa26/0x3330
+ ext4_ext_map_blocks+0xe22/0x2d40
+ ext4_map_blocks+0x71e/0x1700
+ ext4_do_writepages+0x1290/0x2800
+ ext4_writepages+0x26d/0x4e0
+ do_writepages+0x175/0x700
+[...]
+==================================================================
+
+So use *ppath to update the path to avoid the above problem.
+
+Reported-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Closes: https://lore.kernel.org/r/ZqyL6rmtwl6N4MWR@li-bb2b2a4c-3307-11b2-a85c-8fa5c3a69313.ibm.com
+Fixes: 10809df84a4d ("ext4: teach ext4_ext_find_extent() to realloc path if necessary")
+Cc: stable@kernel.org
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240822023545.1994557-7-libaokun@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/extents.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -2103,6 +2103,7 @@ prepend:
+ ppath, newext);
+ if (err)
+ goto cleanup;
++ path = *ppath;
+ depth = ext_depth(inode);
+ eh = path[depth].p_hdr;
+
--- /dev/null
+From 70dd7b573afeba9b8f8a33f2ae1e4a9a2ec8c1ec Mon Sep 17 00:00:00 2001
+From: "yao.ly" <yao.ly@linux.alibaba.com>
+Date: Mon, 1 Jul 2024 14:43:39 +0800
+Subject: ext4: correct encrypted dentry name hash when not casefolded
+
+From: yao.ly <yao.ly@linux.alibaba.com>
+
+commit 70dd7b573afeba9b8f8a33f2ae1e4a9a2ec8c1ec upstream.
+
+EXT4_DIRENT_HASH and EXT4_DIRENT_MINOR_HASH will access struct
+ext4_dir_entry_hash followed ext4_dir_entry. But there is no ext4_dir_entry_hash
+followed when inode is encrypted and not casefolded
+
+Signed-off-by: yao.ly <yao.ly@linux.alibaba.com>
+Link: https://patch.msgid.link/1719816219-128287-1-git-send-email-yao.ly@linux.alibaba.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/dir.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/fs/ext4/dir.c
++++ b/fs/ext4/dir.c
+@@ -279,12 +279,20 @@ static int ext4_readdir(struct file *fil
+ struct fscrypt_str de_name =
+ FSTR_INIT(de->name,
+ de->name_len);
++ u32 hash;
++ u32 minor_hash;
++
++ if (IS_CASEFOLDED(inode)) {
++ hash = EXT4_DIRENT_HASH(de);
++ minor_hash = EXT4_DIRENT_MINOR_HASH(de);
++ } else {
++ hash = 0;
++ minor_hash = 0;
++ }
+
+ /* Directory is encrypted */
+ err = fscrypt_fname_disk_to_usr(inode,
+- EXT4_DIRENT_HASH(de),
+- EXT4_DIRENT_MINOR_HASH(de),
+- &de_name, &fstr);
++ hash, minor_hash, &de_name, &fstr);
+ de_name = fstr;
+ fstr.len = save_len;
+ if (err)
--- /dev/null
+From dda898d7ffe85931f9cca6d702a51f33717c501e Mon Sep 17 00:00:00 2001
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+Date: Fri, 9 Aug 2024 20:15:32 +0800
+Subject: ext4: dax: fix overflowing extents beyond inode size when partially writing
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+commit dda898d7ffe85931f9cca6d702a51f33717c501e upstream.
+
+The dax_iomap_rw() does two things in each iteration: map written blocks
+and copy user data to blocks. If the process is killed by user(See signal
+handling in dax_iomap_iter()), the copied data will be returned and added
+on inode size, which means that the length of written extents may exceed
+the inode size, then fsck will fail. An example is given as:
+
+dd if=/dev/urandom of=file bs=4M count=1
+ dax_iomap_rw
+ iomap_iter // round 1
+ ext4_iomap_begin
+ ext4_iomap_alloc // allocate 0~2M extents(written flag)
+ dax_iomap_iter // copy 2M data
+ iomap_iter // round 2
+ iomap_iter_advance
+ iter->pos += iter->processed // iter->pos = 2M
+ ext4_iomap_begin
+ ext4_iomap_alloc // allocate 2~4M extents(written flag)
+ dax_iomap_iter
+ fatal_signal_pending
+ done = iter->pos - iocb->ki_pos // done = 2M
+ ext4_handle_inode_extension
+ ext4_update_inode_size // inode size = 2M
+
+fsck reports: Inode 13, i_size is 2097152, should be 4194304. Fix?
+
+Fix the problem by truncating extents if the written length is smaller
+than expected.
+
+Fixes: 776722e85d3b ("ext4: DAX iomap write support")
+CC: stable@vger.kernel.org
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=219136
+Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Link: https://patch.msgid.link/20240809121532.2105494-1-chengzhihao@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/file.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -324,10 +324,10 @@ static ssize_t ext4_handle_inode_extensi
+ * Clean up the inode after DIO or DAX extending write has completed and the
+ * inode size has been updated using ext4_handle_inode_extension().
+ */
+-static void ext4_inode_extension_cleanup(struct inode *inode, ssize_t count)
++static void ext4_inode_extension_cleanup(struct inode *inode, bool need_trunc)
+ {
+ lockdep_assert_held_write(&inode->i_rwsem);
+- if (count < 0) {
++ if (need_trunc) {
+ ext4_truncate_failed_write(inode);
+ /*
+ * If the truncate operation failed early, then the inode may
+@@ -567,7 +567,7 @@ static ssize_t ext4_dio_write_iter(struc
+ * writeback of delalloc blocks.
+ */
+ WARN_ON_ONCE(ret == -EIOCBQUEUED);
+- ext4_inode_extension_cleanup(inode, ret);
++ ext4_inode_extension_cleanup(inode, ret < 0);
+ }
+
+ out:
+@@ -651,7 +651,7 @@ ext4_dax_write_iter(struct kiocb *iocb,
+
+ if (extend) {
+ ret = ext4_handle_inode_extension(inode, offset, ret);
+- ext4_inode_extension_cleanup(inode, ret);
++ ext4_inode_extension_cleanup(inode, ret < (ssize_t)count);
+ }
+ out:
+ inode_unlock(inode);
--- /dev/null
+From 5c0f4cc84d3a601c99bc5e6e6eb1cbda542cce95 Mon Sep 17 00:00:00 2001
+From: Baokun Li <libaokun1@huawei.com>
+Date: Thu, 22 Aug 2024 10:35:27 +0800
+Subject: ext4: drop ppath from ext4_ext_replay_update_ex() to avoid double-free
+
+From: Baokun Li <libaokun1@huawei.com>
+
+commit 5c0f4cc84d3a601c99bc5e6e6eb1cbda542cce95 upstream.
+
+When calling ext4_force_split_extent_at() in ext4_ext_replay_update_ex(),
+the 'ppath' is updated but it is the 'path' that is freed, thus potentially
+triggering a double-free in the following process:
+
+ext4_ext_replay_update_ex
+ ppath = path
+ ext4_force_split_extent_at(&ppath)
+ ext4_split_extent_at
+ ext4_ext_insert_extent
+ ext4_ext_create_new_leaf
+ ext4_ext_grow_indepth
+ ext4_find_extent
+ if (depth > path[0].p_maxdepth)
+ kfree(path) ---> path First freed
+ *orig_path = path = NULL ---> null ppath
+ kfree(path) ---> path double-free !!!
+
+So drop the unnecessary ppath and use path directly to avoid this problem.
+And use ext4_find_extent() directly to update path, avoiding unnecessary
+memory allocation and freeing. Also, propagate the error returned by
+ext4_find_extent() instead of using strange error codes.
+
+Fixes: 8016e29f4362 ("ext4: fast commit recovery path")
+Cc: stable@kernel.org
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Link: https://patch.msgid.link/20240822023545.1994557-8-libaokun@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/extents.c | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -5926,7 +5926,7 @@ out:
+ int ext4_ext_replay_update_ex(struct inode *inode, ext4_lblk_t start,
+ int len, int unwritten, ext4_fsblk_t pblk)
+ {
+- struct ext4_ext_path *path = NULL, *ppath;
++ struct ext4_ext_path *path;
+ struct ext4_extent *ex;
+ int ret;
+
+@@ -5942,30 +5942,29 @@ int ext4_ext_replay_update_ex(struct ino
+ if (le32_to_cpu(ex->ee_block) != start ||
+ ext4_ext_get_actual_len(ex) != len) {
+ /* We need to split this extent to match our extent first */
+- ppath = path;
+ down_write(&EXT4_I(inode)->i_data_sem);
+- ret = ext4_force_split_extent_at(NULL, inode, &ppath, start, 1);
++ ret = ext4_force_split_extent_at(NULL, inode, &path, start, 1);
+ up_write(&EXT4_I(inode)->i_data_sem);
+ if (ret)
+ goto out;
+- kfree(path);
+- path = ext4_find_extent(inode, start, NULL, 0);
++
++ path = ext4_find_extent(inode, start, &path, 0);
+ if (IS_ERR(path))
+- return -1;
+- ppath = path;
++ return PTR_ERR(path);
+ ex = path[path->p_depth].p_ext;
+ WARN_ON(le32_to_cpu(ex->ee_block) != start);
++
+ if (ext4_ext_get_actual_len(ex) != len) {
+ down_write(&EXT4_I(inode)->i_data_sem);
+- ret = ext4_force_split_extent_at(NULL, inode, &ppath,
++ ret = ext4_force_split_extent_at(NULL, inode, &path,
+ start + len, 1);
+ up_write(&EXT4_I(inode)->i_data_sem);
+ if (ret)
+ goto out;
+- kfree(path);
+- path = ext4_find_extent(inode, start, NULL, 0);
++
++ path = ext4_find_extent(inode, start, &path, 0);
+ if (IS_ERR(path))
+- return -EINVAL;
++ return PTR_ERR(path);
+ ex = path[path->p_depth].p_ext;
+ }
+ }
--- /dev/null
+From dcaa6c31134c0f515600111c38ed7750003e1b9c Mon Sep 17 00:00:00 2001
+From: Baokun Li <libaokun1@huawei.com>
+Date: Thu, 22 Aug 2024 10:35:28 +0800
+Subject: ext4: fix double brelse() the buffer of the extents path
+
+From: Baokun Li <libaokun1@huawei.com>
+
+commit dcaa6c31134c0f515600111c38ed7750003e1b9c upstream.
+
+In ext4_ext_try_to_merge_up(), set path[1].p_bh to NULL after it has been
+released, otherwise it may be released twice. An example of what triggers
+this is as follows:
+
+ split2 map split1
+|--------|-------|--------|
+
+ext4_ext_map_blocks
+ ext4_ext_handle_unwritten_extents
+ ext4_split_convert_extents
+ // path->p_depth == 0
+ ext4_split_extent
+ // 1. do split1
+ ext4_split_extent_at
+ |ext4_ext_insert_extent
+ | ext4_ext_create_new_leaf
+ | ext4_ext_grow_indepth
+ | le16_add_cpu(&neh->eh_depth, 1)
+ | ext4_find_extent
+ | // return -ENOMEM
+ |// get error and try zeroout
+ |path = ext4_find_extent
+ | path->p_depth = 1
+ |ext4_ext_try_to_merge
+ | ext4_ext_try_to_merge_up
+ | path->p_depth = 0
+ | brelse(path[1].p_bh) ---> not set to NULL here
+ |// zeroout success
+ // 2. update path
+ ext4_find_extent
+ // 3. do split2
+ ext4_split_extent_at
+ ext4_ext_insert_extent
+ ext4_ext_create_new_leaf
+ ext4_ext_grow_indepth
+ le16_add_cpu(&neh->eh_depth, 1)
+ ext4_find_extent
+ path[0].p_bh = NULL;
+ path->p_depth = 1
+ read_extent_tree_block ---> return err
+ // path[1].p_bh is still the old value
+ ext4_free_ext_path
+ ext4_ext_drop_refs
+ // path->p_depth == 1
+ brelse(path[1].p_bh) ---> brelse a buffer twice
+
+Finally got the following WARRNING when removing the buffer from lru:
+
+============================================
+VFS: brelse: Trying to free free buffer
+WARNING: CPU: 2 PID: 72 at fs/buffer.c:1241 __brelse+0x58/0x90
+CPU: 2 PID: 72 Comm: kworker/u19:1 Not tainted 6.9.0-dirty #716
+RIP: 0010:__brelse+0x58/0x90
+Call Trace:
+ <TASK>
+ __find_get_block+0x6e7/0x810
+ bdev_getblk+0x2b/0x480
+ __ext4_get_inode_loc+0x48a/0x1240
+ ext4_get_inode_loc+0xb2/0x150
+ ext4_reserve_inode_write+0xb7/0x230
+ __ext4_mark_inode_dirty+0x144/0x6a0
+ ext4_ext_insert_extent+0x9c8/0x3230
+ ext4_ext_map_blocks+0xf45/0x2dc0
+ ext4_map_blocks+0x724/0x1700
+ ext4_do_writepages+0x12d6/0x2a70
+[...]
+============================================
+
+Fixes: ecb94f5fdf4b ("ext4: collapse a single extent tree block into the inode if possible")
+Cc: stable@kernel.org
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Link: https://patch.msgid.link/20240822023545.1994557-9-libaokun@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/extents.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -1877,6 +1877,7 @@ static void ext4_ext_try_to_merge_up(han
+ path[0].p_hdr->eh_max = cpu_to_le16(max_root);
+
+ brelse(path[1].p_bh);
++ path[1].p_bh = NULL;
+ ext4_free_blocks(handle, inode, NULL, blk, 1,
+ EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET);
+ }
--- /dev/null
+From 6db3c1575a750fd417a70e0178bdf6efa0dd5037 Mon Sep 17 00:00:00 2001
+From: "Luis Henriques (SUSE)" <luis.henriques@linux.dev>
+Date: Wed, 17 Jul 2024 18:22:20 +0100
+Subject: ext4: fix fast commit inode enqueueing during a full journal commit
+
+From: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+
+commit 6db3c1575a750fd417a70e0178bdf6efa0dd5037 upstream.
+
+When a full journal commit is on-going, any fast commit has to be enqueued
+into a different queue: FC_Q_STAGING instead of FC_Q_MAIN. This enqueueing
+is done only once, i.e. if an inode is already queued in a previous fast
+commit entry it won't be enqueued again. However, if a full commit starts
+_after_ the inode is enqueued into FC_Q_MAIN, the next fast commit needs to
+be done into FC_Q_STAGING. And this is not being done in function
+ext4_fc_track_template().
+
+This patch fixes the issue by re-enqueuing an inode into the STAGING queue
+during the fast commit clean-up callback when doing a full commit. However,
+to prevent a race with a fast-commit, the clean-up callback has to be called
+with the journal locked.
+
+This bug was found using fstest generic/047. This test creates several 32k
+bytes files, sync'ing each of them after it's creation, and then shutting
+down the filesystem. Some data may be loss in this operation; for example a
+file may have it's size truncated to zero.
+
+Suggested-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240717172220.14201-1-luis.henriques@linux.dev
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/fast_commit.c | 15 ++++++++++++++-
+ fs/jbd2/journal.c | 2 +-
+ 2 files changed, 15 insertions(+), 2 deletions(-)
+
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -1317,8 +1317,21 @@ static void ext4_fc_cleanup(journal_t *j
+ list_del_init(&iter->i_fc_list);
+ ext4_clear_inode_state(&iter->vfs_inode,
+ EXT4_STATE_FC_COMMITTING);
+- if (tid_geq(tid, iter->i_sync_tid))
++ if (tid_geq(tid, iter->i_sync_tid)) {
+ ext4_fc_reset_inode(&iter->vfs_inode);
++ } else if (full) {
++ /*
++ * We are called after a full commit, inode has been
++ * modified while the commit was running. Re-enqueue
++ * the inode into STAGING, which will then be splice
++ * back into MAIN. This cannot happen during
++ * fastcommit because the journal is locked all the
++ * time in that case (and tid doesn't increase so
++ * tid check above isn't reliable).
++ */
++ list_add_tail(&EXT4_I(&iter->vfs_inode)->i_fc_list,
++ &sbi->s_fc_q[FC_Q_STAGING]);
++ }
+ /* Make sure EXT4_STATE_FC_COMMITTING bit is clear */
+ smp_mb();
+ #if (BITS_PER_LONG < 64)
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -767,9 +767,9 @@ EXPORT_SYMBOL(jbd2_fc_begin_commit);
+ */
+ static int __jbd2_fc_end_commit(journal_t *journal, tid_t tid, bool fallback)
+ {
+- jbd2_journal_unlock_updates(journal);
+ if (journal->j_fc_cleanup_callback)
+ journal->j_fc_cleanup_callback(journal, 0, tid);
++ jbd2_journal_unlock_updates(journal);
+ write_lock(&journal->j_state_lock);
+ journal->j_flags &= ~JBD2_FAST_COMMIT_ONGOING;
+ if (fallback)
--- /dev/null
+From 972090651ee15e51abfb2160e986fa050cfc7a40 Mon Sep 17 00:00:00 2001
+From: "Luis Henriques (SUSE)" <luis.henriques@linux.dev>
+Date: Wed, 24 Jul 2024 17:11:16 +0100
+Subject: ext4: fix incorrect tid assumption in __jbd2_log_wait_for_space()
+
+From: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+
+commit 972090651ee15e51abfb2160e986fa050cfc7a40 upstream.
+
+Function __jbd2_log_wait_for_space() assumes that '0' is not a valid value
+for transaction IDs, which is incorrect. Don't assume that and invoke
+jbd2_log_wait_commit() if the journal had a committing transaction instead.
+
+Signed-off-by: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240724161119.13448-3-luis.henriques@linux.dev
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/jbd2/checkpoint.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -91,9 +91,12 @@ __releases(&journal->j_state_lock)
+ if (space_left < nblocks) {
+ int chkpt = journal->j_checkpoint_transactions != NULL;
+ tid_t tid = 0;
++ bool has_transaction = false;
+
+- if (journal->j_committing_transaction)
++ if (journal->j_committing_transaction) {
+ tid = journal->j_committing_transaction->t_tid;
++ has_transaction = true;
++ }
+ spin_unlock(&journal->j_list_lock);
+ write_unlock(&journal->j_state_lock);
+ if (chkpt) {
+@@ -101,7 +104,7 @@ __releases(&journal->j_state_lock)
+ } else if (jbd2_cleanup_journal_tail(journal) == 0) {
+ /* We were able to recover space; yay! */
+ ;
+- } else if (tid) {
++ } else if (has_transaction) {
+ /*
+ * jbd2_journal_commit_transaction() may want
+ * to take the checkpoint_mutex if JBD2_FLUSHED
--- /dev/null
+From ebc4b2c1ac92fc0f8bf3f5a9c285a871d5084a6b Mon Sep 17 00:00:00 2001
+From: "Luis Henriques (SUSE)" <luis.henriques@linux.dev>
+Date: Wed, 24 Jul 2024 17:11:18 +0100
+Subject: ext4: fix incorrect tid assumption in ext4_fc_mark_ineligible()
+
+From: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+
+commit ebc4b2c1ac92fc0f8bf3f5a9c285a871d5084a6b upstream.
+
+Function jbd2_journal_shrink_checkpoint_list() assumes that '0' is not a
+valid value for transaction IDs, which is incorrect.
+
+Furthermore, the sbi->s_fc_ineligible_tid handling also makes the same
+assumption by being initialised to '0'. Fortunately, the sb flag
+EXT4_MF_FC_INELIGIBLE can be used to check whether sbi->s_fc_ineligible_tid
+has been previously set instead of comparing it with '0'.
+
+Signed-off-by: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240724161119.13448-5-luis.henriques@linux.dev
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/fast_commit.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -339,22 +339,29 @@ void ext4_fc_mark_ineligible(struct supe
+ {
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+ tid_t tid;
++ bool has_transaction = true;
++ bool is_ineligible;
+
+ if (ext4_fc_disabled(sb))
+ return;
+
+- ext4_set_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
+ if (handle && !IS_ERR(handle))
+ tid = handle->h_transaction->t_tid;
+ else {
+ read_lock(&sbi->s_journal->j_state_lock);
+- tid = sbi->s_journal->j_running_transaction ?
+- sbi->s_journal->j_running_transaction->t_tid : 0;
++ if (sbi->s_journal->j_running_transaction)
++ tid = sbi->s_journal->j_running_transaction->t_tid;
++ else
++ has_transaction = false;
+ read_unlock(&sbi->s_journal->j_state_lock);
+ }
+ spin_lock(&sbi->s_fc_lock);
+- if (tid_gt(tid, sbi->s_fc_ineligible_tid))
++ is_ineligible = ext4_test_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
++ if (has_transaction &&
++ (!is_ineligible ||
++ (is_ineligible && tid_gt(tid, sbi->s_fc_ineligible_tid))))
+ sbi->s_fc_ineligible_tid = tid;
++ ext4_set_mount_flag(sb, EXT4_MF_FC_INELIGIBLE);
+ spin_unlock(&sbi->s_fc_lock);
+ WARN_ON(reason >= EXT4_FC_REASON_MAX);
+ sbi->s_fc_stats.fc_ineligible_reason_count[reason]++;
--- /dev/null
+From dd589b0f1445e1ea1085b98edca6e4d5dedb98d0 Mon Sep 17 00:00:00 2001
+From: "Luis Henriques (SUSE)" <luis.henriques@linux.dev>
+Date: Wed, 24 Jul 2024 17:11:15 +0100
+Subject: ext4: fix incorrect tid assumption in ext4_wait_for_tail_page_commit()
+
+From: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+
+commit dd589b0f1445e1ea1085b98edca6e4d5dedb98d0 upstream.
+
+Function ext4_wait_for_tail_page_commit() assumes that '0' is not a valid
+value for transaction IDs, which is incorrect. Don't assume that and invoke
+jbd2_log_wait_commit() if the journal had a committing transaction instead.
+
+Signed-off-by: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240724161119.13448-2-luis.henriques@linux.dev
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/inode.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5350,8 +5350,9 @@ static void ext4_wait_for_tail_page_comm
+ {
+ unsigned offset;
+ journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
+- tid_t commit_tid = 0;
++ tid_t commit_tid;
+ int ret;
++ bool has_transaction;
+
+ offset = inode->i_size & (PAGE_SIZE - 1);
+ /*
+@@ -5376,12 +5377,14 @@ static void ext4_wait_for_tail_page_comm
+ folio_put(folio);
+ if (ret != -EBUSY)
+ return;
+- commit_tid = 0;
++ has_transaction = false;
+ read_lock(&journal->j_state_lock);
+- if (journal->j_committing_transaction)
++ if (journal->j_committing_transaction) {
+ commit_tid = journal->j_committing_transaction->t_tid;
++ has_transaction = true;
++ }
+ read_unlock(&journal->j_state_lock);
+- if (commit_tid)
++ if (has_transaction)
+ jbd2_log_wait_commit(journal, commit_tid);
+ }
+ }
--- /dev/null
+From 7a6443e1dad70281f99f0bd394d7fd342481a632 Mon Sep 17 00:00:00 2001
+From: "Luis Henriques (SUSE)" <luis.henriques@linux.dev>
+Date: Wed, 24 Jul 2024 17:11:17 +0100
+Subject: ext4: fix incorrect tid assumption in jbd2_journal_shrink_checkpoint_list()
+
+From: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+
+commit 7a6443e1dad70281f99f0bd394d7fd342481a632 upstream.
+
+Function jbd2_journal_shrink_checkpoint_list() assumes that '0' is not a
+valid value for transaction IDs, which is incorrect. Don't assume that and
+use two extra boolean variables to control the loop iterations and keep
+track of the first and last tid.
+
+Signed-off-by: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240724161119.13448-4-luis.henriques@linux.dev
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/jbd2/checkpoint.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -424,6 +424,7 @@ unsigned long jbd2_journal_shrink_checkp
+ tid_t tid = 0;
+ unsigned long nr_freed = 0;
+ unsigned long freed;
++ bool first_set = false;
+
+ again:
+ spin_lock(&journal->j_list_lock);
+@@ -443,8 +444,10 @@ again:
+ else
+ transaction = journal->j_checkpoint_transactions;
+
+- if (!first_tid)
++ if (!first_set) {
+ first_tid = transaction->t_tid;
++ first_set = true;
++ }
+ last_transaction = journal->j_checkpoint_transactions->t_cpprev;
+ next_transaction = transaction;
+ last_tid = last_transaction->t_tid;
+@@ -474,7 +477,7 @@ again:
+ spin_unlock(&journal->j_list_lock);
+ cond_resched();
+
+- if (*nr_to_scan && next_tid)
++ if (*nr_to_scan && journal->j_shrink_transaction)
+ goto again;
+ out:
+ trace_jbd2_shrink_checkpoint_list(journal, first_tid, tid, last_tid,
--- /dev/null
+From c26ab35702f8cd0cdc78f96aa5856bfb77be798f Mon Sep 17 00:00:00 2001
+From: Baokun Li <libaokun1@huawei.com>
+Date: Thu, 22 Aug 2024 10:35:23 +0800
+Subject: ext4: fix slab-use-after-free in ext4_split_extent_at()
+
+From: Baokun Li <libaokun1@huawei.com>
+
+commit c26ab35702f8cd0cdc78f96aa5856bfb77be798f upstream.
+
+We hit the following use-after-free:
+
+==================================================================
+BUG: KASAN: slab-use-after-free in ext4_split_extent_at+0xba8/0xcc0
+Read of size 2 at addr ffff88810548ed08 by task kworker/u20:0/40
+CPU: 0 PID: 40 Comm: kworker/u20:0 Not tainted 6.9.0-dirty #724
+Call Trace:
+ <TASK>
+ kasan_report+0x93/0xc0
+ ext4_split_extent_at+0xba8/0xcc0
+ ext4_split_extent.isra.0+0x18f/0x500
+ ext4_split_convert_extents+0x275/0x750
+ ext4_ext_handle_unwritten_extents+0x73e/0x1580
+ ext4_ext_map_blocks+0xe20/0x2dc0
+ ext4_map_blocks+0x724/0x1700
+ ext4_do_writepages+0x12d6/0x2a70
+[...]
+
+Allocated by task 40:
+ __kmalloc_noprof+0x1ac/0x480
+ ext4_find_extent+0xf3b/0x1e70
+ ext4_ext_map_blocks+0x188/0x2dc0
+ ext4_map_blocks+0x724/0x1700
+ ext4_do_writepages+0x12d6/0x2a70
+[...]
+
+Freed by task 40:
+ kfree+0xf1/0x2b0
+ ext4_find_extent+0xa71/0x1e70
+ ext4_ext_insert_extent+0xa22/0x3260
+ ext4_split_extent_at+0x3ef/0xcc0
+ ext4_split_extent.isra.0+0x18f/0x500
+ ext4_split_convert_extents+0x275/0x750
+ ext4_ext_handle_unwritten_extents+0x73e/0x1580
+ ext4_ext_map_blocks+0xe20/0x2dc0
+ ext4_map_blocks+0x724/0x1700
+ ext4_do_writepages+0x12d6/0x2a70
+[...]
+==================================================================
+
+The flow of issue triggering is as follows:
+
+ext4_split_extent_at
+ path = *ppath
+ ext4_ext_insert_extent(ppath)
+ ext4_ext_create_new_leaf(ppath)
+ ext4_find_extent(orig_path)
+ path = *orig_path
+ read_extent_tree_block
+ // return -ENOMEM or -EIO
+ ext4_free_ext_path(path)
+ kfree(path)
+ *orig_path = NULL
+ a. If err is -ENOMEM:
+ ext4_ext_dirty(path + path->p_depth)
+ // path use-after-free !!!
+ b. If err is -EIO and we have EXT_DEBUG defined:
+ ext4_ext_show_leaf(path)
+ eh = path[depth].p_hdr
+ // path also use-after-free !!!
+
+So when trying to zeroout or fix the extent length, call ext4_find_extent()
+to update the path.
+
+In addition we use *ppath directly as an ext4_ext_show_leaf() input to
+avoid possible use-after-free when EXT_DEBUG is defined, and to avoid
+unnecessary path updates.
+
+Fixes: dfe5080939ea ("ext4: drop EXT4_EX_NOFREE_ON_ERR from rest of extents handling code")
+Cc: stable@kernel.org
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Link: https://patch.msgid.link/20240822023545.1994557-4-libaokun@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/extents.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3232,6 +3232,25 @@ static int ext4_split_extent_at(handle_t
+ if (err != -ENOSPC && err != -EDQUOT && err != -ENOMEM)
+ goto out;
+
++ /*
++ * Update path is required because previous ext4_ext_insert_extent()
++ * may have freed or reallocated the path. Using EXT4_EX_NOFAIL
++ * guarantees that ext4_find_extent() will not return -ENOMEM,
++ * otherwise -ENOMEM will cause a retry in do_writepages(), and a
++ * WARN_ON may be triggered in ext4_da_update_reserve_space() due to
++ * an incorrect ee_len causing the i_reserved_data_blocks exception.
++ */
++ path = ext4_find_extent(inode, ee_block, ppath,
++ flags | EXT4_EX_NOFAIL);
++ if (IS_ERR(path)) {
++ EXT4_ERROR_INODE(inode, "Failed split extent on %u, err %ld",
++ split, PTR_ERR(path));
++ return PTR_ERR(path);
++ }
++ depth = ext_depth(inode);
++ ex = path[depth].p_ext;
++ *ppath = path;
++
+ if (EXT4_EXT_MAY_ZEROOUT & split_flag) {
+ if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
+ if (split_flag & EXT4_EXT_DATA_VALID1) {
+@@ -3284,7 +3303,7 @@ fix_extent_len:
+ ext4_ext_dirty(handle, inode, path + path->p_depth);
+ return err;
+ out:
+- ext4_ext_show_leaf(inode, path);
++ ext4_ext_show_leaf(inode, *ppath);
+ return err;
+ }
+
--- /dev/null
+From 04e6ce8f06d161399e5afde3df5dcfa9455b4952 Mon Sep 17 00:00:00 2001
+From: "Luis Henriques (SUSE)" <luis.henriques@linux.dev>
+Date: Mon, 23 Sep 2024 11:49:09 +0100
+Subject: ext4: mark fc as ineligible using an handle in ext4_xattr_set()
+
+From: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+
+commit 04e6ce8f06d161399e5afde3df5dcfa9455b4952 upstream.
+
+Calling ext4_fc_mark_ineligible() with a NULL handle is racy and may result
+in a fast-commit being done before the filesystem is effectively marked as
+ineligible. This patch moves the call to this function so that an handle
+can be used. If a transaction fails to start, then there's not point in
+trying to mark the filesystem as ineligible, and an error will eventually be
+returned to user-space.
+
+Suggested-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240923104909.18342-3-luis.henriques@linux.dev
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/xattr.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -2505,6 +2505,8 @@ retry:
+
+ error = ext4_xattr_set_handle(handle, inode, name_index, name,
+ value, value_len, flags);
++ ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR,
++ handle);
+ error2 = ext4_journal_stop(handle);
+ if (error == -ENOSPC &&
+ ext4_should_retry_alloc(sb, &retries))
+@@ -2512,7 +2514,6 @@ retry:
+ if (error == 0)
+ error = error2;
+ }
+- ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_XATTR, NULL);
+
+ return error;
+ }
--- /dev/null
+From 1a00a393d6a7fb1e745a41edd09019bd6a0ad64c Mon Sep 17 00:00:00 2001
+From: Edward Adam Davis <eadavis@qq.com>
+Date: Mon, 1 Jul 2024 22:25:03 +0800
+Subject: ext4: no need to continue when the number of entries is 1
+
+From: Edward Adam Davis <eadavis@qq.com>
+
+commit 1a00a393d6a7fb1e745a41edd09019bd6a0ad64c upstream.
+
+Fixes: ac27a0ec112a ("[PATCH] ext4: initial copy of files from ext3")
+Reported-by: syzbot+ae688d469e36fb5138d0@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=ae688d469e36fb5138d0
+Signed-off-by: Edward Adam Davis <eadavis@qq.com>
+Reported-and-tested-by: syzbot+ae688d469e36fb5138d0@syzkaller.appspotmail.com
+Link: https://patch.msgid.link/tencent_BE7AEE6C7C2D216CB8949CE8E6EE7ECC2C0A@qq.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/namei.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2047,7 +2047,7 @@ static struct ext4_dir_entry_2 *do_split
+ split = count/2;
+
+ hash2 = map[split].hash;
+- continued = hash2 == map[split - 1].hash;
++ continued = split > 0 ? hash2 == map[split - 1].hash : 0;
+ dxtrace(printk(KERN_INFO "Split block %lu at %x, %i/%i\n",
+ (unsigned long)dx_get_block(frame->at),
+ hash2, split, count-split));
--- /dev/null
+From 369c944ed1d7c3fb7b35f24e4735761153afe7b3 Mon Sep 17 00:00:00 2001
+From: Baokun Li <libaokun1@huawei.com>
+Date: Thu, 22 Aug 2024 10:35:30 +0800
+Subject: ext4: propagate errors from ext4_find_extent() in ext4_insert_range()
+
+From: Baokun Li <libaokun1@huawei.com>
+
+commit 369c944ed1d7c3fb7b35f24e4735761153afe7b3 upstream.
+
+Even though ext4_find_extent() returns an error, ext4_insert_range() still
+returns 0. This may confuse the user as to why fallocate returns success,
+but the contents of the file are not as expected. So propagate the error
+returned by ext4_find_extent() to avoid inconsistencies.
+
+Fixes: 331573febb6a ("ext4: Add support FALLOC_FL_INSERT_RANGE for fallocate")
+Cc: stable@kernel.org
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Tested-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
+Link: https://patch.msgid.link/20240822023545.1994557-11-libaokun@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/extents.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -5570,6 +5570,7 @@ static int ext4_insert_range(struct file
+ path = ext4_find_extent(inode, offset_lblk, NULL, 0);
+ if (IS_ERR(path)) {
+ up_write(&EXT4_I(inode)->i_data_sem);
++ ret = PTR_ERR(path);
+ goto out_stop;
+ }
+
--- /dev/null
+From 5b4b2dcace35f618fe361a87bae6f0d13af31bc1 Mon Sep 17 00:00:00 2001
+From: Baokun Li <libaokun1@huawei.com>
+Date: Thu, 22 Aug 2024 10:35:25 +0800
+Subject: ext4: update orig_path in ext4_find_extent()
+
+From: Baokun Li <libaokun1@huawei.com>
+
+commit 5b4b2dcace35f618fe361a87bae6f0d13af31bc1 upstream.
+
+In ext4_find_extent(), if the path is not big enough, we free it and set
+*orig_path to NULL. But after reallocating and successfully initializing
+the path, we don't update *orig_path, in which case the caller gets a
+valid path but a NULL ppath, and this may cause a NULL pointer dereference
+or a path memory leak. For example:
+
+ext4_split_extent
+ path = *ppath = 2000
+ ext4_find_extent
+ if (depth > path[0].p_maxdepth)
+ kfree(path = 2000);
+ *orig_path = path = NULL;
+ path = kcalloc() = 3000
+ ext4_split_extent_at(*ppath = NULL)
+ path = *ppath;
+ ex = path[depth].p_ext;
+ // NULL pointer dereference!
+
+==================================================================
+BUG: kernel NULL pointer dereference, address: 0000000000000010
+CPU: 6 UID: 0 PID: 576 Comm: fsstress Not tainted 6.11.0-rc2-dirty #847
+RIP: 0010:ext4_split_extent_at+0x6d/0x560
+Call Trace:
+ <TASK>
+ ext4_split_extent.isra.0+0xcb/0x1b0
+ ext4_ext_convert_to_initialized+0x168/0x6c0
+ ext4_ext_handle_unwritten_extents+0x325/0x4d0
+ ext4_ext_map_blocks+0x520/0xdb0
+ ext4_map_blocks+0x2b0/0x690
+ ext4_iomap_begin+0x20e/0x2c0
+[...]
+==================================================================
+
+Therefore, *orig_path is updated when the extent lookup succeeds, so that
+the caller can safely use path or *ppath.
+
+Fixes: 10809df84a4d ("ext4: teach ext4_ext_find_extent() to realloc path if necessary")
+Cc: stable@kernel.org
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240822023545.1994557-6-libaokun@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/extents.c | 3 ++-
+ fs/ext4/move_extent.c | 1 -
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -957,6 +957,8 @@ ext4_find_extent(struct inode *inode, ex
+
+ ext4_ext_show_path(inode, path);
+
++ if (orig_path)
++ *orig_path = path;
+ return path;
+
+ err:
+@@ -3251,7 +3253,6 @@ static int ext4_split_extent_at(handle_t
+ }
+ depth = ext_depth(inode);
+ ex = path[depth].p_ext;
+- *ppath = path;
+
+ if (EXT4_EXT_MAY_ZEROOUT & split_flag) {
+ if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
+--- a/fs/ext4/move_extent.c
++++ b/fs/ext4/move_extent.c
+@@ -36,7 +36,6 @@ get_ext_path(struct inode *inode, ext4_l
+ *ppath = NULL;
+ return -ENODATA;
+ }
+- *ppath = path;
+ return 0;
+ }
+
--- /dev/null
+From faab35a0370fd6e0821c7a8dd213492946fc776f Mon Sep 17 00:00:00 2001
+From: "Luis Henriques (SUSE)" <luis.henriques@linux.dev>
+Date: Mon, 23 Sep 2024 11:49:08 +0100
+Subject: ext4: use handle to mark fc as ineligible in __track_dentry_update()
+
+From: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+
+commit faab35a0370fd6e0821c7a8dd213492946fc776f upstream.
+
+Calling ext4_fc_mark_ineligible() with a NULL handle is racy and may result
+in a fast-commit being done before the filesystem is effectively marked as
+ineligible. This patch fixes the calls to this function in
+__track_dentry_update() by adding an extra parameter to the callback used in
+ext4_fc_track_template().
+
+Suggested-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Luis Henriques (SUSE) <luis.henriques@linux.dev>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240923104909.18342-2-luis.henriques@linux.dev
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/fast_commit.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -379,7 +379,7 @@ void ext4_fc_mark_ineligible(struct supe
+ */
+ static int ext4_fc_track_template(
+ handle_t *handle, struct inode *inode,
+- int (*__fc_track_fn)(struct inode *, void *, bool),
++ int (*__fc_track_fn)(handle_t *handle, struct inode *, void *, bool),
+ void *args, int enqueue)
+ {
+ bool update = false;
+@@ -396,7 +396,7 @@ static int ext4_fc_track_template(
+ ext4_fc_reset_inode(inode);
+ ei->i_sync_tid = tid;
+ }
+- ret = __fc_track_fn(inode, args, update);
++ ret = __fc_track_fn(handle, inode, args, update);
+ mutex_unlock(&ei->i_fc_lock);
+
+ if (!enqueue)
+@@ -420,7 +420,8 @@ struct __track_dentry_update_args {
+ };
+
+ /* __track_fn for directory entry updates. Called with ei->i_fc_lock. */
+-static int __track_dentry_update(struct inode *inode, void *arg, bool update)
++static int __track_dentry_update(handle_t *handle, struct inode *inode,
++ void *arg, bool update)
+ {
+ struct ext4_fc_dentry_update *node;
+ struct ext4_inode_info *ei = EXT4_I(inode);
+@@ -435,14 +436,14 @@ static int __track_dentry_update(struct
+
+ if (IS_ENCRYPTED(dir)) {
+ ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_ENCRYPTED_FILENAME,
+- NULL);
++ handle);
+ mutex_lock(&ei->i_fc_lock);
+ return -EOPNOTSUPP;
+ }
+
+ node = kmem_cache_alloc(ext4_fc_dentry_cachep, GFP_NOFS);
+ if (!node) {
+- ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_NOMEM, NULL);
++ ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_NOMEM, handle);
+ mutex_lock(&ei->i_fc_lock);
+ return -ENOMEM;
+ }
+@@ -454,7 +455,7 @@ static int __track_dentry_update(struct
+ node->fcd_name.name = kmalloc(dentry->d_name.len, GFP_NOFS);
+ if (!node->fcd_name.name) {
+ kmem_cache_free(ext4_fc_dentry_cachep, node);
+- ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_NOMEM, NULL);
++ ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_NOMEM, handle);
+ mutex_lock(&ei->i_fc_lock);
+ return -ENOMEM;
+ }
+@@ -576,7 +577,8 @@ void ext4_fc_track_create(handle_t *hand
+ }
+
+ /* __track_fn for inode tracking */
+-static int __track_inode(struct inode *inode, void *arg, bool update)
++static int __track_inode(handle_t *handle, struct inode *inode, void *arg,
++ bool update)
+ {
+ if (update)
+ return -EEXIST;
+@@ -614,7 +616,8 @@ struct __track_range_args {
+ };
+
+ /* __track_fn for tracking data updates */
+-static int __track_range(struct inode *inode, void *arg, bool update)
++static int __track_range(handle_t *handle, struct inode *inode, void *arg,
++ bool update)
+ {
+ struct ext4_inode_info *ei = EXT4_I(inode);
+ ext4_lblk_t oldstart;
alsa-line6-add-hw-monitor-volume-control-to-pod-hd500x.patch
alsa-hda-realtek-add-quirk-for-huawei-matebook-13-klv-wx9.patch
alsa-hda-realtek-add-a-quirk-for-hp-pavilion-15z-ec200.patch
+ext4-no-need-to-continue-when-the-number-of-entries-is-1.patch
+ext4-correct-encrypted-dentry-name-hash-when-not-casefolded.patch
+ext4-fix-slab-use-after-free-in-ext4_split_extent_at.patch
+ext4-propagate-errors-from-ext4_find_extent-in-ext4_insert_range.patch
+ext4-fix-incorrect-tid-assumption-in-ext4_fc_mark_ineligible.patch
+ext4-dax-fix-overflowing-extents-beyond-inode-size-when-partially-writing.patch
+ext4-fix-incorrect-tid-assumption-in-__jbd2_log_wait_for_space.patch
+ext4-drop-ppath-from-ext4_ext_replay_update_ex-to-avoid-double-free.patch
+ext4-aovid-use-after-free-in-ext4_ext_insert_extent.patch
+ext4-fix-double-brelse-the-buffer-of-the-extents-path.patch
+ext4-update-orig_path-in-ext4_find_extent.patch
+ext4-fix-incorrect-tid-assumption-in-ext4_wait_for_tail_page_commit.patch
+ext4-fix-incorrect-tid-assumption-in-jbd2_journal_shrink_checkpoint_list.patch
+ext4-fix-fast-commit-inode-enqueueing-during-a-full-journal-commit.patch
+ext4-use-handle-to-mark-fc-as-ineligible-in-__track_dentry_update.patch
+ext4-mark-fc-as-ineligible-using-an-handle-in-ext4_xattr_set.patch