VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-45880

CVE-2026-45880

Description

In the Linux kernel, the following vulnerability has been resolved:

PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails

When vm_insert_page() fails in p2pmem_alloc_mmap(), p2pmem_alloc_mmap() doesn't invoke percpu_ref_put() to free the per-CPU ref of pgmap acquired after gen_pool_alloc_owner(), and memunmap_pages() will hang forever when trying to remove the PCI device.

Fix it by adding the missed percpu_ref_put().

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

In the Linux kernel's PCI/P2PDMA, missing percpu_ref_put when vm_insert_page() fails causes device removal hang.

Vulnerability

In the Linux kernel's PCI/P2PDMA subsystem, the function p2pmem_alloc_mmap() fails to call percpu_ref_put() to release the per-CPU reference count of the pgmap when vm_insert_page() fails. This missing reference release occurs after a successful gen_pool_alloc_owner() call [1]. The issue affects kernel versions prior to the commit that adds the missing percpu_ref_put().

Exploitation

To trigger the vulnerability, the attacker must cause vm_insert_page() to fail during a mmap operation on a PCI P2PDMA memory region. This can happen under memory pressure or other conditions that prevent page insertion. The attacker needs the ability to mmap a P2PDMA device, which typically requires access to the device (e.g., through device file permissions). No additional privileges are required beyond that access [1].

Impact

When the vulnerability is triggered, memunmap_pages() hangs indefinitely upon removal of the PCI device. This results in a denial of service (DoS) as the device cannot be cleanly removed, potentially affecting system stability and availability [1].

Mitigation

The fix is included in Linux kernel stable commit e19cce88ec4c (see reference [1]). Users should update their kernel to a version containing this commit. No workaround is available; the only mitigation is to apply the patch [1].

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

10
a1f4dc72efc3

PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitHou TaoDec 20, 2025Fixed in 6.19.4via kernel-cna
1 file changed · +1 1
  • drivers/pci/p2pdma.c+1 1 modified
    diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
    index 4a2fc7ab42c349..218c1f5252b660 100644
    --- a/drivers/pci/p2pdma.c
    +++ b/drivers/pci/p2pdma.c
    @@ -152,6 +152,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
     		ret = vm_insert_page(vma, vaddr, page);
     		if (ret) {
     			gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len);
    +			percpu_ref_put(ref);
     			return ret;
     		}
     		percpu_ref_get(ref);
    -- 
    cgit 1.3-korg
    
    
    
6220694c52a5

PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitHou TaoDec 20, 2025Fixed in 7.0via kernel-cna
1 file changed · +1 1
  • drivers/pci/p2pdma.c+1 1 modified
    diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
    index 4a2fc7ab42c349..218c1f5252b660 100644
    --- a/drivers/pci/p2pdma.c
    +++ b/drivers/pci/p2pdma.c
    @@ -152,6 +152,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
     		ret = vm_insert_page(vma, vaddr, page);
     		if (ret) {
     			gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len);
    +			percpu_ref_put(ref);
     			return ret;
     		}
     		percpu_ref_get(ref);
    -- 
    cgit 1.3-korg
    
    
    
e19cce88ec4c

PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitHou TaoDec 20, 2025Fixed in 6.18.14via kernel-cna
1 file changed · +1 1
  • drivers/pci/p2pdma.c+1 1 modified
    diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
    index 78e108e47254ab..5497ce0be7c5c8 100644
    --- a/drivers/pci/p2pdma.c
    +++ b/drivers/pci/p2pdma.c
    @@ -152,6 +152,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
     		ret = vm_insert_page(vma, vaddr, page);
     		if (ret) {
     			gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len);
    +			percpu_ref_put(ref);
     			return ret;
     		}
     		percpu_ref_get(ref);
    -- 
    cgit 1.3-korg
    
    
    
51b7181cfbed

PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitHou TaoDec 20, 2025Fixed in 6.12.75via kernel-cna
1 file changed · +1 1
  • drivers/pci/p2pdma.c+1 1 modified
    diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
    index 52e1564eadd0ba..ec53b2b0d57fe1 100644
    --- a/drivers/pci/p2pdma.c
    +++ b/drivers/pci/p2pdma.c
    @@ -143,6 +143,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
     		ret = vm_insert_page(vma, vaddr, virt_to_page(kaddr));
     		if (ret) {
     			gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len);
    +			percpu_ref_put(ref);
     			return ret;
     		}
     		percpu_ref_get(ref);
    -- 
    cgit 1.3-korg
    
    
    
baa42b756d18

PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitHou TaoDec 20, 2025Fixed in 6.6.128via kernel-cna
1 file changed · +1 1
  • drivers/pci/p2pdma.c+1 1 modified
    diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
    index 0f1e431bbfc20a..f97ac18a8dc8fc 100644
    --- a/drivers/pci/p2pdma.c
    +++ b/drivers/pci/p2pdma.c
    @@ -143,6 +143,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
     		ret = vm_insert_page(vma, vaddr, virt_to_page(kaddr));
     		if (ret) {
     			gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len);
    +			percpu_ref_put(ref);
     			return ret;
     		}
     		percpu_ref_get(ref);
    -- 
    cgit 1.3-korg
    
    
    
