CVE-2024-47741
Severity CVSS v4.0:
Pending analysis
Type:
CWE-362
Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')
Publication date:
21/10/2024
Last modified:
23/10/2024
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
btrfs: fix race setting file private on concurrent lseek using same fd<br />
<br />
When doing concurrent lseek(2) system calls against the same file<br />
descriptor, using multiple threads belonging to the same process, we have<br />
a short time window where a race happens and can result in a memory leak.<br />
<br />
The race happens like this:<br />
<br />
1) A program opens a file descriptor for a file and then spawns two<br />
threads (with the pthreads library for example), lets call them<br />
task A and task B;<br />
<br />
2) Task A calls lseek with SEEK_DATA or SEEK_HOLE and ends up at<br />
file.c:find_desired_extent() while holding a read lock on the inode;<br />
<br />
3) At the start of find_desired_extent(), it extracts the file&#39;s<br />
private_data pointer into a local variable named &#39;private&#39;, which has<br />
a value of NULL;<br />
<br />
4) Task B also calls lseek with SEEK_DATA or SEEK_HOLE, locks the inode<br />
in shared mode and enters file.c:find_desired_extent(), where it also<br />
extracts file->private_data into its local variable &#39;private&#39;, which<br />
has a NULL value;<br />
<br />
5) Because it saw a NULL file private, task A allocates a private<br />
structure and assigns to the file structure;<br />
<br />
6) Task B also saw a NULL file private so it also allocates its own file<br />
private and then assigns it to the same file structure, since both<br />
tasks are using the same file descriptor.<br />
<br />
At this point we leak the private structure allocated by task A.<br />
<br />
Besides the memory leak, there&#39;s also the detail that both tasks end up<br />
using the same cached state record in the private structure (struct<br />
btrfs_file_private::llseek_cached_state), which can result in a<br />
use-after-free problem since one task can free it while the other is<br />
still using it (only one task took a reference count on it). Also, sharing<br />
the cached state is not a good idea since it could result in incorrect<br />
results in the future - right now it should not be a problem because it<br />
end ups being used only in extent-io-tree.c:count_range_bits() where we do<br />
range validation before using the cached state.<br />
<br />
Fix this by protecting the private assignment and check of a file while<br />
holding the inode&#39;s spinlock and keep track of the task that allocated<br />
the private, so that it&#39;s used only by that task in order to prevent<br />
user-after-free issues with the cached state record as well as potentially<br />
using it incorrectly in the future.
Impact
Base Score 3.x
7.00
Severity 3.x
HIGH
Vulnerable products and versions
| CPE | From | Up to |
|---|---|---|
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.2 (including) | 6.6.54 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.7 (including) | 6.10.13 (excluding) |
| cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.11 (including) | 6.11.2 (excluding) |
To consult the complete list of CPE names with products and versions, see this page



