]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 7 Oct 2024 10:24:14 +0000 (12:24 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 7 Oct 2024 10:24:14 +0000 (12:24 +0200)
added patches:
ext4-aovid-use-after-free-in-ext4_ext_insert_extent.patch
ext4-drop-ppath-from-ext4_ext_replay_update_ex-to-avoid-double-free.patch
ext4-fix-double-brelse-the-buffer-of-the-extents-path.patch
ext4-fix-incorrect-tid-assumption-in-__jbd2_log_wait_for_space.patch
ext4-fix-incorrect-tid-assumption-in-ext4_wait_for_tail_page_commit.patch
ext4-fix-slab-use-after-free-in-ext4_split_extent_at.patch
ext4-no-need-to-continue-when-the-number-of-entries-is-1.patch
ext4-propagate-errors-from-ext4_find_extent-in-ext4_insert_range.patch
ext4-update-orig_path-in-ext4_find_extent.patch

queue-5.10/ext4-aovid-use-after-free-in-ext4_ext_insert_extent.patch [new file with mode: 0644]
queue-5.10/ext4-drop-ppath-from-ext4_ext_replay_update_ex-to-avoid-double-free.patch [new file with mode: 0644]
queue-5.10/ext4-fix-double-brelse-the-buffer-of-the-extents-path.patch [new file with mode: 0644]
queue-5.10/ext4-fix-incorrect-tid-assumption-in-__jbd2_log_wait_for_space.patch [new file with mode: 0644]
queue-5.10/ext4-fix-incorrect-tid-assumption-in-ext4_wait_for_tail_page_commit.patch [new file with mode: 0644]
queue-5.10/ext4-fix-slab-use-after-free-in-ext4_split_extent_at.patch [new file with mode: 0644]
queue-5.10/ext4-no-need-to-continue-when-the-number-of-entries-is-1.patch [new file with mode: 0644]
queue-5.10/ext4-propagate-errors-from-ext4_find_extent-in-ext4_insert_range.patch [new file with mode: 0644]
queue-5.10/ext4-update-orig_path-in-ext4_find_extent.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/ext4-aovid-use-after-free-in-ext4_ext_insert_extent.patch b/queue-5.10/ext4-aovid-use-after-free-in-ext4_ext_insert_extent.patch
new file mode 100644 (file)
index 0000000..70574c7
--- /dev/null
@@ -0,0 +1,85 @@
+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
+@@ -2095,6 +2095,7 @@ prepend:
+                                      ppath, newext);
+       if (err)
+               goto cleanup;
++      path = *ppath;
+       depth = ext_depth(inode);
+       eh = path[depth].p_hdr;
diff --git a/queue-5.10/ext4-drop-ppath-from-ext4_ext_replay_update_ex-to-avoid-double-free.patch b/queue-5.10/ext4-drop-ppath-from-ext4_ext_replay_update_ex-to-avoid-double-free.patch
new file mode 100644 (file)
index 0000000..d2157a6
--- /dev/null
@@ -0,0 +1,95 @@
+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
+@@ -5928,7 +5928,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;
+@@ -5944,30 +5944,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;
+               }
+       }
diff --git a/queue-5.10/ext4-fix-double-brelse-the-buffer-of-the-extents-path.patch b/queue-5.10/ext4-fix-double-brelse-the-buffer-of-the-extents-path.patch
new file mode 100644 (file)
index 0000000..5ad05b8
--- /dev/null
@@ -0,0 +1,100 @@
+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
+@@ -1867,6 +1867,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);
+ }
diff --git a/queue-5.10/ext4-fix-incorrect-tid-assumption-in-__jbd2_log_wait_for_space.patch b/queue-5.10/ext4-fix-incorrect-tid-assumption-in-__jbd2_log_wait_for_space.patch
new file mode 100644 (file)
index 0000000..8b31425
--- /dev/null
@@ -0,0 +1,48 @@
+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
+@@ -115,9 +115,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) {
+@@ -125,7 +128,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
diff --git a/queue-5.10/ext4-fix-incorrect-tid-assumption-in-ext4_wait_for_tail_page_commit.patch b/queue-5.10/ext4-fix-incorrect-tid-assumption-in-ext4_wait_for_tail_page_commit.patch
new file mode 100644 (file)
index 0000000..5a895bc
--- /dev/null
@@ -0,0 +1,54 @@
+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
+@@ -5367,8 +5367,9 @@ static void ext4_wait_for_tail_page_comm
+       struct page *page;
+       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);
+       /*
+@@ -5393,12 +5394,14 @@ static void ext4_wait_for_tail_page_comm
+               put_page(page);
+               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);
+       }
+ }
diff --git a/queue-5.10/ext4-fix-slab-use-after-free-in-ext4_split_extent_at.patch b/queue-5.10/ext4-fix-slab-use-after-free-in-ext4_split_extent_at.patch
new file mode 100644 (file)
index 0000000..4a6e672
--- /dev/null
@@ -0,0 +1,127 @@
+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
+@@ -3226,6 +3226,25 @@ static int ext4_split_extent_at(handle_t
+       if (err != -ENOSPC && err != -EDQUOT)
+               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) {
+@@ -3278,7 +3297,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;
+ }
diff --git a/queue-5.10/ext4-no-need-to-continue-when-the-number-of-entries-is-1.patch b/queue-5.10/ext4-no-need-to-continue-when-the-number-of-entries-is-1.patch
new file mode 100644 (file)
index 0000000..37bf5ba
--- /dev/null
@@ -0,0 +1,33 @@
+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
+@@ -1936,7 +1936,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));
diff --git a/queue-5.10/ext4-propagate-errors-from-ext4_find_extent-in-ext4_insert_range.patch b/queue-5.10/ext4-propagate-errors-from-ext4_find_extent-in-ext4_insert_range.patch
new file mode 100644 (file)
index 0000000..bec9ee6
--- /dev/null
@@ -0,0 +1,37 @@
+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
+@@ -5566,6 +5566,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;
+       }
diff --git a/queue-5.10/ext4-update-orig_path-in-ext4_find_extent.patch b/queue-5.10/ext4-update-orig_path-in-ext4_find_extent.patch
new file mode 100644 (file)
index 0000000..5044092
--- /dev/null
@@ -0,0 +1,86 @@
+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
+@@ -949,6 +949,8 @@ ext4_find_extent(struct inode *inode, ex
+       ext4_ext_show_path(inode, path);
++      if (orig_path)
++              *orig_path = path;
+       return path;
+ err:
+@@ -3245,7 +3247,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;
+ }
index 2fdde69ffd274e60770bc8d47fbce0bad00275f5..c9324687a85bba82bfd8e55ce31b5f1dd2536132 100644 (file)
@@ -379,3 +379,12 @@ drm-consistently-use-struct-drm_mode_rect-for-fb_damage_clips.patch
 alsa-core-add-isascii-check-to-card-id-generator.patch
 alsa-line6-add-hw-monitor-volume-control-to-pod-hd500x.patch
 alsa-hda-realtek-add-quirk-for-huawei-matebook-13-klv-wx9.patch
+ext4-no-need-to-continue-when-the-number-of-entries-is-1.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-__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