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

CVE-2026-45862

CVE-2026-45862

Description

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

iommu/vt-d: Flush cache for PASID table before using it

When writing the address of a freshly allocated zero-initialized PASID table to a PASID directory entry, do that after the CPU cache flush for this PASID table, not before it, to avoid the time window when this PASID table may be already used by non-coherent IOMMU hardware while its contents in RAM is still some random old data, not zero-initialized.

AI Insight

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

In the Linux kernel's iommu/vt-d driver, a PASID table use-after-clear race allows non-coherent IOMMU hardware to read stale data before a cache flush completes.

Vulnerability

In the Linux kernel's iommu/vt-d driver, a vulnerability exists in the handling of PASID (Process Address Space ID) table initialization. When a new PASID table is allocated and zero-initialized, its physical address is written to a PASID directory entry. The code path incorrectly performs this write before issuing a CPU cache flush for the PASID table data. This creates a window in which non-coherent IOMMU hardware (such as older VT-d implementations) may read the PASID table directly from RAM, potentially accessing stale or non-zeroed data instead of the intended zero-initialized entries. The issue affects stable kernel versions as referenced in the commit that fixes it [1].

Exploitation

An attacker does not need to be authenticated or have local access to trigger this condition. The vulnerability is a race window that occurs during normal kernel operation when the IOMMU driver allocates and activates a new PASID table. A malicious actor with physical access to the system or control of DMA-capable devices could potentially exploit the short time window between the directory entry update and the cache flush to direct the IOMMU to read incomplete or stale PASID table content from RAM. No special timing or user interaction is required beyond the existence of a non-coherent IOMMU and a device that can perform DMA operations during this window.

Impact

If successfully exploited, an attacker could cause the IOMMU to use incorrect PASID table entries, leading to unauthorized memory access or privilege escalation. Specifically, the non-zeroed random data in the PASID table might allow a device to bypass IOMMU protection, potentially reading or writing to memory regions that should be isolated. The outcome could include information disclosure or denial of service, and in more complex scenarios, arbitrary code execution if the attacker can carefully control the stale data and the device's DMA operations.

Mitigation

The fix was committed in the Linux kernel stable tree in commit 36990407cdd257473607e33802d00e978af2759e [1]. This commit moves the cache flush to occur after the PASID directory entry is written, eliminating the race window. Systems should update to a kernel version that includes this commit or its backport. No workaround is available beyond applying the patch. There is no indication that this CVE is listed in the CISA Known Exploited Vulnerabilities catalog.

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

16
36990407cdd2

iommu/vt-d: Flush cache for PASID table before using it

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDmytro MalukaJan 22, 2026Fixed in 6.1.165via kernel-cna
2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 32432d82d7744f..9b82676dfd99f7 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -205,6 +205,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -216,10 +219,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 32432d82d7744f..9b82676dfd99f7 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -205,6 +205,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -216,10 +219,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
c93f23375d8c

iommu/vt-d: Flush cache for PASID table before using it

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDmytro MalukaJan 22, 2026Fixed in 6.6.128via kernel-cna
2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 8faa93cffac45d..07c8b0df8e2a85 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -207,6 +207,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -218,10 +221,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 8faa93cffac45d..07c8b0df8e2a85 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -207,6 +207,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -218,10 +221,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
36244dfd3853

