CVE-2024-47679

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:
03/11/2025

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> vfs: fix race between evice_inodes() and find_inode()&amp;iput()<br /> <br /> Hi, all<br /> <br /> Recently I noticed a bug[1] in btrfs, after digged it into<br /> and I believe it&amp;#39;a race in vfs.<br /> <br /> Let&amp;#39;s assume there&amp;#39;s a inode (ie ino 261) with i_count 1 is<br /> called by iput(), and there&amp;#39;s a concurrent thread calling<br /> generic_shutdown_super().<br /> <br /> cpu0: cpu1:<br /> iput() // i_count is 1<br /> -&gt;spin_lock(inode)<br /> -&gt;dec i_count to 0<br /> -&gt;iput_final() generic_shutdown_super()<br /> -&gt;__inode_add_lru() -&gt;evict_inodes()<br /> // cause some reason[2] -&gt;if (atomic_read(inode-&gt;i_count)) continue;<br /> // return before // inode 261 passed the above check<br /> // list_lru_add_obj() // and then schedule out<br /> -&gt;spin_unlock()<br /> // note here: the inode 261<br /> // was still at sb list and hash list,<br /> // and I_FREEING|I_WILL_FREE was not been set<br /> <br /> btrfs_iget()<br /> // after some function calls<br /> -&gt;find_inode()<br /> // found the above inode 261<br /> -&gt;spin_lock(inode)<br /> // check I_FREEING|I_WILL_FREE<br /> // and passed<br /> -&gt;__iget()<br /> -&gt;spin_unlock(inode) // schedule back<br /> -&gt;spin_lock(inode)<br /> // check (I_NEW|I_FREEING|I_WILL_FREE) flags,<br /> // passed and set I_FREEING<br /> iput() -&gt;spin_unlock(inode)<br /> -&gt;spin_lock(inode) -&gt;evict()<br /> // dec i_count to 0<br /> -&gt;iput_final()<br /> -&gt;spin_unlock()<br /> -&gt;evict()<br /> <br /> Now, we have two threads simultaneously evicting<br /> the same inode, which may trigger the BUG(inode-&gt;i_state &amp; I_CLEAR)<br /> statement both within clear_inode() and iput().<br /> <br /> To fix the bug, recheck the inode-&gt;i_count after holding i_lock.<br /> Because in the most scenarios, the first check is valid, and<br /> the overhead of spin_lock() can be reduced.<br /> <br /> If there is any misunderstanding, please let me know, thanks.<br /> <br /> [1]: https://lore.kernel.org/linux-btrfs/000000000000eabe1d0619c48986@google.com/<br /> [2]: The reason might be 1. SB_ACTIVE was removed or 2. mapping_shrinkable()<br /> return false when I reproduced the bug.

Vulnerable products and versions

CPE From Up to
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 2.6.37 (including) 5.10.227 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.11 (including) 5.15.168 (excluding)
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.16 (including) 6.1.113 (excluding)
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)