In the Linux kernel, the following vulnerability has been resolved:
vfs: fix race between eviceinodes() and findinode()&iput()
Hi, all
Recently I noticed a bug[1] in btrfs, after digged it into and I believe it'a race in vfs.
Let's assume there's a inode (ie ino 261) with icount 1 is called by iput(), and there's a concurrent thread calling genericshutdown_super().
cpu0: cpu1: iput() // icount is 1 ->spinlock(inode) ->dec icount to 0 ->iputfinal() genericshutdownsuper() ->_inodeaddlru() ->evictinodes() // cause some reason[2] ->if (atomicread(inode->icount)) continue; // return before // inode 261 passed the above check // listlruaddobj() // and then schedule out ->spinunlock() // note here: the inode 261 // was still at sb list and hash list, // and IFREEING|IWILL_FREE was not been set
btrfsiget() // after some function calls ->findinode() // found the above inode 261 ->spinlock(inode) // check IFREEING|IWILLFREE // and passed ->_iget() ->spinunlock(inode) // schedule back ->spinlock(inode) // check (INEW|IFREEING|IWILLFREE) flags, // passed and set IFREEING iput() ->spinunlock(inode) ->spinlock(inode) ->evict() // dec icount to 0 ->iputfinal() ->spin_unlock() ->evict()
Now, we have two threads simultaneously evicting the same inode, which may trigger the BUG(inode->istate & ICLEAR) statement both within clear_inode() and iput().
To fix the bug, recheck the inode->icount after holding ilock. Because in the most scenarios, the first check is valid, and the overhead of spin_lock() can be reduced.
If there is any misunderstanding, please let me know, thanks.
return false when I reproduced the bug.
[
{
"signature_type": "Line",
"target": {
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-163e3b05",
"digest": {
"threshold": 0.9,
"line_hashes": [
"88443806174920730646312650460005680236",
"215694799066216304590137008200684462029",
"184136748470220505790477323569397954237",
"261287184064076834310398286224845062081"
]
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@88b1afbf0f6b221f6c5bb66cc80cd3b38d696687",
"deprecated": false
},
{
"signature_type": "Function",
"target": {
"function": "evict_inodes",
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-1b62c135",
"digest": {
"function_hash": "152612230714229384351673534117233558358",
"length": 707.0
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@0eed942bc65de1f93eca7bda51344290f9c573bb",
"deprecated": false
},
{
"signature_type": "Function",
"target": {
"function": "evict_inodes",
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-200e793d",
"digest": {
"function_hash": "152612230714229384351673534117233558358",
"length": 707.0
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@6c857fb12b9137fee574443385d53914356bbe11",
"deprecated": false
},
{
"signature_type": "Line",
"target": {
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-259b9b15",
"digest": {
"threshold": 0.9,
"line_hashes": [
"88443806174920730646312650460005680236",
"215694799066216304590137008200684462029",
"184136748470220505790477323569397954237",
"261287184064076834310398286224845062081"
]
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@6c857fb12b9137fee574443385d53914356bbe11",
"deprecated": false
},
{
"signature_type": "Line",
"target": {
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-30e12793",
"digest": {
"threshold": 0.9,
"line_hashes": [
"88443806174920730646312650460005680236",
"215694799066216304590137008200684462029",
"184136748470220505790477323569397954237",
"261287184064076834310398286224845062081"
]
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@3721a69403291e2514d13a7c3af50a006ea1153b",
"deprecated": false
},
{
"signature_type": "Function",
"target": {
"function": "evict_inodes",
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-4d40eef3",
"digest": {
"function_hash": "152612230714229384351673534117233558358",
"length": 707.0
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@3721a69403291e2514d13a7c3af50a006ea1153b",
"deprecated": false
},
{
"signature_type": "Line",
"target": {
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-4fb5b4d3",
"digest": {
"threshold": 0.9,
"line_hashes": [
"88443806174920730646312650460005680236",
"215694799066216304590137008200684462029",
"184136748470220505790477323569397954237",
"261287184064076834310398286224845062081"
]
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@6cc13a80a26e6b48f78c725c01b91987d61563ef",
"deprecated": false
},
{
"signature_type": "Function",
"target": {
"function": "evict_inodes",
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-5f07327d",
"digest": {
"function_hash": "152612230714229384351673534117233558358",
"length": 707.0
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@489faddb1ae75b0e1a741fe5ca2542a2b5e794a5",
"deprecated": false
},
{
"signature_type": "Line",
"target": {
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-6c3611c9",
"digest": {
"threshold": 0.9,
"line_hashes": [
"88443806174920730646312650460005680236",
"215694799066216304590137008200684462029",
"184136748470220505790477323569397954237",
"261287184064076834310398286224845062081"
]
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@0eed942bc65de1f93eca7bda51344290f9c573bb",
"deprecated": false
},
{
"signature_type": "Line",
"target": {
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-976701e9",
"digest": {
"threshold": 0.9,
"line_hashes": [
"88443806174920730646312650460005680236",
"215694799066216304590137008200684462029",
"184136748470220505790477323569397954237",
"261287184064076834310398286224845062081"
]
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@0f8a5b6d0dafa4f533ac82e98f8b812073a7c9d1",
"deprecated": false
},
{
"signature_type": "Line",
"target": {
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-a7d8427c",
"digest": {
"threshold": 0.9,
"line_hashes": [
"88443806174920730646312650460005680236",
"215694799066216304590137008200684462029",
"184136748470220505790477323569397954237",
"261287184064076834310398286224845062081"
]
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@540fb13120c9eab3ef203f90c00c8e69f37449d1",
"deprecated": false
},
{
"signature_type": "Function",
"target": {
"function": "evict_inodes",
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-b10a867d",
"digest": {
"function_hash": "152612230714229384351673534117233558358",
"length": 707.0
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@540fb13120c9eab3ef203f90c00c8e69f37449d1",
"deprecated": false
},
{
"signature_type": "Function",
"target": {
"function": "evict_inodes",
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-b553bdc9",
"digest": {
"function_hash": "152612230714229384351673534117233558358",
"length": 707.0
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@6cc13a80a26e6b48f78c725c01b91987d61563ef",
"deprecated": false
},
{
"signature_type": "Function",
"target": {
"function": "evict_inodes",
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-bbbfa487",
"digest": {
"function_hash": "152612230714229384351673534117233558358",
"length": 707.0
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@47a68c75052a660e4c37de41e321582ec9496195",
"deprecated": false
},
{
"signature_type": "Line",
"target": {
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-be11cd79",
"digest": {
"threshold": 0.9,
"line_hashes": [
"88443806174920730646312650460005680236",
"215694799066216304590137008200684462029",
"184136748470220505790477323569397954237",
"261287184064076834310398286224845062081"
]
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@489faddb1ae75b0e1a741fe5ca2542a2b5e794a5",
"deprecated": false
},
{
"signature_type": "Function",
"target": {
"function": "evict_inodes",
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-d0912c90",
"digest": {
"function_hash": "152612230714229384351673534117233558358",
"length": 707.0
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@88b1afbf0f6b221f6c5bb66cc80cd3b38d696687",
"deprecated": false
},
{
"signature_type": "Line",
"target": {
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-e3b17aa8",
"digest": {
"threshold": 0.9,
"line_hashes": [
"88443806174920730646312650460005680236",
"215694799066216304590137008200684462029",
"184136748470220505790477323569397954237",
"261287184064076834310398286224845062081"
]
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@47a68c75052a660e4c37de41e321582ec9496195",
"deprecated": false
},
{
"signature_type": "Function",
"target": {
"function": "evict_inodes",
"file": "fs/inode.c"
},
"id": "CVE-2024-47679-e77c4518",
"digest": {
"function_hash": "152612230714229384351673534117233558358",
"length": 707.0
},
"signature_version": "v1",
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@0f8a5b6d0dafa4f533ac82e98f8b812073a7c9d1",
"deprecated": false
}
]