{"api_version":"1","generated_at":"2026-08-02T13:17:00+00:00","cve":"CVE-2025-40303","urls":{"html":"https://cve.report/CVE-2025-40303","api":"https://cve.report/api/cve/CVE-2025-40303.json","docs":"https://cve.report/api","cve_org":"https://www.cve.org/CVERecord?id=CVE-2025-40303","nvd":"https://nvd.nist.gov/vuln/detail/CVE-2025-40303"},"summary":{"title":"btrfs: ensure no dirty metadata is written back for an fs with errors","description":"In the Linux kernel, the following vulnerability has been resolved:\n\nbtrfs: ensure no dirty metadata is written back for an fs with errors\n\n[BUG]\nDuring development of a minor feature (make sure all btrfs_bio::end_io()\nis called in task context), I noticed a crash in generic/388, where\nmetadata writes triggered new works after btrfs_stop_all_workers().\n\nIt turns out that it can even happen without any code modification, just\nusing RAID5 for metadata and the same workload from generic/388 is going\nto trigger the use-after-free.\n\n[CAUSE]\nIf btrfs hits an error, the fs is marked as error, no new\ntransaction is allowed thus metadata is in a frozen state.\n\nBut there are some metadata modifications before that error, and they are\nstill in the btree inode page cache.\n\nSince there will be no real transaction commit, all those dirty folios\nare just kept as is in the page cache, and they can not be invalidated\nby invalidate_inode_pages2() call inside close_ctree(), because they are\ndirty.\n\nAnd finally after btrfs_stop_all_workers(), we call iput() on btree\ninode, which triggers writeback of those dirty metadata.\n\nAnd if the fs is using RAID56 metadata, this will trigger RMW and queue\nnew works into rmw_workers, which is already stopped, causing warning\nfrom queue_work() and use-after-free.\n\n[FIX]\nAdd a special handling for write_one_eb(), that if the fs is already in\nan error state, immediately mark the bbio as failure, instead of really\nsubmitting them.\n\nThen during close_ctree(), iput() will just discard all those dirty\ntree blocks without really writing them back, thus no more new jobs for\nalready stopped-and-freed workqueues.\n\nThe extra discard in write_one_eb() also acts as an extra safenet.\nE.g. the transaction abort is triggered by some extent/free space\ntree corruptions, and since extent/free space tree is already corrupted\nsome tree blocks may be allocated where they shouldn't be (overwriting\nexisting tree blocks). In that case writing them back will further\ncorrupting the fs.","state":"PUBLISHED","assigner":"Linux","published_at":"2025-12-08 01:16:02","updated_at":"2026-07-30 06:24:27"},"problem_types":[],"metrics":[{"version":"3.1","source":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","type":"Secondary","score":"7.8","severity":"HIGH","vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","data":{"version":"3.1","vectorString":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","baseScore":7.8,"baseSeverity":"HIGH","attackVector":"LOCAL","attackComplexity":"LOW","privilegesRequired":"LOW","userInteraction":"NONE","scope":"UNCHANGED","confidentialityImpact":"HIGH","integrityImpact":"HIGH","availabilityImpact":"HIGH"}},{"version":"3.1","source":"CNA","type":"DECLARED","score":"7.8","severity":"HIGH","vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","data":{"baseScore":7.8,"baseSeverity":"HIGH","vectorString":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","version":"3.1"}}],"references":[{"url":"https://git.kernel.org/stable/c/e2b3859067bf012d53c49b3f885fef40624a2c83","name":"https://git.kernel.org/stable/c/e2b3859067bf012d53c49b3f885fef40624a2c83","refsource":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":[],"title":"","mime":"","httpstatus":"","archivestatus":"0"},{"url":"https://git.kernel.org/stable/c/54a5b5a15588e3b0b294df31474d08a2678d4291","name":"https://git.kernel.org/stable/c/54a5b5a15588e3b0b294df31474d08a2678d4291","refsource":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":[],"title":"","mime":"","httpstatus":"","archivestatus":"0"},{"url":"https://git.kernel.org/stable/c/2618849f31e7cf51fadd4a5242458501a6d5b315","name":"https://git.kernel.org/stable/c/2618849f31e7cf51fadd4a5242458501a6d5b315","refsource":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":[],"title":"","mime":"","httpstatus":"","archivestatus":"0"},{"url":"https://git.kernel.org/stable/c/066ee13f05fbd82ada01883e51f0695172f98dff","name":"https://git.kernel.org/stable/c/066ee13f05fbd82ada01883e51f0695172f98dff","refsource":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":[],"title":"","mime":"","httpstatus":"","archivestatus":"0"},{"url":"https://www.cve.org/CVERecord?id=CVE-2025-40303","name":"CVE Program record","refsource":"CVE.ORG","tags":["canonical"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2025-40303","name":"NVD vulnerability detail","refsource":"NVD","tags":["canonical","analysis"]}],"affected":[{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected 13e6c37b989859e70b0d73d3f2cb0aa022159b17 066ee13f05fbd82ada01883e51f0695172f98dff git","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected 13e6c37b989859e70b0d73d3f2cb0aa022159b17 e2b3859067bf012d53c49b3f885fef40624a2c83 git","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected 13e6c37b989859e70b0d73d3f2cb0aa022159b17 54a5b5a15588e3b0b294df31474d08a2678d4291 git","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected 13e6c37b989859e70b0d73d3f2cb0aa022159b17 2618849f31e7cf51fadd4a5242458501a6d5b315 git","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected 3.10","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 3.10 semver","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 6.6.117 6.6.* semver","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 6.12.58 6.12.* semver","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 6.17.8 6.17.* semver","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 6.18 * original_commit_for_fix","platforms":[]}],"timeline":[],"solutions":[],"workarounds":[],"exploits":[],"credits":[],"nvd_cpes":[],"vendor_comments":[],"enrichments":{"kev":null,"epss":{"cve_year":"2025","cve_id":"40303","cve":"CVE-2025-40303","epss":"0.001240000","percentile":"0.025150000","score_date":"2026-07-31","updated_at":"2026-08-01 00:10:35"},"legacy_qids":[]},"source_records":{"cve_program":{"containers":{"cna":{"affected":[{"defaultStatus":"unaffected","product":"Linux","programFiles":["fs/btrfs/extent_io.c"],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","vendor":"Linux","versions":[{"lessThan":"066ee13f05fbd82ada01883e51f0695172f98dff","status":"affected","version":"13e6c37b989859e70b0d73d3f2cb0aa022159b17","versionType":"git"},{"lessThan":"e2b3859067bf012d53c49b3f885fef40624a2c83","status":"affected","version":"13e6c37b989859e70b0d73d3f2cb0aa022159b17","versionType":"git"},{"lessThan":"54a5b5a15588e3b0b294df31474d08a2678d4291","status":"affected","version":"13e6c37b989859e70b0d73d3f2cb0aa022159b17","versionType":"git"},{"lessThan":"2618849f31e7cf51fadd4a5242458501a6d5b315","status":"affected","version":"13e6c37b989859e70b0d73d3f2cb0aa022159b17","versionType":"git"}]},{"defaultStatus":"affected","product":"Linux","programFiles":["fs/btrfs/extent_io.c"],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","vendor":"Linux","versions":[{"status":"affected","version":"3.10"},{"lessThan":"3.10","status":"unaffected","version":"0","versionType":"semver"},{"lessThanOrEqual":"6.6.*","status":"unaffected","version":"6.6.117","versionType":"semver"},{"lessThanOrEqual":"6.12.*","status":"unaffected","version":"6.12.58","versionType":"semver"},{"lessThanOrEqual":"6.17.*","status":"unaffected","version":"6.17.8","versionType":"semver"},{"lessThanOrEqual":"*","status":"unaffected","version":"6.18","versionType":"original_commit_for_fix"}]}],"cpeApplicability":[{"nodes":[{"cpeMatch":[{"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionEndExcluding":"6.6.117","versionStartIncluding":"3.10","vulnerable":true},{"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionEndExcluding":"6.12.58","versionStartIncluding":"3.10","vulnerable":true},{"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionEndExcluding":"6.17.8","versionStartIncluding":"3.10","vulnerable":true},{"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionEndExcluding":"6.18","versionStartIncluding":"3.10","vulnerable":true}],"negate":false,"operator":"OR"}]}],"descriptions":[{"lang":"en","value":"In the Linux kernel, the following vulnerability has been resolved:\n\nbtrfs: ensure no dirty metadata is written back for an fs with errors\n\n[BUG]\nDuring development of a minor feature (make sure all btrfs_bio::end_io()\nis called in task context), I noticed a crash in generic/388, where\nmetadata writes triggered new works after btrfs_stop_all_workers().\n\nIt turns out that it can even happen without any code modification, just\nusing RAID5 for metadata and the same workload from generic/388 is going\nto trigger the use-after-free.\n\n[CAUSE]\nIf btrfs hits an error, the fs is marked as error, no new\ntransaction is allowed thus metadata is in a frozen state.\n\nBut there are some metadata modifications before that error, and they are\nstill in the btree inode page cache.\n\nSince there will be no real transaction commit, all those dirty folios\nare just kept as is in the page cache, and they can not be invalidated\nby invalidate_inode_pages2() call inside close_ctree(), because they are\ndirty.\n\nAnd finally after btrfs_stop_all_workers(), we call iput() on btree\ninode, which triggers writeback of those dirty metadata.\n\nAnd if the fs is using RAID56 metadata, this will trigger RMW and queue\nnew works into rmw_workers, which is already stopped, causing warning\nfrom queue_work() and use-after-free.\n\n[FIX]\nAdd a special handling for write_one_eb(), that if the fs is already in\nan error state, immediately mark the bbio as failure, instead of really\nsubmitting them.\n\nThen during close_ctree(), iput() will just discard all those dirty\ntree blocks without really writing them back, thus no more new jobs for\nalready stopped-and-freed workqueues.\n\nThe extra discard in write_one_eb() also acts as an extra safenet.\nE.g. the transaction abort is triggered by some extent/free space\ntree corruptions, and since extent/free space tree is already corrupted\nsome tree blocks may be allocated where they shouldn't be (overwriting\nexisting tree blocks). In that case writing them back will further\ncorrupting the fs."}],"metrics":[{"cvssV3_1":{"baseScore":7.8,"baseSeverity":"HIGH","vectorString":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","version":"3.1"}}],"providerMetadata":{"dateUpdated":"2026-07-30T06:02:38.299Z","orgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","shortName":"Linux"},"references":[{"url":"https://git.kernel.org/stable/c/066ee13f05fbd82ada01883e51f0695172f98dff"},{"url":"https://git.kernel.org/stable/c/e2b3859067bf012d53c49b3f885fef40624a2c83"},{"url":"https://git.kernel.org/stable/c/54a5b5a15588e3b0b294df31474d08a2678d4291"},{"url":"https://git.kernel.org/stable/c/2618849f31e7cf51fadd4a5242458501a6d5b315"}],"title":"btrfs: ensure no dirty metadata is written back for an fs with errors","x_generator":{"engine":"bippy-1.2.0"}}},"cveMetadata":{"assignerOrgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","assignerShortName":"Linux","cveId":"CVE-2025-40303","datePublished":"2025-12-08T00:46:27.820Z","dateReserved":"2025-04-16T07:20:57.185Z","dateUpdated":"2026-07-30T06:02:38.299Z","state":"PUBLISHED"},"dataType":"CVE_RECORD","dataVersion":"5.2"},"nvd":{"publishedDate":"2025-12-08 01:16:02","lastModifiedDate":"2026-07-30 06:24:27","problem_types":[],"metrics":{"cvssMetricV31":[{"source":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","type":"Secondary","cvssData":{"version":"3.1","vectorString":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","baseScore":7.8,"baseSeverity":"HIGH","attackVector":"LOCAL","attackComplexity":"LOW","privilegesRequired":"LOW","userInteraction":"NONE","scope":"UNCHANGED","confidentialityImpact":"HIGH","integrityImpact":"HIGH","availabilityImpact":"HIGH"},"exploitabilityScore":1.8,"impactScore":5.9}]},"configurations":[]},"legacy_mitre":{"record":{"CveYear":"2025","CveId":"40303","Ordinal":"1","Title":"btrfs: ensure no dirty metadata is written back for an fs with e","CVE":"CVE-2025-40303","Year":"2025"},"notes":[{"CveYear":"2025","CveId":"40303","Ordinal":"1","NoteData":"In the Linux kernel, the following vulnerability has been resolved:\n\nbtrfs: ensure no dirty metadata is written back for an fs with errors\n\n[BUG]\nDuring development of a minor feature (make sure all btrfs_bio::end_io()\nis called in task context), I noticed a crash in generic/388, where\nmetadata writes triggered new works after btrfs_stop_all_workers().\n\nIt turns out that it can even happen without any code modification, just\nusing RAID5 for metadata and the same workload from generic/388 is going\nto trigger the use-after-free.\n\n[CAUSE]\nIf btrfs hits an error, the fs is marked as error, no new\ntransaction is allowed thus metadata is in a frozen state.\n\nBut there are some metadata modifications before that error, and they are\nstill in the btree inode page cache.\n\nSince there will be no real transaction commit, all those dirty folios\nare just kept as is in the page cache, and they can not be invalidated\nby invalidate_inode_pages2() call inside close_ctree(), because they are\ndirty.\n\nAnd finally after btrfs_stop_all_workers(), we call iput() on btree\ninode, which triggers writeback of those dirty metadata.\n\nAnd if the fs is using RAID56 metadata, this will trigger RMW and queue\nnew works into rmw_workers, which is already stopped, causing warning\nfrom queue_work() and use-after-free.\n\n[FIX]\nAdd a special handling for write_one_eb(), that if the fs is already in\nan error state, immediately mark the bbio as failure, instead of really\nsubmitting them.\n\nThen during close_ctree(), iput() will just discard all those dirty\ntree blocks without really writing them back, thus no more new jobs for\nalready stopped-and-freed workqueues.\n\nThe extra discard in write_one_eb() also acts as an extra safenet.\nE.g. the transaction abort is triggered by some extent/free space\ntree corruptions, and since extent/free space tree is already corrupted\nsome tree blocks may be allocated where they shouldn't be (overwriting\nexisting tree blocks). In that case writing them back will further\ncorrupting the fs.","Type":"Description","Title":"btrfs: ensure no dirty metadata is written back for an fs with e"}]}}}