CVE-2021-46989

Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
28/02/2024
Last modified:
14/03/2025

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> hfsplus: prevent corruption in shrinking truncate<br /> <br /> I believe there are some issues introduced by commit 31651c607151<br /> ("hfsplus: avoid deadlock on file truncation")<br /> <br /> HFS+ has extent records which always contains 8 extents. In case the<br /> first extent record in catalog file gets full, new ones are allocated from<br /> extents overflow file.<br /> <br /> In case shrinking truncate happens to middle of an extent record which<br /> locates in extents overflow file, the logic in hfsplus_file_truncate() was<br /> changed so that call to hfs_brec_remove() is not guarded any more.<br /> <br /> Right action would be just freeing the extents that exceed the new size<br /> inside extent record by calling hfsplus_free_extents(), and then check if<br /> the whole extent record should be removed. However since the guard<br /> (blk_cnt &gt; start) is now after the call to hfs_brec_remove(), this has<br /> unfortunate effect that the last matching extent record is removed<br /> unconditionally.<br /> <br /> To reproduce this issue, create a file which has at least 10 extents, and<br /> then perform shrinking truncate into middle of the last extent record, so<br /> that the number of remaining extents is not under or divisible by 8. This<br /> causes the last extent record (8 extents) to be removed totally instead of<br /> truncating into middle of it. Thus this causes corruption, and lost data.<br /> <br /> Fix for this is simply checking if the new truncated end is below the<br /> start of this extent record, making it safe to remove the full extent<br /> record. However call to hfs_brec_remove() can&amp;#39;t be moved to it&amp;#39;s previous<br /> place since we&amp;#39;re dropping -&gt;tree_lock and it can cause a race condition<br /> and the cached info being invalidated possibly corrupting the node data.<br /> <br /> Another issue is related to this one. When entering into the block<br /> (blk_cnt &gt; start) we are not holding the -&gt;tree_lock. We break out from<br /> the loop not holding the lock, but hfs_find_exit() does unlock it. Not<br /> sure if it&amp;#39;s possible for someone else to take the lock under our feet,<br /> but it can cause hard to debug errors and premature unlocking. Even if<br /> there&amp;#39;s no real risk of it, the locking should still always be kept in<br /> balance. Thus taking the lock now just before the check.

Vulnerable products and versions

CPE From Up to
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 4.19 (including) 4.19.191 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 4.20 (including) 5.4.120 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.5 (including) 5.10.38 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.11 (including) 5.11.22 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.12 (including) 5.12.5 (excluding)
cpe:2.3:o:linux:linux_kernel:5.13:rc1:*:*:*:*:*:*