CVE-2022-49898
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
01/05/2025
Last modified:
02/05/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
btrfs: fix tree mod log mishandling of reallocated nodes<br />
<br />
We have been seeing the following panic in production<br />
<br />
kernel BUG at fs/btrfs/tree-mod-log.c:677!<br />
invalid opcode: 0000 [#1] SMP<br />
RIP: 0010:tree_mod_log_rewind+0x1b4/0x200<br />
RSP: 0000:ffffc9002c02f890 EFLAGS: 00010293<br />
RAX: 0000000000000003 RBX: ffff8882b448c700 RCX: 0000000000000000<br />
RDX: 0000000000008000 RSI: 00000000000000a7 RDI: ffff88877d831c00<br />
RBP: 0000000000000002 R08: 000000000000009f R09: 0000000000000000<br />
R10: 0000000000000000 R11: 0000000000100c40 R12: 0000000000000001<br />
R13: ffff8886c26d6a00 R14: ffff88829f5424f8 R15: ffff88877d831a00<br />
FS: 00007fee1d80c780(0000) GS:ffff8890400c0000(0000) knlGS:0000000000000000<br />
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033<br />
CR2: 00007fee1963a020 CR3: 0000000434f33002 CR4: 00000000007706e0<br />
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000<br />
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400<br />
PKRU: 55555554<br />
Call Trace:<br />
btrfs_get_old_root+0x12b/0x420<br />
btrfs_search_old_slot+0x64/0x2f0<br />
? tree_mod_log_oldest_root+0x3d/0xf0<br />
resolve_indirect_ref+0xfd/0x660<br />
? ulist_alloc+0x31/0x60<br />
? kmem_cache_alloc_trace+0x114/0x2c0<br />
find_parent_nodes+0x97a/0x17e0<br />
? ulist_alloc+0x30/0x60<br />
btrfs_find_all_roots_safe+0x97/0x150<br />
iterate_extent_inodes+0x154/0x370<br />
? btrfs_search_path_in_tree+0x240/0x240<br />
iterate_inodes_from_logical+0x98/0xd0<br />
? btrfs_search_path_in_tree+0x240/0x240<br />
btrfs_ioctl_logical_to_ino+0xd9/0x180<br />
btrfs_ioctl+0xe2/0x2ec0<br />
? __mod_memcg_lruvec_state+0x3d/0x280<br />
? do_sys_openat2+0x6d/0x140<br />
? kretprobe_dispatcher+0x47/0x70<br />
? kretprobe_rethook_handler+0x38/0x50<br />
? rethook_trampoline_handler+0x82/0x140<br />
? arch_rethook_trampoline_callback+0x3b/0x50<br />
? kmem_cache_free+0xfb/0x270<br />
? do_sys_openat2+0xd5/0x140<br />
__x64_sys_ioctl+0x71/0xb0<br />
do_syscall_64+0x2d/0x40<br />
<br />
Which is this code in tree_mod_log_rewind()<br />
<br />
switch (tm->op) {<br />
case BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING:<br />
BUG_ON(tm->slot From here the bug is triggered by the following steps<br />
<br />
1. Call btrfs_get_old_root() on the new_root.<br />
2. We call tree_mod_log_oldest_root(btrfs_root_node(new_root)), which is<br />
currently logical 0.<br />
3. tree_mod_log_oldest_root() calls tree_mod_log_search_oldest(), which<br />
gives us the KEY_REPLACE seq 2, and since that&#39;s not a<br />
LOG_ROOT_REPLACE we incorrectly believe that we don&#39;t have an old<br />
root, because we expect that the most recent change should be a<br />
LOG_ROOT_REPLACE.<br />
4. Back in tree_mod_log_oldest_root() we don&#39;t have a LOG_ROOT_REPLACE,<br />
so we don&#39;t set old_root, we simply use our e<br />
---truncated---