iommu/vt-d: Flush cache for PASID table before using it

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDmytro MalukaJan 22, 2026Fixed in 6.18.14via kernel-cna
2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 52f678975da745..67cbf53d18c8ff 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -153,6 +153,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -165,10 +168,8 @@ retry:
     			iommu_free_pages(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 52f678975da745..67cbf53d18c8ff 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -153,6 +153,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -165,10 +168,8 @@ retry:
     			iommu_free_pages(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
5962c30a6f05

iommu/vt-d: Flush cache for PASID table before using it

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDmytro MalukaJan 22, 2026Fixed in 6.12.75via kernel-cna
2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 2e5fa0a232999f..2ec76333b69736 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -152,6 +152,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -164,10 +167,8 @@ retry:
     			iommu_free_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 2e5fa0a232999f..2ec76333b69736 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -152,6 +152,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -164,10 +167,8 @@ retry:
     			iommu_free_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
22d169bdd284

iommu/vt-d: Flush cache for PASID table before using it

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDmytro MalukaJan 22, 2026Fixed in 7.0via kernel-cna
2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 99692f88b8834c..6379b211f12b0f 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -153,6 +153,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -165,10 +168,8 @@ retry:
     			iommu_free_pages(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 99692f88b8834c..6379b211f12b0f 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -153,6 +153,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -165,10 +168,8 @@ retry:
     			iommu_free_pages(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
0616137b70e6

iommu/vt-d: Flush cache for PASID table before using it

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDmytro MalukaJan 22, 2026Fixed in 5.15.202via kernel-cna
2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 589b97ff5433cb..fd60e7ec625eae 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -268,6 +268,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -279,10 +282,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 589b97ff5433cb..fd60e7ec625eae 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -268,6 +268,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -279,10 +282,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
d15cda135148

iommu/vt-d: Flush cache for PASID table before using it

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDmytro MalukaJan 22, 2026Fixed in 6.19.4via kernel-cna
2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 3e2255057079c5..77b9b147ab50e5 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -153,6 +153,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -165,10 +168,8 @@ retry:
     			iommu_free_pages(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 3e2255057079c5..77b9b147ab50e5 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -153,6 +153,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -165,10 +168,8 @@ retry:
     			iommu_free_pages(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
cd75e77125c8

iommu/vt-d: Flush cache for PASID table before using it

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitDmytro MalukaJan 22, 2026Fixed in 5.10.252via kernel-cna
2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 586b289cf468de..8c973481521e60 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -268,6 +268,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -279,10 +282,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 586b289cf468de..8c973481521e60 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -268,6 +268,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -279,10 +282,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
c93f23375d8c

iommu/vt-d: Flush cache for PASID table before using it

2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 8faa93cffac45d..07c8b0df8e2a85 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -207,6 +207,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -218,10 +221,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 8faa93cffac45d..07c8b0df8e2a85 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -207,6 +207,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -218,10 +221,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
5962c30a6f05

iommu/vt-d: Flush cache for PASID table before using it

2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 2e5fa0a232999f..2ec76333b69736 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -152,6 +152,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -164,10 +167,8 @@ retry:
     			iommu_free_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 2e5fa0a232999f..2ec76333b69736 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -152,6 +152,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -164,10 +167,8 @@ retry:
     			iommu_free_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
cd75e77125c8

iommu/vt-d: Flush cache for PASID table before using it

2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 586b289cf468de..8c973481521e60 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -268,6 +268,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -279,10 +282,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 586b289cf468de..8c973481521e60 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -268,6 +268,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -279,10 +282,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
36244dfd3853

iommu/vt-d: Flush cache for PASID table before using it

2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 52f678975da745..67cbf53d18c8ff 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -153,6 +153,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -165,10 +168,8 @@ retry:
     			iommu_free_pages(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 52f678975da745..67cbf53d18c8ff 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -153,6 +153,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -165,10 +168,8 @@ retry:
     			iommu_free_pages(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
0616137b70e6

iommu/vt-d: Flush cache for PASID table before using it

2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 589b97ff5433cb..fd60e7ec625eae 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -268,6 +268,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -279,10 +282,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 589b97ff5433cb..fd60e7ec625eae 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -268,6 +268,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -279,10 +282,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
22d169bdd284

iommu/vt-d: Flush cache for PASID table before using it

2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 99692f88b8834c..6379b211f12b0f 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -153,6 +153,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -165,10 +168,8 @@ retry:
     			iommu_free_pages(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 99692f88b8834c..6379b211f12b0f 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -153,6 +153,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -165,10 +168,8 @@ retry:
     			iommu_free_pages(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
d15cda135148

iommu/vt-d: Flush cache for PASID table before using it

2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 3e2255057079c5..77b9b147ab50e5 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -153,6 +153,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -165,10 +168,8 @@ retry:
     			iommu_free_pages(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 3e2255057079c5..77b9b147ab50e5 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -153,6 +153,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -165,10 +168,8 @@ retry:
     			iommu_free_pages(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
36990407cdd2

iommu/vt-d: Flush cache for PASID table before using it

2 files changed · +8 8
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 32432d82d7744f..9b82676dfd99f7 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -205,6 +205,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -216,10 +219,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/iommu/intel/pasid.c+4 4 modified
    diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
    index 32432d82d7744f..9b82676dfd99f7 100644
    --- a/drivers/iommu/intel/pasid.c
    +++ b/drivers/iommu/intel/pasid.c
    @@ -205,6 +205,9 @@ retry:
     		if (!entries)
     			return NULL;
     
    +		if (!ecap_coherent(info->iommu->ecap))
    +			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +
     		/*
     		 * The pasid directory table entry won't be freed after
     		 * allocation. No worry about the race with free and
    @@ -216,10 +219,8 @@ retry:
     			free_pgtable_page(entries);
     			goto retry;
     		}
    -		if (!ecap_coherent(info->iommu->ecap)) {
    -			clflush_cache_range(entries, VTD_PAGE_SIZE);
    +		if (!ecap_coherent(info->iommu->ecap))
     			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
    -		}
     	}
     
     	return &entries[index];
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"CPU cache flush for a freshly allocated PASID table is performed after writing its address to the directory entry, creating a TOCTOU window where non-coherent IOMMU hardware may read stale data from RAM."

Attack vector

On systems with non-coherent IOMMU hardware (where `ecap_coherent()` returns false), the CPU cache flush for the newly allocated PASID table was performed *after* writing its address into the PASID directory entry [patch_id=2661983]. This creates a time window where the IOMMU hardware may read the PASID table from RAM while the CPU's zero-initialized data is still only in the cache, causing the IOMMU to see stale/random data instead of zeros. An attacker who can trigger PASID table allocation (e.g. via device assignment or IOMMU domain creation) could exploit this race to cause the IOMMU to use uninitialized table contents, potentially leading to incorrect DMA translations or privilege escalation.

Affected code

The bug is in `drivers/iommu/intel/pasid.c` in the function that allocates and installs a PASID table. The code path is inside a `retry` loop where a freshly allocated zero-initialized PASID table (`entries`) is written into a PASID directory entry (`dir[dir_index].val`).

What the fix does

The patch moves the `clflush_cache_range(entries, VTD_PAGE_SIZE)` call to execute *before* the PASID directory entry is written, rather than after [patch_id=2661983]. In the old code, the directory entry was written first, then the cache flush occurred inside a block that also flushed the directory entry itself. The fix separates the two flushes: the PASID table flush happens immediately after allocation (before the directory entry is written), and only the directory entry flush remains in the later block. This ensures that when the IOMMU hardware sees the new directory pointer, the PASID table contents are already coherent in RAM.

Preconditions

  • configIOMMU hardware must be non-coherent (ecap_coherent() returns false)
  • inputAttacker must be able to trigger PASID table allocation (e.g. via device assignment or IOMMU domain creation)

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

References

8

News mentions

0

No linked articles in our index yet.