| From bippy-5f407fcff5a0 Mon Sep 17 00:00:00 2001 |
| From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| To: <linux-cve-announce@vger.kernel.org> |
| Reply-to: <cve@kernel.org>, <linux-kernel@vger.kernel.org> |
| Subject: CVE-2024-53171: ubifs: authentication: Fix use-after-free in ubifs_tnc_end_commit |
| |
| Description |
| =========== |
| |
| In the Linux kernel, the following vulnerability has been resolved: |
| |
| ubifs: authentication: Fix use-after-free in ubifs_tnc_end_commit |
| |
| After an insertion in TNC, the tree might split and cause a node to |
| change its `znode->parent`. A further deletion of other nodes in the |
| tree (which also could free the nodes), the aforementioned node's |
| `znode->cparent` could still point to a freed node. This |
| `znode->cparent` may not be updated when getting nodes to commit in |
| `ubifs_tnc_start_commit()`. This could then trigger a use-after-free |
| when accessing the `znode->cparent` in `write_index()` in |
| `ubifs_tnc_end_commit()`. |
| |
| This can be triggered by running |
| |
| rm -f /etc/test-file.bin |
| dd if=/dev/urandom of=/etc/test-file.bin bs=1M count=60 conv=fsync |
| |
| in a loop, and with `CONFIG_UBIFS_FS_AUTHENTICATION`. KASAN then |
| reports: |
| |
| BUG: KASAN: use-after-free in ubifs_tnc_end_commit+0xa5c/0x1950 |
| Write of size 32 at addr ffffff800a3af86c by task ubifs_bgt0_20/153 |
| |
| Call trace: |
| dump_backtrace+0x0/0x340 |
| show_stack+0x18/0x24 |
| dump_stack_lvl+0x9c/0xbc |
| print_address_description.constprop.0+0x74/0x2b0 |
| kasan_report+0x1d8/0x1f0 |
| kasan_check_range+0xf8/0x1a0 |
| memcpy+0x84/0xf4 |
| ubifs_tnc_end_commit+0xa5c/0x1950 |
| do_commit+0x4e0/0x1340 |
| ubifs_bg_thread+0x234/0x2e0 |
| kthread+0x36c/0x410 |
| ret_from_fork+0x10/0x20 |
| |
| Allocated by task 401: |
| kasan_save_stack+0x38/0x70 |
| __kasan_kmalloc+0x8c/0xd0 |
| __kmalloc+0x34c/0x5bc |
| tnc_insert+0x140/0x16a4 |
| ubifs_tnc_add+0x370/0x52c |
| ubifs_jnl_write_data+0x5d8/0x870 |
| do_writepage+0x36c/0x510 |
| ubifs_writepage+0x190/0x4dc |
| __writepage+0x58/0x154 |
| write_cache_pages+0x394/0x830 |
| do_writepages+0x1f0/0x5b0 |
| filemap_fdatawrite_wbc+0x170/0x25c |
| file_write_and_wait_range+0x140/0x190 |
| ubifs_fsync+0xe8/0x290 |
| vfs_fsync_range+0xc0/0x1e4 |
| do_fsync+0x40/0x90 |
| __arm64_sys_fsync+0x34/0x50 |
| invoke_syscall.constprop.0+0xa8/0x260 |
| do_el0_svc+0xc8/0x1f0 |
| el0_svc+0x34/0x70 |
| el0t_64_sync_handler+0x108/0x114 |
| el0t_64_sync+0x1a4/0x1a8 |
| |
| Freed by task 403: |
| kasan_save_stack+0x38/0x70 |
| kasan_set_track+0x28/0x40 |
| kasan_set_free_info+0x28/0x4c |
| __kasan_slab_free+0xd4/0x13c |
| kfree+0xc4/0x3a0 |
| tnc_delete+0x3f4/0xe40 |
| ubifs_tnc_remove_range+0x368/0x73c |
| ubifs_tnc_remove_ino+0x29c/0x2e0 |
| ubifs_jnl_delete_inode+0x150/0x260 |
| ubifs_evict_inode+0x1d4/0x2e4 |
| evict+0x1c8/0x450 |
| iput+0x2a0/0x3c4 |
| do_unlinkat+0x2cc/0x490 |
| __arm64_sys_unlinkat+0x90/0x100 |
| invoke_syscall.constprop.0+0xa8/0x260 |
| do_el0_svc+0xc8/0x1f0 |
| el0_svc+0x34/0x70 |
| el0t_64_sync_handler+0x108/0x114 |
| el0t_64_sync+0x1a4/0x1a8 |
| |
| The offending `memcpy()` in `ubifs_copy_hash()` has a use-after-free |
| when a node becomes root in TNC but still has a `cparent` to an already |
| freed node. More specifically, consider the following TNC: |
| |
| zroot |
| / |
| / |
| zp1 |
| / |
| / |
| zn |
| |
| Inserting a new node `zn_new` with a key smaller then `zn` will trigger |
| a split in `tnc_insert()` if `zp1` is full: |
| |
| zroot |
| / \ |
| / \ |
| zp1 zp2 |
| / \ |
| / \ |
| zn_new zn |
| |
| `zn->parent` has now been moved to `zp2`, *but* `zn->cparent` still |
| points to `zp1`. |
| |
| Now, consider a removal of all the nodes _except_ `zn`. Just when |
| `tnc_delete()` is about to delete `zroot` and `zp2`: |
| |
| zroot |
| \ |
| \ |
| zp2 |
| \ |
| \ |
| zn |
| |
| `zroot` and `zp2` get freed and the tree collapses: |
| |
| zn |
| |
| `zn` now becomes the new `zroot`. |
| |
| `get_znodes_to_commit()` will now only find `zn`, the new `zroot`, and |
| `write_index()` will check its `znode->cparent` that wrongly points to |
| the already freed `zp1`. `ubifs_copy_hash()` thus gets wrongly called |
| with `znode->cparent->zbranch[znode->iip].hash` that triggers the |
| use-after-free! |
| |
| Fix this by explicitly setting `znode->cparent` to `NULL` in |
| `get_znodes_to_commit()` for the root node. The search for the dirty |
| nodes is bottom-up in the tree. Thus, when `find_next_dirty(znode)` |
| returns NULL, the current `znode` _is_ the root node. Add an assert for |
| this. |
| |
| The Linux kernel CVE team has assigned CVE-2024-53171 to this issue. |
| |
| |
| Affected and fixed versions |
| =========================== |
| |
| Issue introduced in 4.20 with commit 16a26b20d2afd0cf063816725b45b12e78d5bb31 and fixed in 5.4.287 with commit daac4aa1825de0dbc1a6eede2fa7f9fc53f14223 |
| Issue introduced in 4.20 with commit 16a26b20d2afd0cf063816725b45b12e78d5bb31 and fixed in 5.10.231 with commit 8d8b3f5f4cbfbf6cb0ea4a4d5dc296872b4151eb |
| Issue introduced in 4.20 with commit 16a26b20d2afd0cf063816725b45b12e78d5bb31 and fixed in 5.15.174 with commit 4d9807048b851d7a58d5bd089c16254af896e4df |
| Issue introduced in 4.20 with commit 16a26b20d2afd0cf063816725b45b12e78d5bb31 and fixed in 6.1.120 with commit 74981f7577d183acad1cd58f74c10d263711a215 |
| Issue introduced in 4.20 with commit 16a26b20d2afd0cf063816725b45b12e78d5bb31 and fixed in 6.6.64 with commit 01d3a2293d7e4edfff96618c15727db7e51f11b6 |
| Issue introduced in 4.20 with commit 16a26b20d2afd0cf063816725b45b12e78d5bb31 and fixed in 6.11.11 with commit 398a91599d263e41c5f95a2fd4ebdb6280b5c6c3 |
| Issue introduced in 4.20 with commit 16a26b20d2afd0cf063816725b45b12e78d5bb31 and fixed in 6.12.2 with commit 2497479aecebe869d23a0064e0fd1a03e34f0e2a |
| Issue introduced in 4.20 with commit 16a26b20d2afd0cf063816725b45b12e78d5bb31 and fixed in 6.13 with commit 4617fb8fc15effe8eda4dd898d4e33eb537a7140 |
| |
| Please see https://www.kernel.org for a full list of currently supported |
| kernel versions by the kernel community. |
| |
| Unaffected versions might change over time as fixes are backported to |
| older supported kernel versions. The official CVE entry at |
| https://cve.org/CVERecord/?id=CVE-2024-53171 |
| will be updated if fixes are backported, please check that for the most |
| up to date information about this issue. |
| |
| |
| Affected files |
| ============== |
| |
| The file(s) affected by this issue are: |
| fs/ubifs/tnc_commit.c |
| |
| |
| Mitigation |
| ========== |
| |
| The Linux kernel CVE team recommends that you update to the latest |
| stable kernel version for this, and many other bugfixes. Individual |
| changes are never tested alone, but rather are part of a larger kernel |
| release. Cherry-picking individual commits is not recommended or |
| supported by the Linux kernel community at all. If however, updating to |
| the latest release is impossible, the individual changes to resolve this |
| issue can be found at these commits: |
| https://git.kernel.org/stable/c/daac4aa1825de0dbc1a6eede2fa7f9fc53f14223 |
| https://git.kernel.org/stable/c/8d8b3f5f4cbfbf6cb0ea4a4d5dc296872b4151eb |
| https://git.kernel.org/stable/c/4d9807048b851d7a58d5bd089c16254af896e4df |
| https://git.kernel.org/stable/c/74981f7577d183acad1cd58f74c10d263711a215 |
| https://git.kernel.org/stable/c/01d3a2293d7e4edfff96618c15727db7e51f11b6 |
| https://git.kernel.org/stable/c/398a91599d263e41c5f95a2fd4ebdb6280b5c6c3 |
| https://git.kernel.org/stable/c/2497479aecebe869d23a0064e0fd1a03e34f0e2a |
| https://git.kernel.org/stable/c/4617fb8fc15effe8eda4dd898d4e33eb537a7140 |