blob: c540de6f2e5f38ba08ccd0401616f3e99751e54a [file] [log] [blame]
{
"containers": {
"cna": {
"providerMetadata": {
"orgId": "f4215fc3-5b6b-47ff-a258-f7189bd81038"
},
"descriptions": [
{
"lang": "en",
"value": "In the Linux kernel, the following vulnerability has been resolved:\n\niommu/vt-d: Fix potential lockup if qi_submit_sync called with 0 count\n\nIf qi_submit_sync() is invoked with 0 invalidation descriptors (for\ninstance, for DMA draining purposes), we can run into a bug where a\nsubmitting thread fails to detect the completion of invalidation_wait.\nSubsequently, this led to a soft lockup. Currently, there is no impact\nby this bug on the existing users because no callers are submitting\ninvalidations with 0 descriptors. This fix will enable future users\n(such as DMA drain) calling qi_submit_sync() with 0 count.\n\nSuppose thread T1 invokes qi_submit_sync() with non-zero descriptors, while\nconcurrently, thread T2 calls qi_submit_sync() with zero descriptors. Both\nthreads then enter a while loop, waiting for their respective descriptors\nto complete. T1 detects its completion (i.e., T1's invalidation_wait status\nchanges to QI_DONE by HW) and proceeds to call reclaim_free_desc() to\nreclaim all descriptors, potentially including adjacent ones of other\nthreads that are also marked as QI_DONE.\n\nDuring this time, while T2 is waiting to acquire the qi->q_lock, the IOMMU\nhardware may complete the invalidation for T2, setting its status to\nQI_DONE. However, if T1's execution of reclaim_free_desc() frees T2's\ninvalidation_wait descriptor and changes its status to QI_FREE, T2 will\nnot observe the QI_DONE status for its invalidation_wait and will\nindefinitely remain stuck.\n\nThis soft lockup does not occur when only non-zero descriptors are\nsubmitted.In such cases, invalidation descriptors are interspersed among\nwait descriptors with the status QI_IN_USE, acting as barriers. These\nbarriers prevent the reclaim code from mistakenly freeing descriptors\nbelonging to other submitters.\n\nConsidered the following example timeline:\n\tT1\t\t\tT2\n========================================\n\tID1\n\tWD1\n\twhile(WD1!=QI_DONE)\n\tunlock\n\t\t\t\tlock\n\tWD1=QI_DONE*\t\tWD2\n\t\t\t\twhile(WD2!=QI_DONE)\n\t\t\t\tunlock\n\tlock\n\tWD1==QI_DONE?\n\tID1=QI_DONE\t\tWD2=DONE*\n\treclaim()\n\tID1=FREE\n\tWD1=FREE\n\tWD2=FREE\n\tunlock\n\t\t\t\tsoft lockup! T2 never sees QI_DONE in WD2\n\nWhere:\nID = invalidation descriptor\nWD = wait descriptor\n* Written by hardware\n\nThe root of the problem is that the descriptor status QI_DONE flag is used\nfor two conflicting purposes:\n1. signal a descriptor is ready for reclaim (to be freed)\n2. signal by the hardware that a wait descriptor is complete\n\nThe solution (in this patch) is state separation by using QI_FREE flag\nfor #1.\n\nOnce a thread's invalidation descriptors are complete, their status would\nbe set to QI_FREE. The reclaim_free_desc() function would then only\nfree descriptors marked as QI_FREE instead of those marked as\nQI_DONE. This change ensures that T2 (from the previous example) will\ncorrectly observe the completion of its invalidation_wait (marked as\nQI_DONE)."
}
],
"affected": [
{
"product": "Linux",
"vendor": "Linux",
"defaultStatus": "unaffected",
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"programFiles": [
"drivers/iommu/intel/dmar.c"
],
"versions": [
{
"version": "1da177e4c3f4",
"lessThan": "de9e7f687625",
"status": "affected",
"versionType": "git"
},
{
"version": "1da177e4c3f4",
"lessThan": "8840dc73ac9e",
"status": "affected",
"versionType": "git"
},
{
"version": "1da177e4c3f4",
"lessThan": "e03f00aa4a6c",
"status": "affected",
"versionType": "git"
},
{
"version": "1da177e4c3f4",
"lessThan": "dfdbc5ba10fb",
"status": "affected",
"versionType": "git"
},
{
"version": "1da177e4c3f4",
"lessThan": "07e4e92f84b7",
"status": "affected",
"versionType": "git"
},
{
"version": "1da177e4c3f4",
"lessThan": "92ba5b014d54",
"status": "affected",
"versionType": "git"
},
{
"version": "1da177e4c3f4",
"lessThan": "3cf74230c139",
"status": "affected",
"versionType": "git"
}
]
},
{
"product": "Linux",
"vendor": "Linux",
"defaultStatus": "affected",
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"programFiles": [
"drivers/iommu/intel/dmar.c"
],
"versions": [
{
"version": "5.10.227",
"lessThanOrEqual": "5.10.*",
"status": "unaffected",
"versionType": "semver"
},
{
"version": "5.15.168",
"lessThanOrEqual": "5.15.*",
"status": "unaffected",
"versionType": "semver"
},
{
"version": "6.1.113",
"lessThanOrEqual": "6.1.*",
"status": "unaffected",
"versionType": "semver"
},
{
"version": "6.6.55",
"lessThanOrEqual": "6.6.*",
"status": "unaffected",
"versionType": "semver"
},
{
"version": "6.10.14",
"lessThanOrEqual": "6.10.*",
"status": "unaffected",
"versionType": "semver"
},
{
"version": "6.11.3",
"lessThanOrEqual": "6.11.*",
"status": "unaffected",
"versionType": "semver"
},
{
"version": "6.12-rc1",
"lessThanOrEqual": "*",
"status": "unaffected",
"versionType": "original_commit_for_fix"
}
]
}
],
"references": [
{
"url": "https://git.kernel.org/stable/c/de9e7f68762585f7532de8a06de9485bf39dbd38"
},
{
"url": "https://git.kernel.org/stable/c/8840dc73ac9e1028291458ef1429ec3c2524ffec"
},
{
"url": "https://git.kernel.org/stable/c/e03f00aa4a6c0c49c17857a4048f586636abdc32"
},
{
"url": "https://git.kernel.org/stable/c/dfdbc5ba10fb792c9d6d12ba8cb6e465f97365ed"
},
{
"url": "https://git.kernel.org/stable/c/07e4e92f84b7d3018b7064ef8d8438aeb54a2ca5"
},
{
"url": "https://git.kernel.org/stable/c/92ba5b014d5435dd7a1ee02a2c7f2a0e8fe06c36"
},
{
"url": "https://git.kernel.org/stable/c/3cf74230c139f208b7fb313ae0054386eee31a81"
}
],
"title": "iommu/vt-d: Fix potential lockup if qi_submit_sync called with 0 count",
"x_generator": {
"engine": "bippy-9e1c9544281a"
}
}
},
"cveMetadata": {
"assignerOrgId": "f4215fc3-5b6b-47ff-a258-f7189bd81038",
"cveID": "CVE-2024-49993",
"requesterUserId": "gregkh@kernel.org",
"serial": "1",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.0"
}