CVE-2026-98924 (GCVE-0-2026-98924)
Vulnerability from cvelistv5 – Published: 2026-10-23 12:03 – Updated: 2026-10-23 12:05
VLAI
EPSS
VEX
Title
fs: avoid repeated scans in evict_inodes()
Summary
In the Linux kernel, the following vulnerability has been resolved:
fs: avoid repeated scans in evict_inodes()
We observed hung tasks when users attempted to unmount a filesystem
after its disk had been removed while still in use. During device
removal, fs_bdev_mark_dead() calls evict_inodes() while holding s_umount.
Each time evict_inodes() drops s_inode_list_lock to reschedule, it
restarts the walk from the head of s_inodes. With many referenced inodes
at the head of the list, these restarts repeatedly scan the same inodes
without reclaiming them. This can keep s_umount held for a long time,
blocking concurrent umount attempts and triggering hung-task reports.
Keep the current inode, already marked I_FREEING, out of the disposal
batch until s_inode_list_lock is reacquired. Resume the walk from this
inode and dispose of it in a later batch or at the end of the walk.
The zero-refcount and state checks under i_lock allow this walker to
claim the inode by setting I_FREEING and removing it from the LRU.
Other reclaimers skip the inode, leaving this walker responsible for
eviction. Only evict() removes it from s_inodes, so keeping it out of
the disposal batch ensures that it remains on the list while the lock
is dropped. After reacquiring the lock, reading its current next pointer
accounts for concurrent removal of following inodes.
The existing inode lifetime rules prohibit acquiring a reference to an
inode marked I_FREEING or I_WILL_FREE. __iget() requires its caller to
hold i_lock and establish that taking a reference is valid. Inode lookup
and igrab() check these flags under i_lock when acquiring a reference
from zero. ihold() requires an existing reference, which would keep
i_count nonzero and prevent this walker from claiming the inode. These
rules already allow iput_final() and the inode shrinker to release
i_lock after setting I_FREEING and before eviction completes.
A temporary __iget() reference would also keep the inode on the list,
but its release must preserve last-reference handling. Another user can
acquire a reference, update lazy timestamps and drop its reference while
the pin is held. If the pin becomes the last reference, dropping it with
atomic_dec_and_test() and evicting directly bypasses iput()'s lazytime
handling and can lose those timestamp updates.
Releasing the pin with iput() preserves that handling, but does not
guarantee eviction. fs_bdev_mark_dead() runs with SB_ACTIVE set, so iput()
may retain the inode in cache, whereas evict_inodes() must evict eligible
zero-reference inodes. The inode may also have been freed when iput()
returns, so the walker cannot then use it to force eviction. Using
I_FREEING preserves the existing eviction behavior without introducing
an additional last-reference transition.
The xfstests auto group passed on ext4 and XFS with known unrelated
failures excluded. No new issues were observed, and the previously
reproducible hung task no longer occurs with this patch.
Severity
No CVSS data available.
Assigner
References
Impacted products
2 products
| Vendor | Product | Version | CPE status | |
|---|---|---|---|---|
| Linux | Linux |
Affected:
ac05fbb40062411ea1b722aa2cede7feaa94f1b4 , < e4f3e476cd4066a815ef68cd6caa1828b9c167d5
(git)
Affected: ac05fbb40062411ea1b722aa2cede7feaa94f1b4 , < 3cdc6e12ff79f0f8a3ba62d7e61474ae4b5e119a (git) Affected: ac05fbb40062411ea1b722aa2cede7feaa94f1b4 , < 7459c021874246c196f397686e100702f059b9e7 (git) |
guessed | |
| Linux | Linux |
Affected:
4.3
Unaffected: 0 , < 4.3 (semver) Unaffected: 6.18.55 , ≤ 6.18.* (semver) Unaffected: 7.2.9 , ≤ 7.2.* (semver) Unaffected: 7.3 , ≤ * (original_commit_for_fix) |
guessed |
{
"containers": {
"cna": {
"affected": [
{
"defaultStatus": "unaffected",
"product": "Linux",
"programFiles": [
"fs/inode.c"
],
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"versions": [
{
"lessThan": "e4f3e476cd4066a815ef68cd6caa1828b9c167d5",
"status": "affected",
"version": "ac05fbb40062411ea1b722aa2cede7feaa94f1b4",
"versionType": "git"
},
{
"lessThan": "3cdc6e12ff79f0f8a3ba62d7e61474ae4b5e119a",
"status": "affected",
"version": "ac05fbb40062411ea1b722aa2cede7feaa94f1b4",
"versionType": "git"
},
{
"lessThan": "7459c021874246c196f397686e100702f059b9e7",
"status": "affected",
"version": "ac05fbb40062411ea1b722aa2cede7feaa94f1b4",
"versionType": "git"
}
]
},
{
"defaultStatus": "affected",
"product": "Linux",
"programFiles": [
"fs/inode.c"
],
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"versions": [
{
"status": "affected",
"version": "4.3"
},
{
"lessThan": "4.3",
"status": "unaffected",
"version": "0",
"versionType": "semver"
},
{
"lessThanOrEqual": "6.18.*",
"status": "unaffected",
"version": "6.18.55",
"versionType": "semver"
},
{
"lessThanOrEqual": "7.2.*",
"status": "unaffected",
"version": "7.2.9",
"versionType": "semver"
},
{
"lessThanOrEqual": "*",
"status": "unaffected",
"version": "7.3",
"versionType": "original_commit_for_fix"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionEndExcluding": "6.18.55",
"versionStartIncluding": "4.3",
"vulnerable": true
},
{
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionEndExcluding": "7.2.9",
"versionStartIncluding": "4.3",
"vulnerable": true
},
{
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionEndExcluding": "7.3",
"versionStartIncluding": "4.3",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
]
}
],
"descriptions": [
{
"lang": "en",
"value": "In the Linux kernel, the following vulnerability has been resolved:\n\nfs: avoid repeated scans in evict_inodes()\n\nWe observed hung tasks when users attempted to unmount a filesystem\nafter its disk had been removed while still in use. During device\nremoval, fs_bdev_mark_dead() calls evict_inodes() while holding s_umount.\n\nEach time evict_inodes() drops s_inode_list_lock to reschedule, it\nrestarts the walk from the head of s_inodes. With many referenced inodes\nat the head of the list, these restarts repeatedly scan the same inodes\nwithout reclaiming them. This can keep s_umount held for a long time,\nblocking concurrent umount attempts and triggering hung-task reports.\n\nKeep the current inode, already marked I_FREEING, out of the disposal\nbatch until s_inode_list_lock is reacquired. Resume the walk from this\ninode and dispose of it in a later batch or at the end of the walk.\n\nThe zero-refcount and state checks under i_lock allow this walker to\nclaim the inode by setting I_FREEING and removing it from the LRU.\nOther reclaimers skip the inode, leaving this walker responsible for\neviction. Only evict() removes it from s_inodes, so keeping it out of\nthe disposal batch ensures that it remains on the list while the lock\nis dropped. After reacquiring the lock, reading its current next pointer\naccounts for concurrent removal of following inodes.\n\nThe existing inode lifetime rules prohibit acquiring a reference to an\ninode marked I_FREEING or I_WILL_FREE. __iget() requires its caller to\nhold i_lock and establish that taking a reference is valid. Inode lookup\nand igrab() check these flags under i_lock when acquiring a reference\nfrom zero. ihold() requires an existing reference, which would keep\ni_count nonzero and prevent this walker from claiming the inode. These\nrules already allow iput_final() and the inode shrinker to release\ni_lock after setting I_FREEING and before eviction completes.\n\nA temporary __iget() reference would also keep the inode on the list,\nbut its release must preserve last-reference handling. Another user can\nacquire a reference, update lazy timestamps and drop its reference while\nthe pin is held. If the pin becomes the last reference, dropping it with\natomic_dec_and_test() and evicting directly bypasses iput()\u0027s lazytime\nhandling and can lose those timestamp updates.\n\nReleasing the pin with iput() preserves that handling, but does not\nguarantee eviction. fs_bdev_mark_dead() runs with SB_ACTIVE set, so iput()\nmay retain the inode in cache, whereas evict_inodes() must evict eligible\nzero-reference inodes. The inode may also have been freed when iput()\nreturns, so the walker cannot then use it to force eviction. Using\nI_FREEING preserves the existing eviction behavior without introducing\nan additional last-reference transition.\n\nThe xfstests auto group passed on ext4 and XFS with known unrelated\nfailures excluded. No new issues were observed, and the previously\nreproducible hung task no longer occurs with this patch."
}
],
"providerMetadata": {
"dateUpdated": "2026-10-23T12:05:50.501Z",
"orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"shortName": "Linux"
},
"references": [
{
"url": "https://git.kernel.org/stable/c/e4f3e476cd4066a815ef68cd6caa1828b9c167d5"
},
{
"url": "https://git.kernel.org/stable/c/3cdc6e12ff79f0f8a3ba62d7e61474ae4b5e119a"
},
{
"url": "https://git.kernel.org/stable/c/7459c021874246c196f397686e100702f059b9e7"
}
],
"title": "fs: avoid repeated scans in evict_inodes()",
"x_generator": {
"engine": "bippy-1.2.0"
}
}
},
"cveMetadata": {
"assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"assignerShortName": "Linux",
"cveId": "CVE-2026-98924",
"datePublished": "2026-10-23T12:03:50.230Z",
"dateReserved": "2026-09-25T10:25:14.380Z",
"dateUpdated": "2026-10-23T12:05:50.501Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2",
"vulnerability-lookup:meta": {
"microsoft_vex": {
"current_release_date": "2026-10-24T01:07:52.000Z",
"cve": "CVE-2026-98924",
"id": "msrc_CVE-2026-98924",
"initial_release_date": "2026-10-24T01:07:52.000Z",
"product_status:under_investigation": "1",
"source": "Microsoft CSAF VEX",
"status": "final",
"title": "fs: avoid repeated scans in evict_inodes()",
"url": "https://msrc.microsoft.com/csaf/vex/2026/msrc_cve-2026-98924.json",
"version": "1"
},
"nvd": {
"cve": {
"affected": [
{
"affectedData": [
{
"defaultStatus": "unaffected",
"product": "Linux",
"programFiles": [
"fs/inode.c"
],
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"versions": [
{
"lessThan": "e4f3e476cd4066a815ef68cd6caa1828b9c167d5",
"status": "affected",
"version": "ac05fbb40062411ea1b722aa2cede7feaa94f1b4",
"versionType": "git"
},
{
"lessThan": "3cdc6e12ff79f0f8a3ba62d7e61474ae4b5e119a",
"status": "affected",
"version": "ac05fbb40062411ea1b722aa2cede7feaa94f1b4",
"versionType": "git"
},
{
"lessThan": "7459c021874246c196f397686e100702f059b9e7",
"status": "affected",
"version": "ac05fbb40062411ea1b722aa2cede7feaa94f1b4",
"versionType": "git"
}
]
},
{
"defaultStatus": "affected",
"product": "Linux",
"programFiles": [
"fs/inode.c"
],
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"versions": [
{
"status": "affected",
"version": "4.3"
},
{
"lessThan": "4.3",
"status": "unaffected",
"version": "0",
"versionType": "semver"
},
{
"lessThanOrEqual": "6.18.*",
"status": "unaffected",
"version": "6.18.55",
"versionType": "semver"
},
{
"lessThanOrEqual": "7.2.*",
"status": "unaffected",
"version": "7.2.9",
"versionType": "semver"
},
{
"lessThanOrEqual": "*",
"status": "unaffected",
"version": "7.3",
"versionType": "original_commit_for_fix"
}
]
}
],
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67"
}
],
"cveTags": [],
"descriptions": [
{
"lang": "en",
"value": "In the Linux kernel, the following vulnerability has been resolved:\n\nfs: avoid repeated scans in evict_inodes()\n\nWe observed hung tasks when users attempted to unmount a filesystem\nafter its disk had been removed while still in use. During device\nremoval, fs_bdev_mark_dead() calls evict_inodes() while holding s_umount.\n\nEach time evict_inodes() drops s_inode_list_lock to reschedule, it\nrestarts the walk from the head of s_inodes. With many referenced inodes\nat the head of the list, these restarts repeatedly scan the same inodes\nwithout reclaiming them. This can keep s_umount held for a long time,\nblocking concurrent umount attempts and triggering hung-task reports.\n\nKeep the current inode, already marked I_FREEING, out of the disposal\nbatch until s_inode_list_lock is reacquired. Resume the walk from this\ninode and dispose of it in a later batch or at the end of the walk.\n\nThe zero-refcount and state checks under i_lock allow this walker to\nclaim the inode by setting I_FREEING and removing it from the LRU.\nOther reclaimers skip the inode, leaving this walker responsible for\neviction. Only evict() removes it from s_inodes, so keeping it out of\nthe disposal batch ensures that it remains on the list while the lock\nis dropped. After reacquiring the lock, reading its current next pointer\naccounts for concurrent removal of following inodes.\n\nThe existing inode lifetime rules prohibit acquiring a reference to an\ninode marked I_FREEING or I_WILL_FREE. __iget() requires its caller to\nhold i_lock and establish that taking a reference is valid. Inode lookup\nand igrab() check these flags under i_lock when acquiring a reference\nfrom zero. ihold() requires an existing reference, which would keep\ni_count nonzero and prevent this walker from claiming the inode. These\nrules already allow iput_final() and the inode shrinker to release\ni_lock after setting I_FREEING and before eviction completes.\n\nA temporary __iget() reference would also keep the inode on the list,\nbut its release must preserve last-reference handling. Another user can\nacquire a reference, update lazy timestamps and drop its reference while\nthe pin is held. If the pin becomes the last reference, dropping it with\natomic_dec_and_test() and evicting directly bypasses iput()\u0027s lazytime\nhandling and can lose those timestamp updates.\n\nReleasing the pin with iput() preserves that handling, but does not\nguarantee eviction. fs_bdev_mark_dead() runs with SB_ACTIVE set, so iput()\nmay retain the inode in cache, whereas evict_inodes() must evict eligible\nzero-reference inodes. The inode may also have been freed when iput()\nreturns, so the walker cannot then use it to force eviction. Using\nI_FREEING preserves the existing eviction behavior without introducing\nan additional last-reference transition.\n\nThe xfstests auto group passed on ext4 and XFS with known unrelated\nfailures excluded. No new issues were observed, and the previously\nreproducible hung task no longer occurs with this patch."
}
],
"id": "CVE-2026-98924",
"lastModified": "2026-10-23T13:17:13.083",
"metrics": {},
"published": "2026-10-23T13:17:13.083",
"references": [
{
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"url": "https://git.kernel.org/stable/c/3cdc6e12ff79f0f8a3ba62d7e61474ae4b5e119a"
},
{
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"url": "https://git.kernel.org/stable/c/7459c021874246c196f397686e100702f059b9e7"
},
{
"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"url": "https://git.kernel.org/stable/c/e4f3e476cd4066a815ef68cd6caa1828b9c167d5"
}
],
"sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"vulnStatus": "Received"
}
}
}
}
Loading…
Loading…
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Experimental. This forecast is provided for visualization only and may change without notice. Do not use it for operational decisions.
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
Loading timeline…
Loading…
Loading…
The MITRE ATT&CK techniques below are AI-generated suggestions, inferred from the description of the
vulnerability by the CIRCL/vulnerability-attack-technique-classification-roberta-base
model, served locally by ML-Gateway.
They have not been verified by an analyst and are provided for guidance only.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Loading…
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.