CVE-2024-27080
Severity CVSS v4.0:
Pending analysis
Type:
CWE-362
Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')
Publication date:
01/05/2024
Last modified:
18/09/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
btrfs: fix race when detecting delalloc ranges during fiemap<br />
<br />
For fiemap we recently stopped locking the target extent range for the<br />
whole duration of the fiemap call, in order to avoid a deadlock in a<br />
scenario where the fiemap buffer happens to be a memory mapped range of<br />
the same file. This use case is very unlikely to be useful in practice but<br />
it may be triggered by fuzz testing (syzbot, etc).<br />
<br />
This however introduced a race that makes us miss delalloc ranges for<br />
file regions that are currently holes, so the caller of fiemap will not<br />
be aware that there&#39;s data for some file regions. This can be quite<br />
serious for some use cases - for example in coreutils versions before 9.0,<br />
the cp program used fiemap to detect holes and data in the source file,<br />
copying only regions with data (extents or delalloc) from the source file<br />
to the destination file in order to preserve holes (see the documentation<br />
for its --sparse command line option). This means that if cp was used<br />
with a source file that had delalloc in a hole, the destination file could<br />
end up without that data, which is effectively a data loss issue, if it<br />
happened to hit the race described below.<br />
<br />
The race happens like this:<br />
<br />
1) Fiemap is called, without the FIEMAP_FLAG_SYNC flag, for a file that<br />
has delalloc in the file range [64M, 65M[, which is currently a hole;<br />
<br />
2) Fiemap locks the inode in shared mode, then starts iterating the<br />
inode&#39;s subvolume tree searching for file extent items, without having<br />
the whole fiemap target range locked in the inode&#39;s io tree - the<br />
change introduced recently by commit b0ad381fa769 ("btrfs: fix<br />
deadlock with fiemap and extent locking"). It only locks ranges in<br />
the io tree when it finds a hole or prealloc extent since that<br />
commit;<br />
<br />
3) Note that fiemap clones each leaf before using it, and this is to<br />
avoid deadlocks when locking a file range in the inode&#39;s io tree and<br />
the fiemap buffer is memory mapped to some file, because writing<br />
to the page with btrfs_page_mkwrite() will wait on any ordered extent<br />
for the page&#39;s range and the ordered extent needs to lock the range<br />
and may need to modify the same leaf, therefore leading to a deadlock<br />
on the leaf;<br />
<br />
4) While iterating the file extent items in the cloned leaf before<br />
finding the hole in the range [64M, 65M[, the delalloc in that range<br />
is flushed and its ordered extent completes - meaning the corresponding<br />
file extent item is in the inode&#39;s subvolume tree, but not present in<br />
the cloned leaf that fiemap is iterating over;<br />
<br />
5) When fiemap finds the hole in the [64M, 65M[ range by seeing the gap in<br />
the cloned leaf (or a file extent item with disk_bytenr == 0 in case<br />
the NO_HOLES feature is not enabled), it will lock that file range in<br />
the inode&#39;s io tree and then search for delalloc by checking for the<br />
EXTENT_DELALLOC bit in the io tree for that range and ordered extents<br />
(with btrfs_find_delalloc_in_range()). But it finds nothing since the<br />
delalloc in that range was already flushed and the ordered extent<br />
completed and is gone - as a result fiemap will not report that there&#39;s<br />
delalloc or an extent for the range [64M, 65M[, so user space will be<br />
mislead into thinking that there&#39;s a hole in that range.<br />
<br />
This could actually be sporadically triggered with test case generic/094<br />
from fstests, which reports a missing extent/delalloc range like this:<br />
<br />
generic/094 2s ... - output mismatch (see /home/fdmanana/git/hub/xfstests/results//generic/094.out.bad)<br />
--- tests/generic/094.out 2020-06-10 19:29:03.830519425 +0100<br />
+++ /home/fdmanana/git/hub/xfstests/results//generic/094.out.bad 2024-02-28 11:00:00.381071525 +0000<br />
@@ -1,3 +1,9 @@<br />
QA output created by 094<br />
fiemap run with sync<br />
fiemap run without sync<br />
+ERROR: couldn&#39;t find extent at 7<br />
+map is &#39;HHDDHPPDPHPH&#39;<br />
+logical: [ 5.. 6] phys:<br />
---truncated---
Impact
Base Score 3.x
4.70
Severity 3.x
MEDIUM
Vulnerable products and versions
| CPE | From | Up to |
|---|---|---|
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.6.24 (including) | 6.6.26 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.7.12 (including) | 6.8 (excluding) |
| cpe:2.3:o:linux:linux_kernel:6.8:-:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:6.8:rc6:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:6.8:rc7:*:*:*:*:*:* | ||
| cpe:2.3:o:linux:linux_kernel:6.8.1:*:*:*:*:*:*:* |
To consult the complete list of CPE names with products and versions, see this page
References to Advisories, Solutions, and Tools
- https://git.kernel.org/stable/c/49d640d2946c35a17b051d54171a032dd95b0f50
- https://git.kernel.org/stable/c/978b63f7464abcfd364a6c95f734282c50f3decf
- https://git.kernel.org/stable/c/ced63fffd63072c0ca55d5a451010d71bf08c0b3
- https://git.kernel.org/stable/c/49d640d2946c35a17b051d54171a032dd95b0f50
- https://git.kernel.org/stable/c/978b63f7464abcfd364a6c95f734282c50f3decf
- https://git.kernel.org/stable/c/ced63fffd63072c0ca55d5a451010d71bf08c0b3



