CVE-2026-74568 (GCVE-0-2026-74568)

Vulnerability from cvelistv5 – Published: 2026-08-15 12:28 – Updated: 2026-08-17 05:48
VLAI
Title
KVM: arm64: vgic: Fix race between LPI release and re-registration
Summary
In the Linux kernel, the following vulnerability has been resolved: KVM: arm64: vgic: Fix race between LPI release and re-registration Fix a potential race between decrementing an LPI's reference count and evicting that structure from the LPI xarray. LPI structures are maintained in the VGIC LPI xarray (dist->lpi_xa). When the reference count of an LPI structure drops to zero, vgic_release_lpi_locked() removes the structure from the xarray and frees it under the xarray lock. However, the release of an LPI can race with a concurrent LPI re-registration with the same INTID via vgic_add_lpi() on another CPU, since the reference count drop and the xarray eviction are not performed in a single atomic step. This can happen e.g. if the guest issues a DISCARD while the LPI is still referenced from a vCPU's active-pending list (ap_list), and the same INTID is re-mapped via MAPTI. Particularly, vgic_release_lpi_locked() is called from two distinct paths: direct release via vgic_put_irq(), and deferred release via vgic_release_deleted_lpis(). During direct release, the issue can result in deleting a newly registered LPI from the xarray: CPU0 (Releasing LPI) CPU1 (Adding new LPI) ==================== ===================== vgic_put_irq() __vgic_put_irq() refcount_dec_and_test() vgic_add_lpi() xa_lock_irqsave() old_irq = xa_load(.., intid) vgic_try_get_irq_ref(old_irq) == false new IRQ inserted --> __xa_store(.., intid, ..) xa_unlock_irqrestore() xa_lock_irqsave(); vgic_release_lpi_locked() __xa_erase(.., irq->intid) <-- BUG: new IRQ is erased kfree_rcu(old_irq) During the deferred release path, the old IRQ can be leaked: CPU0 (Releasing LPI) CPU1 (Adding new LPI) ==================== ===================== vgic_put_irq_norelease() __vgic_put_irq() refcount_dec_and_test() irq->pending_release = true vgic_add_lpi() xa_lock_irqsave() old_irq = xa_load(.., intid) vgic_try_get_irq_ref(oldirq) == false BUG: old IRQ overwritten --> __xa_store(.., intid, ..) xa_unlock_irqrestore() vgic_release_deleted_lpis() xa_lock_irqsave() xa_for_each() { .. } <-- old IRQ with pending_release = true is gone, so it cannot be released To fix the direct release path, move the reference count drop inside the xarray lock, making sure that vgic_add_lpi() never encounters the to-be-released LPI. In the deferred release path, the refcount drop must happen under a raw spinlock, so the xarray lock cannot be grabbed, and the same solution does not work. Instead, update vgic_add_lpi(), so that if it evicts an LPI from the xarray, it takes on the responsibility of freeing it. Consequently, an LPI may now be freed concurrently after a deferred release drops the refcount, so accessing the pending_release field is no longer safe from use-after-free. Delete all uses of the flag, and update vgic_release_deleted_lpis() to identify orphaned LPIs purely based on their refcount.
Impacted products
Vendor Product Version CPE status
Linux Linux Affected: 3a08a6ca7c373198c84e2a8c025c395ee966ff8a , < 292e80a159aa88635bf668a7212cfdf526b8bd52 (git)
Affected: 3a08a6ca7c373198c84e2a8c025c395ee966ff8a , < cbfe2b24a1ea9de35032dbdd100fdc700f5be92d (git)
guessed Create a notification for this product.
Linux Linux Affected: 6.17
Unaffected: 0 , < 6.17 (semver)
Unaffected: 7.1.8 , ≤ 7.1.* (semver)
Unaffected: 7.2 , ≤ * (original_commit_for_fix)
guessed Create a notification for this product.
Show details on NVD website

