VYPR
Unrated severityNVD Advisory· Published Jun 8, 2026

CVE-2026-46309

CVE-2026-46309

Description

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

drm/xe/uapi: Reject coh_none PAT index for CPU cached memory in madvise

Add validation in xe_vm_madvise_ioctl() to reject PAT indices with XE_COH_NONE coherency mode when applied to CPU cached memory.

Using coh_none with CPU cached buffers is a security issue. When the kernel clears pages before reallocation, the clear operation stays in CPU cache (dirty). GPU with coh_none can bypass CPU caches and read stale sensitive data directly from DRAM, potentially leaking data from previously freed pages of other processes.

This aligns with the existing validation in vm_bind path (xe_vm_bind_ioctl_validate_bo).

v2(Matthew brost) - Add fixes - Move one debug print to better place

v3(Matthew Auld) - Should be drm/xe/uapi - More Cc

v4(Shuicheng Lin) - Fix kmem leak issues by the way

v5 - Remove kmem leak because it has been merged by another patch

v6 - Remove the fix which is not related to current fix

v7 - No change

v8 - Rebase

v9 - Limit the restrictions to iGPU

v10 - No change

(cherry picked from commit 016ccdb674b8c899940b3944952c96a6a490d10a)

Affected products

3

Patches

7
4e5591c2fc1b