baa42b756d18

PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails

1 file changed · +1 1
  • drivers/pci/p2pdma.c+1 1 modified
    diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
    index 0f1e431bbfc20a..f97ac18a8dc8fc 100644
    --- a/drivers/pci/p2pdma.c
    +++ b/drivers/pci/p2pdma.c
    @@ -143,6 +143,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
     		ret = vm_insert_page(vma, vaddr, virt_to_page(kaddr));
     		if (ret) {
     			gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len);
    +			percpu_ref_put(ref);
     			return ret;
     		}
     		percpu_ref_get(ref);
    -- 
    cgit 1.3-korg
    
    
    
a1f4dc72efc3

PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails

1 file changed · +1 1
  • drivers/pci/p2pdma.c+1 1 modified
    diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
    index 4a2fc7ab42c349..218c1f5252b660 100644
    --- a/drivers/pci/p2pdma.c
    +++ b/drivers/pci/p2pdma.c
    @@ -152,6 +152,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
     		ret = vm_insert_page(vma, vaddr, page);
     		if (ret) {
     			gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len);
    +			percpu_ref_put(ref);
     			return ret;
     		}
     		percpu_ref_get(ref);
    -- 
    cgit 1.3-korg
    
    
    
6220694c52a5

PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails

1 file changed · +1 1
  • drivers/pci/p2pdma.c+1 1 modified
    diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
    index 4a2fc7ab42c349..218c1f5252b660 100644
    --- a/drivers/pci/p2pdma.c
    +++ b/drivers/pci/p2pdma.c
    @@ -152,6 +152,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
     		ret = vm_insert_page(vma, vaddr, page);
     		if (ret) {
     			gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len);
    +			percpu_ref_put(ref);
     			return ret;
     		}
     		percpu_ref_get(ref);
    -- 
    cgit 1.3-korg
    
    
    
51b7181cfbed

PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails

1 file changed · +1 1
  • drivers/pci/p2pdma.c+1 1 modified
    diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
    index 52e1564eadd0ba..ec53b2b0d57fe1 100644
    --- a/drivers/pci/p2pdma.c
    +++ b/drivers/pci/p2pdma.c
    @@ -143,6 +143,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
     		ret = vm_insert_page(vma, vaddr, virt_to_page(kaddr));
     		if (ret) {
     			gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len);
    +			percpu_ref_put(ref);
     			return ret;
     		}
     		percpu_ref_get(ref);
    -- 
    cgit 1.3-korg
    
    
    
e19cce88ec4c

PCI/P2PDMA: Release per-CPU pgmap ref when vm_insert_page() fails

1 file changed · +1 1
  • drivers/pci/p2pdma.c+1 1 modified
    diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
    index 78e108e47254ab..5497ce0be7c5c8 100644
    --- a/drivers/pci/p2pdma.c
    +++ b/drivers/pci/p2pdma.c
    @@ -152,6 +152,7 @@ static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
     		ret = vm_insert_page(vma, vaddr, page);
     		if (ret) {
     			gen_pool_free(p2pdma->pool, (uintptr_t)kaddr, len);
    +			percpu_ref_put(ref);
     			return ret;
     		}
     		percpu_ref_get(ref);
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing percpu_ref_put() in the error path of p2pmem_alloc_mmap() when vm_insert_page() fails, causing a reference-count leak that hangs device removal."

Attack vector

An attacker with the ability to trigger a memory-mapping operation on a PCI P2PDMA device through sysfs (e.g., by writing to a sysfs file that invokes `p2pmem_alloc_mmap()`) can cause `vm_insert_page()` to fail. When this failure occurs, the function returns an error without calling `percpu_ref_put()`, leaving the per-CPU reference count elevated. This prevents `memunmap_pages()` from completing during device removal, causing the kernel to hang indefinitely. No special privileges beyond local access to the sysfs interface are required.

Affected code

The vulnerability is in the `p2pmem_alloc_mmap()` function in `drivers/pci/p2pdma.c` [patch_id=2661741]. The error path after a failed `vm_insert_page()` call frees the pool allocation via `gen_pool_free()` but does not release the per-CPU reference count (`percpu_ref`) that was acquired earlier for the pgmap.

What the fix does

The patch adds a single line — `percpu_ref_put(ref);` — inside the error-handling block of `p2pmem_alloc_mmap()` after `vm_insert_page()` fails [patch_id=2661741]. Previously, the error path called `gen_pool_free()` to return the allocated memory to the pool but did not decrement the per-CPU reference count (`ref`) that was acquired earlier via `gen_pool_alloc_owner()`. Without this decrement, the reference count remains elevated, causing `memunmap_pages()` to wait forever for the refcount to reach zero when the PCI device is removed. The fix ensures proper reference-count symmetry on the error path.

Preconditions

  • inputAttacker must have local access to the sysfs interface that triggers p2pmem_alloc_mmap() on a PCI P2PDMA device
  • inputvm_insert_page() must fail (e.g., due to memory pressure or invalid VMA state)

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.