{
  "containers": {
    "cna": {
      "affected": [
        {
          "defaultStatus": "unaffected",
          "product": "Linux",
          "programFiles": [
            "arch/arm64/kvm/vgic/vgic-its.c",
            "arch/arm64/kvm/vgic/vgic.c",
            "include/kvm/arm_vgic.h"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "lessThan": "292e80a159aa88635bf668a7212cfdf526b8bd52",
              "status": "affected",
              "version": "3a08a6ca7c373198c84e2a8c025c395ee966ff8a",
              "versionType": "git"
            },
            {
              "lessThan": "cbfe2b24a1ea9de35032dbdd100fdc700f5be92d",
              "status": "affected",
              "version": "3a08a6ca7c373198c84e2a8c025c395ee966ff8a",
              "versionType": "git"
            }
          ]
        },
        {
          "defaultStatus": "affected",
          "product": "Linux",
          "programFiles": [
            "arch/arm64/kvm/vgic/vgic-its.c",
            "arch/arm64/kvm/vgic/vgic.c",
            "include/kvm/arm_vgic.h"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "status": "affected",
              "version": "6.17"
            },
            {
              "lessThan": "6.17",
              "status": "unaffected",
              "version": "0",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "7.1.*",
              "status": "unaffected",
              "version": "7.1.8",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "*",
              "status": "unaffected",
              "version": "7.2",
              "versionType": "original_commit_for_fix"
            }
          ]
        }
      ],
      "cpeApplicability": [
        {
          "nodes": [
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "7.1.8",
                  "versionStartIncluding": "6.17",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "7.2",
                  "versionStartIncluding": "6.17",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "OR"
            }
          ]
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nKVM: arm64: vgic: Fix race between LPI release and re-registration\n\nFix a potential race between decrementing an LPI\u0027s reference count and\nevicting that structure from the LPI xarray.\n\nLPI structures are maintained in the VGIC LPI xarray (dist-\u003elpi_xa).\nWhen the reference count of an LPI structure drops to zero,\nvgic_release_lpi_locked() removes the structure from the xarray and\nfrees it under the xarray lock.\n\nHowever, the release of an LPI can race with a concurrent LPI\nre-registration with the same INTID via vgic_add_lpi() on another CPU,\nsince the reference count drop and the xarray eviction are not performed\nin a single atomic step. This can happen e.g. if the guest issues a\nDISCARD while the LPI is still referenced from a vCPU\u0027s active-pending\nlist (ap_list), and the same INTID is re-mapped via MAPTI.\n\nParticularly, vgic_release_lpi_locked() is called from two distinct\npaths: direct release via vgic_put_irq(), and deferred release via\nvgic_release_deleted_lpis(). During direct release, the issue can result\nin deleting a newly registered LPI from the xarray:\n\n  CPU0 (Releasing LPI)                    CPU1 (Adding new LPI)\n  ====================                    =====================\n  vgic_put_irq()\n      __vgic_put_irq()\n          refcount_dec_and_test()\n                                          vgic_add_lpi()\n                                              xa_lock_irqsave()\n                                              old_irq = xa_load(.., intid)\n                                              vgic_try_get_irq_ref(old_irq) == false\n                        new IRQ inserted --\u003e  __xa_store(.., intid, ..)\n                                              xa_unlock_irqrestore()\n  xa_lock_irqsave();\n  vgic_release_lpi_locked()\n      __xa_erase(.., irq-\u003eintid)   \u003c-- BUG: new IRQ is erased\n      kfree_rcu(old_irq)\n\nDuring the deferred release path, the old IRQ can be leaked:\n\n  CPU0 (Releasing LPI)                    CPU1 (Adding new LPI)\n  ====================                    =====================\n  vgic_put_irq_norelease()\n      __vgic_put_irq()\n          refcount_dec_and_test()\n      irq-\u003epending_release = true\n                                          vgic_add_lpi()\n                                              xa_lock_irqsave()\n                                              old_irq = xa_load(.., intid)\n                                              vgic_try_get_irq_ref(oldirq) == false\n                 BUG: old IRQ overwritten --\u003e __xa_store(.., intid, ..)\n                                              xa_unlock_irqrestore()\n\n  vgic_release_deleted_lpis()\n      xa_lock_irqsave()\n      xa_for_each() { .. } \u003c-- old IRQ with pending_release = true\n                               is gone, so it cannot be released\n\nTo fix the direct release path, move the reference count drop inside\nthe xarray lock, making sure that vgic_add_lpi() never encounters the\nto-be-released LPI.\n\nIn the deferred release path, the refcount drop must happen under a raw\nspinlock, so the xarray lock cannot be grabbed, and the same solution\ndoes not work. Instead, update vgic_add_lpi(), so that if it evicts\nan LPI from the xarray, it takes on the responsibility of freeing it.\nConsequently, an LPI may now be freed concurrently after a deferred\nrelease drops the refcount, so accessing the pending_release field is no\nlonger safe from use-after-free. Delete all uses of the flag, and update\nvgic_release_deleted_lpis() to identify orphaned LPIs purely based on\ntheir refcount."
        }
      ],
      "metrics": [
        {
          "cvssV3_1": {
            "baseScore": 9.3,
            "baseSeverity": "CRITICAL",
            "vectorString": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
            "version": "3.1"
          },
          "scenarios": [
            {
              "lang": "en",
              "value": "AV:L - The bug is reached when a malicious KVM guest writes emulated GICv3 ITS MMIO (GITS_CWRITER), processing DISCARD/MAPTI commands that call vgic_add_lpi() and vgic_put_irq(); this requires guest code execution on the host, not remote network input.\nAC:L - The race is guest-driven and repeatable: a malicious guest can keep an LPI referenced on a vCPU ap_list, issue DISCARD, and concurrently re-map the same INTID via MAPTI across vCPUs, controlling both sides of the refcount/xarray race.\nPR:N - Exploitation requires only code inside a KVM guest on an arm64 host with VGICv3 ITS/LPI (common on cloud ARM servers); no host root, CAP_SYS_ADMIN, or other elevated host privileges are needed beyond normal VM tenancy.\nUI:N - No victim interaction is required; the attacker fully controls guest ITS command submission, interrupt injection, and multi-vCPU timing from within the VM.\nS:C - Corrupting host-kernel VGIC LPI objects (lpi_xa entries, vgic_irq structures) from guest MMIO crosses the KVM virtual-machine security boundary and can enable guest-to-host escape.\nC:H - The race can erase a newly registered LPI while freeing the old one, leaving stale host pointers (ite-\u003eirq, ap_list) to freed vgic_irq objects; this use-after-free enables arbitrary host kernel memory disclosure via heap reuse.\nI:H - Host heap corruption of vgic_irq structures and xarray state from the race provides use-after-free write primitives that can be leveraged for arbitrary host kernel modification and VM escape code execution.\nA:H - The bug can cause host kernel crashes (oops/panic) from freeing live LPIs, orphaned IRQ state, and use-after-free during concurrent VGIC interrupt handling on multiple vCPUs."
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-08-17T05:48:47.432Z",
        "orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
        "shortName": "Linux"
      },
      "references": [
        {
          "url": "https://git.kernel.org/stable/c/292e80a159aa88635bf668a7212cfdf526b8bd52"
        },
        {
          "url": "https://git.kernel.org/stable/c/cbfe2b24a1ea9de35032dbdd100fdc700f5be92d"
        }
      ],
      "title": "KVM: arm64: vgic: Fix race between LPI release and re-registration",
      "x_generator": {
        "engine": "bippy-1.2.0"
      }
    }
  },
  "cveMetadata": {
    "assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
    "assignerShortName": "Linux",
    "cveId": "CVE-2026-74568",
    "datePublished": "2026-08-15T12:28:08.859Z",
    "dateReserved": "2026-08-15T05:44:03.917Z",
    "dateUpdated": "2026-08-17T05:48:47.432Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2",
  "vulnerability-lookup:meta": {
    "epss": {
      "cve": "CVE-2026-74568",
      "date": "2026-08-18",
      "epss": "0.00122",
      "percentile": "0.02382"
    },
    "nvd": "{\"cve\":{\"id\":\"CVE-2026-74568\",\"sourceIdentifier\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\",\"published\":\"2026-08-15T13:18:02.370\",\"lastModified\":\"2026-08-17T06:19:55.053\",\"vulnStatus\":\"Received\",\"cveTags\":[],\"descriptions\":[{\"lang\":\"en\",\"value\":\"In the Linux kernel, the following vulnerability has been resolved:\\n\\nKVM: arm64: vgic: Fix race between LPI release and re-registration\\n\\nFix a potential race between decrementing an LPI\u0027s reference count and\\nevicting that structure from the LPI xarray.\\n\\nLPI structures are maintained in the VGIC LPI xarray (dist-\u003elpi_xa).\\nWhen the reference count of an LPI structure drops to zero,\\nvgic_release_lpi_locked() removes the structure from the xarray and\\nfrees it under the xarray lock.\\n\\nHowever, the release of an LPI can race with a concurrent LPI\\nre-registration with the same INTID via vgic_add_lpi() on another CPU,\\nsince the reference count drop and the xarray eviction are not performed\\nin a single atomic step. This can happen e.g. if the guest issues a\\nDISCARD while the LPI is still referenced from a vCPU\u0027s active-pending\\nlist (ap_list), and the same INTID is re-mapped via MAPTI.\\n\\nParticularly, vgic_release_lpi_locked() is called from two distinct\\npaths: direct release via vgic_put_irq(), and deferred release via\\nvgic_release_deleted_lpis(). During direct release, the issue can result\\nin deleting a newly registered LPI from the xarray:\\n\\n  CPU0 (Releasing LPI)                    CPU1 (Adding new LPI)\\n  ====================                    =====================\\n  vgic_put_irq()\\n      __vgic_put_irq()\\n          refcount_dec_and_test()\\n                                          vgic_add_lpi()\\n                                              xa_lock_irqsave()\\n                                              old_irq = xa_load(.., intid)\\n                                              vgic_try_get_irq_ref(old_irq) == false\\n                        new IRQ inserted --\u003e  __xa_store(.., intid, ..)\\n                                              xa_unlock_irqrestore()\\n  xa_lock_irqsave();\\n  vgic_release_lpi_locked()\\n      __xa_erase(.., irq-\u003eintid)   \u003c-- BUG: new IRQ is erased\\n      kfree_rcu(old_irq)\\n\\nDuring the deferred release path, the old IRQ can be leaked:\\n\\n  CPU0 (Releasing LPI)                    CPU1 (Adding new LPI)\\n  ====================                    =====================\\n  vgic_put_irq_norelease()\\n      __vgic_put_irq()\\n          refcount_dec_and_test()\\n      irq-\u003epending_release = true\\n                                          vgic_add_lpi()\\n                                              xa_lock_irqsave()\\n                                              old_irq = xa_load(.., intid)\\n                                              vgic_try_get_irq_ref(oldirq) == false\\n                 BUG: old IRQ overwritten --\u003e __xa_store(.., intid, ..)\\n                                              xa_unlock_irqrestore()\\n\\n  vgic_release_deleted_lpis()\\n      xa_lock_irqsave()\\n      xa_for_each() { .. } \u003c-- old IRQ with pending_release = true\\n                               is gone, so it cannot be released\\n\\nTo fix the direct release path, move the reference count drop inside\\nthe xarray lock, making sure that vgic_add_lpi() never encounters the\\nto-be-released LPI.\\n\\nIn the deferred release path, the refcount drop must happen under a raw\\nspinlock, so the xarray lock cannot be grabbed, and the same solution\\ndoes not work. Instead, update vgic_add_lpi(), so that if it evicts\\nan LPI from the xarray, it takes on the responsibility of freeing it.\\nConsequently, an LPI may now be freed concurrently after a deferred\\nrelease drops the refcount, so accessing the pending_release field is no\\nlonger safe from use-after-free. Delete all uses of the flag, and update\\nvgic_release_deleted_lpis() to identify orphaned LPIs purely based on\\ntheir refcount.\"}],\"affected\":[{\"source\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\",\"affectedData\":[{\"vendor\":\"Linux\",\"product\":\"Linux\",\"defaultStatus\":\"unaffected\",\"programFiles\":[\"arch/arm64/kvm/vgic/vgic-its.c\",\"arch/arm64/kvm/vgic/vgic.c\",\"include/kvm/arm_vgic.h\"],\"repo\":\"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git\",\"versions\":[{\"version\":\"3a08a6ca7c373198c84e2a8c025c395ee966ff8a\",\"lessThan\":\"292e80a159aa88635bf668a7212cfdf526b8bd52\",\"versionType\":\"git\",\"status\":\"affected\"},{\"version\":\"3a08a6ca7c373198c84e2a8c025c395ee966ff8a\",\"lessThan\":\"cbfe2b24a1ea9de35032dbdd100fdc700f5be92d\",\"versionType\":\"git\",\"status\":\"affected\"}]},{\"vendor\":\"Linux\",\"product\":\"Linux\",\"defaultStatus\":\"affected\",\"programFiles\":[\"arch/arm64/kvm/vgic/vgic-its.c\",\"arch/arm64/kvm/vgic/vgic.c\",\"include/kvm/arm_vgic.h\"],\"repo\":\"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git\",\"versions\":[{\"version\":\"6.17\",\"status\":\"affected\"},{\"version\":\"0\",\"lessThan\":\"6.17\",\"versionType\":\"semver\",\"status\":\"unaffected\"},{\"version\":\"7.1.8\",\"lessThanOrEqual\":\"7.1.*\",\"versionType\":\"semver\",\"status\":\"unaffected\"},{\"version\":\"7.2\",\"lessThanOrEqual\":\"*\",\"versionType\":\"original_commit_for_fix\",\"status\":\"unaffected\"}]}]}],\"metrics\":{\"cvssMetricV31\":[{\"source\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\",\"type\":\"Secondary\",\"cvssData\":{\"version\":\"3.1\",\"vectorString\":\"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H\",\"baseScore\":9.3,\"baseSeverity\":\"CRITICAL\",\"attackVector\":\"LOCAL\",\"attackComplexity\":\"LOW\",\"privilegesRequired\":\"NONE\",\"userInteraction\":\"NONE\",\"scope\":\"CHANGED\",\"confidentialityImpact\":\"HIGH\",\"integrityImpact\":\"HIGH\",\"availabilityImpact\":\"HIGH\"},\"exploitabilityScore\":2.5,\"impactScore\":6.0}]},\"references\":[{\"url\":\"https://git.kernel.org/stable/c/292e80a159aa88635bf668a7212cfdf526b8bd52\",\"source\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\"},{\"url\":\"https://git.kernel.org/stable/c/cbfe2b24a1ea9de35032dbdd100fdc700f5be92d\",\"source\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\"}]}}",
    "suse_vex": {
      "aggregate_severity": "not set",
      "current_release_date": "2026-08-15T23:49:59Z",
      "cve": "CVE-2026-74568",
      "id": "CVE-2026-74568",
      "initial_release_date": "2026-08-15T23:49:59Z",
      "source": "SUSE CSAF VEX",
      "status": "interim",
      "title": "SUSE CVE CVE-2026-74568",
      "url": "https://ftp.suse.com/pub/projects/security/csaf-vex/cve-2026-74568.json",
      "version": "2"
    }
  }
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

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.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Loading…