drm/xe/uapi: Reject coh_none PAT index for CPU cached memory in madvise

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJia YaoApr 17, 2026Fixed in 7.1-rc2via kernel-cna
1 file changed · +47 1
  • drivers/gpu/drm/xe/xe_vm_madvise.c+47 1 modified
    diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
    index 66f00d3f5c070..c78906dea82be 100644
    --- a/drivers/gpu/drm/xe/xe_vm_madvise.c
    +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
    @@ -621,6 +621,45 @@ static int xe_madvise_purgeable_retained_to_user(const struct xe_madvise_details
     	return 0;
     }
     
    +static bool check_pat_args_are_sane(struct xe_device *xe,
    +				    struct xe_vmas_in_madvise_range *madvise_range,
    +				    u16 pat_index)
    +{
    +	u16 coh_mode = xe_pat_index_get_coh_mode(xe, pat_index);
    +	int i;
    +
    +	/*
    +	 * Using coh_none with CPU cached buffers is not allowed on iGPU.
    +	 * On iGPU the GPU shares the LLC with the CPU, so with coh_none
    +	 * the GPU bypasses CPU caches and reads directly from DRAM,
    +	 * potentially seeing stale sensitive data from previously freed
    +	 * pages. On dGPU this restriction does not apply, because the
    +	 * platform does not provide a non-coherent system memory access
    +	 * path that would violate the DMA coherency contract.
    +	 */
    +	if (coh_mode != XE_COH_NONE || IS_DGFX(xe))
    +		return true;
    +
    +	for (i = 0; i < madvise_range->num_vmas; i++) {
    +		struct xe_vma *vma = madvise_range->vmas[i];
    +		struct xe_bo *bo = xe_vma_bo(vma);
    +
    +		if (bo) {
    +			/* BO with WB caching + COH_NONE is not allowed */
    +			if (XE_IOCTL_DBG(xe, bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB))
    +				return false;
    +			/* Imported dma-buf without caching info, assume cached */
    +			if (XE_IOCTL_DBG(xe, !bo->cpu_caching))
    +				return false;
    +		} else if (XE_IOCTL_DBG(xe, xe_vma_is_cpu_addr_mirror(vma) ||
    +					    xe_vma_is_userptr(vma)))
    +			/* System memory (userptr/SVM) is always CPU cached */
    +			return false;
    +	}
    +
    +	return true;
    +}
    +
     static bool check_bo_args_are_sane(struct xe_vm *vm, struct xe_vma **vmas,
     				   int num_vmas, u32 atomic_val)
     {
    @@ -750,6 +789,14 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
     		}
     	}
     
    +	if (args->type == DRM_XE_MEM_RANGE_ATTR_PAT) {
    +		if (!check_pat_args_are_sane(xe, &madvise_range,
    +					     args->pat_index.val)) {
    +			err = -EINVAL;
    +			goto free_vmas;
    +		}
    +	}
    +
     	if (madvise_range.has_bo_vmas) {
     		if (args->type == DRM_XE_MEM_RANGE_ATTR_ATOMIC) {
     			if (!check_bo_args_are_sane(vm, madvise_range.vmas,
    -- 
    cgit 1.3-korg
    
    
    
87f9b1528e1f

drm/xe/uapi: Reject coh_none PAT index for CPU cached memory in madvise

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJia YaoApr 17, 2026Fixed in 6.18.32via kernel-cna
1 file changed · +47 1
  • drivers/gpu/drm/xe/xe_vm_madvise.c+47 1 modified
    diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
    index 9dc801f657129..da306013a0131 100644
    --- a/drivers/gpu/drm/xe/xe_vm_madvise.c
    +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
    @@ -299,6 +299,45 @@ static bool madvise_args_are_sane(struct xe_device *xe, const struct drm_xe_madv
     	return true;
     }
     
    +static bool check_pat_args_are_sane(struct xe_device *xe,
    +				    struct xe_vmas_in_madvise_range *madvise_range,
    +				    u16 pat_index)
    +{
    +	u16 coh_mode = xe_pat_index_get_coh_mode(xe, pat_index);
    +	int i;
    +
    +	/*
    +	 * Using coh_none with CPU cached buffers is not allowed on iGPU.
    +	 * On iGPU the GPU shares the LLC with the CPU, so with coh_none
    +	 * the GPU bypasses CPU caches and reads directly from DRAM,
    +	 * potentially seeing stale sensitive data from previously freed
    +	 * pages. On dGPU this restriction does not apply, because the
    +	 * platform does not provide a non-coherent system memory access
    +	 * path that would violate the DMA coherency contract.
    +	 */
    +	if (coh_mode != XE_COH_NONE || IS_DGFX(xe))
    +		return true;
    +
    +	for (i = 0; i < madvise_range->num_vmas; i++) {
    +		struct xe_vma *vma = madvise_range->vmas[i];
    +		struct xe_bo *bo = xe_vma_bo(vma);
    +
    +		if (bo) {
    +			/* BO with WB caching + COH_NONE is not allowed */
    +			if (XE_IOCTL_DBG(xe, bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB))
    +				return false;
    +			/* Imported dma-buf without caching info, assume cached */
    +			if (XE_IOCTL_DBG(xe, !bo->cpu_caching))
    +				return false;
    +		} else if (XE_IOCTL_DBG(xe, xe_vma_is_cpu_addr_mirror(vma) ||
    +					    xe_vma_is_userptr(vma)))
    +			/* System memory (userptr/SVM) is always CPU cached */
    +			return false;
    +	}
    +
    +	return true;
    +}
    +
     static bool check_bo_args_are_sane(struct xe_vm *vm, struct xe_vma **vmas,
     				   int num_vmas, u32 atomic_val)
     {
    @@ -384,6 +423,14 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
     	if (err || !madvise_range.num_vmas)
     		goto unlock_vm;
     
    +	if (args->type == DRM_XE_MEM_RANGE_ATTR_PAT) {
    +		if (!check_pat_args_are_sane(xe, &madvise_range,
    +					     args->pat_index.val)) {
    +			err = -EINVAL;
    +			goto free_vmas;
    +		}
    +	}
    +
     	if (madvise_range.has_bo_vmas) {
     		if (args->type == DRM_XE_MEM_RANGE_ATTR_ATOMIC) {
     			if (!check_bo_args_are_sane(vm, madvise_range.vmas,
    -- 
    cgit 1.3-korg
    
    
    
fea04cf6f234

drm/xe/uapi: Reject coh_none PAT index for CPU cached memory in madvise

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJia YaoApr 17, 2026Fixed in 7.0.9via kernel-cna
1 file changed · +47 1
  • drivers/gpu/drm/xe/xe_vm_madvise.c+47 1 modified
    diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
    index b4086129a3648..421224f89f573 100644
    --- a/drivers/gpu/drm/xe/xe_vm_madvise.c
    +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
    @@ -357,6 +357,45 @@ static void xe_madvise_details_fini(struct xe_madvise_details *details)
     	drm_pagemap_put(details->dpagemap);
     }
     
    +static bool check_pat_args_are_sane(struct xe_device *xe,
    +				    struct xe_vmas_in_madvise_range *madvise_range,
    +				    u16 pat_index)
    +{
    +	u16 coh_mode = xe_pat_index_get_coh_mode(xe, pat_index);
    +	int i;
    +
    +	/*
    +	 * Using coh_none with CPU cached buffers is not allowed on iGPU.
    +	 * On iGPU the GPU shares the LLC with the CPU, so with coh_none
    +	 * the GPU bypasses CPU caches and reads directly from DRAM,
    +	 * potentially seeing stale sensitive data from previously freed
    +	 * pages. On dGPU this restriction does not apply, because the
    +	 * platform does not provide a non-coherent system memory access
    +	 * path that would violate the DMA coherency contract.
    +	 */
    +	if (coh_mode != XE_COH_NONE || IS_DGFX(xe))
    +		return true;
    +
    +	for (i = 0; i < madvise_range->num_vmas; i++) {
    +		struct xe_vma *vma = madvise_range->vmas[i];
    +		struct xe_bo *bo = xe_vma_bo(vma);
    +
    +		if (bo) {
    +			/* BO with WB caching + COH_NONE is not allowed */
    +			if (XE_IOCTL_DBG(xe, bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB))
    +				return false;
    +			/* Imported dma-buf without caching info, assume cached */
    +			if (XE_IOCTL_DBG(xe, !bo->cpu_caching))
    +				return false;
    +		} else if (XE_IOCTL_DBG(xe, xe_vma_is_cpu_addr_mirror(vma) ||
    +					    xe_vma_is_userptr(vma)))
    +			/* System memory (userptr/SVM) is always CPU cached */
    +			return false;
    +	}
    +
    +	return true;
    +}
    +
     static bool check_bo_args_are_sane(struct xe_vm *vm, struct xe_vma **vmas,
     				   int num_vmas, u32 atomic_val)
     {
    @@ -454,6 +493,14 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
     	if (err || !madvise_range.num_vmas)
     		goto madv_fini;
     
    +	if (args->type == DRM_XE_MEM_RANGE_ATTR_PAT) {
    +		if (!check_pat_args_are_sane(xe, &madvise_range,
    +					     args->pat_index.val)) {
    +			err = -EINVAL;
    +			goto free_vmas;
    +		}
    +	}
    +
     	if (madvise_range.has_bo_vmas) {
     		if (args->type == DRM_XE_MEM_RANGE_ATTR_ATOMIC) {
     			if (!check_bo_args_are_sane(vm, madvise_range.vmas,
    -- 
    cgit 1.3-korg
    
    
    
016ccdb674b8

drm/xe/uapi: Reject coh_none PAT index for CPU cached memory in madvise

https://github.com/torvalds/linuxJia YaoApr 17, 2026via text-mined
1 file changed · +47 0
  • drivers/gpu/drm/xe/xe_vm_madvise.c+47 0 modified
    @@ -621,6 +621,45 @@ static int xe_madvise_purgeable_retained_to_user(const struct xe_madvise_details
     	return 0;
     }
     
    +static bool check_pat_args_are_sane(struct xe_device *xe,
    +				    struct xe_vmas_in_madvise_range *madvise_range,
    +				    u16 pat_index)
    +{
    +	u16 coh_mode = xe_pat_index_get_coh_mode(xe, pat_index);
    +	int i;
    +
    +	/*
    +	 * Using coh_none with CPU cached buffers is not allowed on iGPU.
    +	 * On iGPU the GPU shares the LLC with the CPU, so with coh_none
    +	 * the GPU bypasses CPU caches and reads directly from DRAM,
    +	 * potentially seeing stale sensitive data from previously freed
    +	 * pages. On dGPU this restriction does not apply, because the
    +	 * platform does not provide a non-coherent system memory access
    +	 * path that would violate the DMA coherency contract.
    +	 */
    +	if (coh_mode != XE_COH_NONE || IS_DGFX(xe))
    +		return true;
    +
    +	for (i = 0; i < madvise_range->num_vmas; i++) {
    +		struct xe_vma *vma = madvise_range->vmas[i];
    +		struct xe_bo *bo = xe_vma_bo(vma);
    +
    +		if (bo) {
    +			/* BO with WB caching + COH_NONE is not allowed */
    +			if (XE_IOCTL_DBG(xe, bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB))
    +				return false;
    +			/* Imported dma-buf without caching info, assume cached */
    +			if (XE_IOCTL_DBG(xe, !bo->cpu_caching))
    +				return false;
    +		} else if (XE_IOCTL_DBG(xe, xe_vma_is_cpu_addr_mirror(vma) ||
    +					    xe_vma_is_userptr(vma)))
    +			/* System memory (userptr/SVM) is always CPU cached */
    +			return false;
    +	}
    +
    +	return true;
    +}
    +
     static bool check_bo_args_are_sane(struct xe_vm *vm, struct xe_vma **vmas,
     				   int num_vmas, u32 atomic_val)
     {
    @@ -750,6 +789,14 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
     		}
     	}
     
    +	if (args->type == DRM_XE_MEM_RANGE_ATTR_PAT) {
    +		if (!check_pat_args_are_sane(xe, &madvise_range,
    +					     args->pat_index.val)) {
    +			err = -EINVAL;
    +			goto free_vmas;
    +		}
    +	}
    +
     	if (madvise_range.has_bo_vmas) {
     		if (args->type == DRM_XE_MEM_RANGE_ATTR_ATOMIC) {
     			if (!check_bo_args_are_sane(vm, madvise_range.vmas,
    
87f9b1528e1f

drm/xe/uapi: Reject coh_none PAT index for CPU cached memory in madvise

1 file changed · +47 1
  • drivers/gpu/drm/xe/xe_vm_madvise.c+47 1 modified
    diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
    index 9dc801f657129..da306013a0131 100644
    --- a/drivers/gpu/drm/xe/xe_vm_madvise.c
    +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
    @@ -299,6 +299,45 @@ static bool madvise_args_are_sane(struct xe_device *xe, const struct drm_xe_madv
     	return true;
     }
     
    +static bool check_pat_args_are_sane(struct xe_device *xe,
    +				    struct xe_vmas_in_madvise_range *madvise_range,
    +				    u16 pat_index)
    +{
    +	u16 coh_mode = xe_pat_index_get_coh_mode(xe, pat_index);
    +	int i;
    +
    +	/*
    +	 * Using coh_none with CPU cached buffers is not allowed on iGPU.
    +	 * On iGPU the GPU shares the LLC with the CPU, so with coh_none
    +	 * the GPU bypasses CPU caches and reads directly from DRAM,
    +	 * potentially seeing stale sensitive data from previously freed
    +	 * pages. On dGPU this restriction does not apply, because the
    +	 * platform does not provide a non-coherent system memory access
    +	 * path that would violate the DMA coherency contract.
    +	 */
    +	if (coh_mode != XE_COH_NONE || IS_DGFX(xe))
    +		return true;
    +
    +	for (i = 0; i < madvise_range->num_vmas; i++) {
    +		struct xe_vma *vma = madvise_range->vmas[i];
    +		struct xe_bo *bo = xe_vma_bo(vma);
    +
    +		if (bo) {
    +			/* BO with WB caching + COH_NONE is not allowed */
    +			if (XE_IOCTL_DBG(xe, bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB))
    +				return false;
    +			/* Imported dma-buf without caching info, assume cached */
    +			if (XE_IOCTL_DBG(xe, !bo->cpu_caching))
    +				return false;
    +		} else if (XE_IOCTL_DBG(xe, xe_vma_is_cpu_addr_mirror(vma) ||
    +					    xe_vma_is_userptr(vma)))
    +			/* System memory (userptr/SVM) is always CPU cached */
    +			return false;
    +	}
    +
    +	return true;
    +}
    +
     static bool check_bo_args_are_sane(struct xe_vm *vm, struct xe_vma **vmas,
     				   int num_vmas, u32 atomic_val)
     {
    @@ -384,6 +423,14 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
     	if (err || !madvise_range.num_vmas)
     		goto unlock_vm;
     
    +	if (args->type == DRM_XE_MEM_RANGE_ATTR_PAT) {
    +		if (!check_pat_args_are_sane(xe, &madvise_range,
    +					     args->pat_index.val)) {
    +			err = -EINVAL;
    +			goto free_vmas;
    +		}
    +	}
    +
     	if (madvise_range.has_bo_vmas) {
     		if (args->type == DRM_XE_MEM_RANGE_ATTR_ATOMIC) {
     			if (!check_bo_args_are_sane(vm, madvise_range.vmas,
    -- 
    cgit 1.3-korg
    
    
    
4e5591c2fc1b

drm/xe/uapi: Reject coh_none PAT index for CPU cached memory in madvise

1 file changed · +47 1
  • drivers/gpu/drm/xe/xe_vm_madvise.c+47 1 modified
    diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
    index 66f00d3f5c070..c78906dea82be 100644
    --- a/drivers/gpu/drm/xe/xe_vm_madvise.c
    +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
    @@ -621,6 +621,45 @@ static int xe_madvise_purgeable_retained_to_user(const struct xe_madvise_details
     	return 0;
     }
     
    +static bool check_pat_args_are_sane(struct xe_device *xe,
    +				    struct xe_vmas_in_madvise_range *madvise_range,
    +				    u16 pat_index)
    +{
    +	u16 coh_mode = xe_pat_index_get_coh_mode(xe, pat_index);
    +	int i;
    +
    +	/*
    +	 * Using coh_none with CPU cached buffers is not allowed on iGPU.
    +	 * On iGPU the GPU shares the LLC with the CPU, so with coh_none
    +	 * the GPU bypasses CPU caches and reads directly from DRAM,
    +	 * potentially seeing stale sensitive data from previously freed
    +	 * pages. On dGPU this restriction does not apply, because the
    +	 * platform does not provide a non-coherent system memory access
    +	 * path that would violate the DMA coherency contract.
    +	 */
    +	if (coh_mode != XE_COH_NONE || IS_DGFX(xe))
    +		return true;
    +
    +	for (i = 0; i < madvise_range->num_vmas; i++) {
    +		struct xe_vma *vma = madvise_range->vmas[i];
    +		struct xe_bo *bo = xe_vma_bo(vma);
    +
    +		if (bo) {
    +			/* BO with WB caching + COH_NONE is not allowed */
    +			if (XE_IOCTL_DBG(xe, bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB))
    +				return false;
    +			/* Imported dma-buf without caching info, assume cached */
    +			if (XE_IOCTL_DBG(xe, !bo->cpu_caching))
    +				return false;
    +		} else if (XE_IOCTL_DBG(xe, xe_vma_is_cpu_addr_mirror(vma) ||
    +					    xe_vma_is_userptr(vma)))
    +			/* System memory (userptr/SVM) is always CPU cached */
    +			return false;
    +	}
    +
    +	return true;
    +}
    +
     static bool check_bo_args_are_sane(struct xe_vm *vm, struct xe_vma **vmas,
     				   int num_vmas, u32 atomic_val)
     {
    @@ -750,6 +789,14 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
     		}
     	}
     
    +	if (args->type == DRM_XE_MEM_RANGE_ATTR_PAT) {
    +		if (!check_pat_args_are_sane(xe, &madvise_range,
    +					     args->pat_index.val)) {
    +			err = -EINVAL;
    +			goto free_vmas;
    +		}
    +	}
    +
     	if (madvise_range.has_bo_vmas) {
     		if (args->type == DRM_XE_MEM_RANGE_ATTR_ATOMIC) {
     			if (!check_bo_args_are_sane(vm, madvise_range.vmas,
    -- 
    cgit 1.3-korg
    
    
    
fea04cf6f234

drm/xe/uapi: Reject coh_none PAT index for CPU cached memory in madvise

1 file changed · +47 1
  • drivers/gpu/drm/xe/xe_vm_madvise.c+47 1 modified
    diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c
    index b4086129a3648..421224f89f573 100644
    --- a/drivers/gpu/drm/xe/xe_vm_madvise.c
    +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c
    @@ -357,6 +357,45 @@ static void xe_madvise_details_fini(struct xe_madvise_details *details)
     	drm_pagemap_put(details->dpagemap);
     }
     
    +static bool check_pat_args_are_sane(struct xe_device *xe,
    +				    struct xe_vmas_in_madvise_range *madvise_range,
    +				    u16 pat_index)
    +{
    +	u16 coh_mode = xe_pat_index_get_coh_mode(xe, pat_index);
    +	int i;
    +
    +	/*
    +	 * Using coh_none with CPU cached buffers is not allowed on iGPU.
    +	 * On iGPU the GPU shares the LLC with the CPU, so with coh_none
    +	 * the GPU bypasses CPU caches and reads directly from DRAM,
    +	 * potentially seeing stale sensitive data from previously freed
    +	 * pages. On dGPU this restriction does not apply, because the
    +	 * platform does not provide a non-coherent system memory access
    +	 * path that would violate the DMA coherency contract.
    +	 */
    +	if (coh_mode != XE_COH_NONE || IS_DGFX(xe))
    +		return true;
    +
    +	for (i = 0; i < madvise_range->num_vmas; i++) {
    +		struct xe_vma *vma = madvise_range->vmas[i];
    +		struct xe_bo *bo = xe_vma_bo(vma);
    +
    +		if (bo) {
    +			/* BO with WB caching + COH_NONE is not allowed */
    +			if (XE_IOCTL_DBG(xe, bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB))
    +				return false;
    +			/* Imported dma-buf without caching info, assume cached */
    +			if (XE_IOCTL_DBG(xe, !bo->cpu_caching))
    +				return false;
    +		} else if (XE_IOCTL_DBG(xe, xe_vma_is_cpu_addr_mirror(vma) ||
    +					    xe_vma_is_userptr(vma)))
    +			/* System memory (userptr/SVM) is always CPU cached */
    +			return false;
    +	}
    +
    +	return true;
    +}
    +
     static bool check_bo_args_are_sane(struct xe_vm *vm, struct xe_vma **vmas,
     				   int num_vmas, u32 atomic_val)
     {
    @@ -454,6 +493,14 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil
     	if (err || !madvise_range.num_vmas)
     		goto madv_fini;
     
    +	if (args->type == DRM_XE_MEM_RANGE_ATTR_PAT) {
    +		if (!check_pat_args_are_sane(xe, &madvise_range,
    +					     args->pat_index.val)) {
    +			err = -EINVAL;
    +			goto free_vmas;
    +		}
    +	}
    +
     	if (madvise_range.has_bo_vmas) {
     		if (args->type == DRM_XE_MEM_RANGE_ATTR_ATOMIC) {
     			if (!check_bo_args_are_sane(vm, madvise_range.vmas,
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"The madvise ioctl mishandles the combination of CPU cached memory and the XE_COH_NONE coherency mode, allowing a GPU to bypass CPU caches and read stale data."

Attack vector

An attacker can trigger this vulnerability by making a specific ioctl call to the Linux kernel's Direct Rendering Manager (DRM) subsystem. This call involves the `madvise` operation with parameters that specify the XE_COH_NONE coherency mode for CPU cached memory. The vulnerability is particularly relevant for integrated GPUs (iGPUs) where the CPU and GPU share the last-level cache (LLC).

Affected code

The vulnerability resides in the `xe_vm_madvise_ioctl()` function within the `drivers/gpu/drm/xe/xe_vm_madvise.c` file. Specifically, the patch modifies this function to include a new validation check before processing `DRM_XE_MEM_RANGE_ATTR_PAT` arguments.

What the fix does

The patch introduces a new validation function, `check_pat_args_are_sane`, within `xe_vm_madvise_ioctl()`. This function checks if the provided PAT index uses the XE_COH_NONE coherency mode. If it does, and the target memory is CPU cached (specifically on iGPUs), the ioctl call is rejected with an `EINVAL` error. This prevents the GPU from accessing stale data in DRAM by bypassing CPU caches, thus mitigating the security risk [patch_id=5239750].

Preconditions

  • configThe system must have an Intel Xe graphics driver loaded.
  • inputA user-space application must be able to make a `madvise` ioctl call to the kernel.

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

References

3

News mentions

2