Commit 18e66015 authored by Filipe Manana's avatar Filipe Manana Committed by Zizhi Wo
Browse files

btrfs: reinitialize delayed ref list after deleting it from the list

stable inclusion
from stable-4.19.324
commit 2fd0948a483e9cb2d669c7199bc620a21c97673d
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IB5AVH
CVE: CVE-2024-50273

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2fd0948a483e9cb2d669c7199bc620a21c97673d



--------------------------------

commit c9a75ec45f1111ef530ab186c2a7684d0a0c9245 upstream.

At insert_delayed_ref() if we need to update the action of an existing
ref to BTRFS_DROP_DELAYED_REF, we delete the ref from its ref head's
ref_add_list using list_del(), which leaves the ref's add_list member
not reinitialized, as list_del() sets the next and prev members of the
list to LIST_POISON1 and LIST_POISON2, respectively.

If later we end up calling drop_delayed_ref() against the ref, which can
happen during merging or when destroying delayed refs due to a transaction
abort, we can trigger a crash since at drop_delayed_ref() we call
list_empty() against the ref's add_list, which returns false since
the list was not reinitialized after the list_del() and as a consequence
we call list_del() again at drop_delayed_ref(). This results in an
invalid list access since the next and prev members are set to poison
pointers, resulting in a splat if CONFIG_LIST_HARDENED and
CONFIG_DEBUG_LIST are set or invalid poison pointer dereferences
otherwise.

So fix this by deleting from the list with list_del_init() instead.

Fixes: 1d57ee94 ("btrfs: improve delayed refs iterations")
CC: stable@vger.kernel.org # 4.19+
Reviewed-by: default avatarJohannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarZizhi Wo <wozizhi@huawei.com>
parent 81e029d5
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -426,7 +426,7 @@ static int insert_delayed_ref(struct btrfs_trans_handle *trans,
					      &href->ref_add_list);
			else if (ref->action == BTRFS_DROP_DELAYED_REF) {
				ASSERT(!list_empty(&exist->add_list));
				list_del(&exist->add_list);
				list_del_init(&exist->add_list);
			} else {
				ASSERT(0);
			}