CVE-2024-53171

Severity CVSS v4.0:
Pending analysis
Type:
CWE-416 Use After Free
Publication date:
27/12/2024
Last modified:
03/11/2025

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> ubifs: authentication: Fix use-after-free in ubifs_tnc_end_commit<br /> <br /> After an insertion in TNC, the tree might split and cause a node to<br /> change its `znode-&gt;parent`. A further deletion of other nodes in the<br /> tree (which also could free the nodes), the aforementioned node&amp;#39;s<br /> `znode-&gt;cparent` could still point to a freed node. This<br /> `znode-&gt;cparent` may not be updated when getting nodes to commit in<br /> `ubifs_tnc_start_commit()`. This could then trigger a use-after-free<br /> when accessing the `znode-&gt;cparent` in `write_index()` in<br /> `ubifs_tnc_end_commit()`.<br /> <br /> This can be triggered by running<br /> <br /> rm -f /etc/test-file.bin<br /> dd if=/dev/urandom of=/etc/test-file.bin bs=1M count=60 conv=fsync<br /> <br /> in a loop, and with `CONFIG_UBIFS_FS_AUTHENTICATION`. KASAN then<br /> reports:<br /> <br /> BUG: KASAN: use-after-free in ubifs_tnc_end_commit+0xa5c/0x1950<br /> Write of size 32 at addr ffffff800a3af86c by task ubifs_bgt0_20/153<br /> <br /> Call trace:<br /> dump_backtrace+0x0/0x340<br /> show_stack+0x18/0x24<br /> dump_stack_lvl+0x9c/0xbc<br /> print_address_description.constprop.0+0x74/0x2b0<br /> kasan_report+0x1d8/0x1f0<br /> kasan_check_range+0xf8/0x1a0<br /> memcpy+0x84/0xf4<br /> ubifs_tnc_end_commit+0xa5c/0x1950<br /> do_commit+0x4e0/0x1340<br /> ubifs_bg_thread+0x234/0x2e0<br /> kthread+0x36c/0x410<br /> ret_from_fork+0x10/0x20<br /> <br /> Allocated by task 401:<br /> kasan_save_stack+0x38/0x70<br /> __kasan_kmalloc+0x8c/0xd0<br /> __kmalloc+0x34c/0x5bc<br /> tnc_insert+0x140/0x16a4<br /> ubifs_tnc_add+0x370/0x52c<br /> ubifs_jnl_write_data+0x5d8/0x870<br /> do_writepage+0x36c/0x510<br /> ubifs_writepage+0x190/0x4dc<br /> __writepage+0x58/0x154<br /> write_cache_pages+0x394/0x830<br /> do_writepages+0x1f0/0x5b0<br /> filemap_fdatawrite_wbc+0x170/0x25c<br /> file_write_and_wait_range+0x140/0x190<br /> ubifs_fsync+0xe8/0x290<br /> vfs_fsync_range+0xc0/0x1e4<br /> do_fsync+0x40/0x90<br /> __arm64_sys_fsync+0x34/0x50<br /> invoke_syscall.constprop.0+0xa8/0x260<br /> do_el0_svc+0xc8/0x1f0<br /> el0_svc+0x34/0x70<br /> el0t_64_sync_handler+0x108/0x114<br /> el0t_64_sync+0x1a4/0x1a8<br /> <br /> Freed by task 403:<br /> kasan_save_stack+0x38/0x70<br /> kasan_set_track+0x28/0x40<br /> kasan_set_free_info+0x28/0x4c<br /> __kasan_slab_free+0xd4/0x13c<br /> kfree+0xc4/0x3a0<br /> tnc_delete+0x3f4/0xe40<br /> ubifs_tnc_remove_range+0x368/0x73c<br /> ubifs_tnc_remove_ino+0x29c/0x2e0<br /> ubifs_jnl_delete_inode+0x150/0x260<br /> ubifs_evict_inode+0x1d4/0x2e4<br /> evict+0x1c8/0x450<br /> iput+0x2a0/0x3c4<br /> do_unlinkat+0x2cc/0x490<br /> __arm64_sys_unlinkat+0x90/0x100<br /> invoke_syscall.constprop.0+0xa8/0x260<br /> do_el0_svc+0xc8/0x1f0<br /> el0_svc+0x34/0x70<br /> el0t_64_sync_handler+0x108/0x114<br /> el0t_64_sync+0x1a4/0x1a8<br /> <br /> The offending `memcpy()` in `ubifs_copy_hash()` has a use-after-free<br /> when a node becomes root in TNC but still has a `cparent` to an already<br /> freed node. More specifically, consider the following TNC:<br /> <br /> zroot<br /> /<br /> /<br /> zp1<br /> /<br /> /<br /> zn<br /> <br /> Inserting a new node `zn_new` with a key smaller then `zn` will trigger<br /> a split in `tnc_insert()` if `zp1` is full:<br /> <br /> zroot<br /> / \<br /> / \<br /> zp1 zp2<br /> / \<br /> / \<br /> zn_new zn<br /> <br /> `zn-&gt;parent` has now been moved to `zp2`, *but* `zn-&gt;cparent` still<br /> points to `zp1`.<br /> <br /> Now, consider a removal of all the nodes _except_ `zn`. Just when<br /> `tnc_delete()` is about to delete `zroot` and `zp2`:<br /> <br /> zroot<br /> \<br /> \<br /> zp2<br /> \<br /> \<br /> zn<br /> <br /> `zroot` and `zp2` get freed and the tree collapses:<br /> <br /> zn<br /> <br /> `zn` now becomes the new `zroot`.<br /> <br /> `get_znodes_to_commit()` will now only find `zn`, the new `zroot`, and<br /> `write_index()` will check its `znode-&gt;cparent` that wrongly points to<br /> the already freed `zp1`. `ubifs_copy_hash()` thus gets wrongly called<br /> with `znode-&gt;cparent-&gt;zbranch[znode-&gt;iip].hash` that triggers the<br /> use-after-free!<br /> <br /> Fix this by explicitly setting `znode-&gt;cparent` to `NULL` in<br /> `get_znodes_to_commit()` for the root node. The search for the dirty<br /> nodes<br /> ---truncated---

Vulnerable products and versions

CPE From Up to
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 4.20 (including) 5.4.287 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.5 (including) 5.10.231 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.11 (including) 5.15.174 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.16 (including) 6.1.120 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.2 (including) 6.6.64 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.7 (including) 6.11.11 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.12 (including) 6.12.2 (excluding)