In the Linux kernel, a recent vulnerability (CVE-2024-27080) has now been fixed in the Btrfs file system. The vulnerability is related to a race condition when detecting delalloc ranges during the fiemap call. This post will discuss the issue, how it was resolved, and what this means for Linux users.

Background

This vulnerability was introduced in the recent Linux kernel commits, specifically in the Btrfs file system. The issue is a race condition during the fiemap call that may cause delalloc ranges to be missed in some specific cases. This can lead to severe problems, such as data loss.

For instance, coreutils (before version 9.) uses fiemap when calling the cp program to copy files while preserving holes, as with its --sparse command line option. So, if cp encounters a source file having delalloc in a hole, the destination file may miss that data, which is effectively a data loss problem.

Here is how the race condition occurs

1. Fiemap is executed, without the FIEMAP_FLAG_SYNC flag, for a file that has delalloc in the range 64M, 65M[, which is currently a hole;
2. Fiemap locks the inode in the shared mode and starts iterating the inode's subvolume tree, searching for file extent items, without locking the whole fiemap target range in the io tree;
3. Fiemap clones each leaf before using it, to avoid deadlocks when locking a file range in the io tree and the fiemap buffer is memory-mapped;
4. While iterating file extent items in the cloned leaf before identifying the hole in the range [64M, 65M[, the delalloc in that range is flushed, and the ordered extent is completed;
5. When fiemap finds the hole in the [64M, 65M[ range, it will lock that file range in the inode’s io tree and then search for delalloc in the io tree for that range and ordered extents. However, it will find nothing since the delalloc in that range has already been flushed.

For more information and the complete technical details, you can read the Linux kernel mailing list discussion here: [btrfs: fix race when detecting delalloc ranges during fiemap

Restore the lock on the target extent range;

2. Introduce a new map flag (FIEMAP_FLAG_MAYBE_MAPPED) to control whether to clone each leaf when the received buffer appears mapped;

Clone the leaf only if the flag is set;

4. If the leaf is not cloned, lock the target range before checking for delalloc ranges to eliminate the possibility of skipping any delalloc ranges;
5. If the leaf is cloned and the target range is already locked and there’s IO in progress, unlock the target range before cloning the leaf.

With these changes, the race condition has been resolved, and the delalloc ranges can now be detected correctly.

Conclusion

This vulnerability may have affected Linux users running on Btrfs file systems, and it could cause data loss issues in certain situations. With the fix in place, Linux users can now use the system with confidence that delalloc ranges will be handled correctly during fiemap calls.

If you are using an affected Linux kernel version, it is highly recommended to update to the latest version with the vulnerability fix.

Timeline

Published on: 05/01/2024 13:15:51 UTC
Last modified on: 12/19/2024 08:54:00 UTC