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