VYPR
Unrated severityNVD Advisory· Published May 28, 2026

CVE-2026-46209

CVE-2026-46209

Description

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

drm/gem: Fix inconsistent plane dimension calculation in drm_gem_fb_init_with_funcs()

drm_gem_fb_init_with_funcs() computes sub-sampled plane dimensions using plain integer division:

unsigned int width = mode_cmd->width / (i ? info->hsub : 1); unsigned int height = mode_cmd->height / (i ? info->vsub : 1);

However, the ioctl-level framebuffer_check() in drm_framebuffer.c uses drm_format_info_plane_width/height() which round up dimensions via DIV_ROUND_UP(). This inconsistency corrupts the subsequent GEM object size check for certain pixel format and dimension combinations.

For example, with NV12 (vsub=2) and a 1-pixel-tall framebuffer the GEM size validation path sees height=0 instead of height=1. The expression (height - 1) then wraps to UINT_MAX as an unsigned int, causing min_size to overflow and wrap back to a small value. A tiny GEM object therefore passes the size guard, yet when the GPU accesses the chroma plane it will read or write memory beyond the object's bounds.

Fix by replacing the open-coded divisions with drm_format_info_plane_width() and drm_format_info_plane_height(), which use DIV_ROUND_UP() and match the calculation already used in framebuffer_check().

AI Insight

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

Inconsistent plane dimension rounding in Linux kernel DRM GEM leads to out-of-bounds memory access via integer underflow.

Vulnerability

In the Linux kernel, drm_gem_fb_init_with_funcs() computes sub-sampled plane dimensions using plain integer division (width / hsub, height / vsub), while the ioctl-level framebuffer_check() uses drm_format_info_plane_width/height() which round up via DIV_ROUND_UP(). This inconsistency can cause an integer underflow for certain formats (e.g., NV12 with height=1), leading to a small GEM object passing the size check, enabling out-of-bounds access. The issue affects kernel versions before the fix commit [1].

Exploitation

An attacker with the ability to create a framebuffer (e.g., via DRM ioctl) can craft a mode_cmd with dimensions such that the division yields zero for a plane (e.g., NV12 with height=1). The GEM object size check then wraps, allowing a small object to be used. No special privileges beyond DRM access are required.

Impact

Successful exploitation allows an attacker to trigger out-of-bounds reads or writes when the GPU accesses the chroma plane, potentially leading to information disclosure or privilege escalation.

Mitigation

The fix is included in commit c5fc49d8470c5ebf3b41607600f277158f159950 [1]. Users should apply the patch from the stable kernel tree. No workaround is available; update to a patched kernel version.

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

Affected products

1

Patches

10
3d4c2268bd72

drm/gem: Fix inconsistent plane dimension calculation in drm_gem_fb_init_with_funcs()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAshutosh DesaiApr 20, 2026Fixed in 7.1-rc2via kernel-cna
1 file changed · +2 3
  • drivers/gpu/drm/drm_gem_framebuffer_helper.c+2 3 modified
    diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    index 9166c353f131cb..88808e972cc156 100644
    --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    @@ -172,8 +172,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
     	}
     
     	for (i = 0; i < info->num_planes; i++) {
    -		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
    -		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
    +		unsigned int width = drm_format_info_plane_width(info, mode_cmd->width, i);
    +		unsigned int height = drm_format_info_plane_height(info, mode_cmd->height, i);
     		unsigned int min_size;
     
     		objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
    -- 
    cgit 1.3-korg
    
    
    
6b992591e04f

drm/gem: Fix inconsistent plane dimension calculation in drm_gem_fb_init_with_funcs()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAshutosh DesaiApr 20, 2026Fixed in 6.6.140via kernel-cna
1 file changed · +2 3
  • drivers/gpu/drm/drm_gem_framebuffer_helper.c+2 3 modified
    diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    index 3bdb6ba37ff42f..2383ebb5e435a4 100644
    --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    @@ -174,8 +174,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
     	}
     
     	for (i = 0; i < info->num_planes; i++) {
    -		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
    -		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
    +		unsigned int width = drm_format_info_plane_width(info, mode_cmd->width, i);
    +		unsigned int height = drm_format_info_plane_height(info, mode_cmd->height, i);
     		unsigned int min_size;
     
     		objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
    -- 
    cgit 1.3-korg
    
    
    
1da4ab7189f1

drm/gem: Fix inconsistent plane dimension calculation in drm_gem_fb_init_with_funcs()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAshutosh DesaiApr 20, 2026Fixed in 6.12.90via kernel-cna
1 file changed · +2 3
  • drivers/gpu/drm/drm_gem_framebuffer_helper.c+2 3 modified
    diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    index 3bdb6ba37ff42f..2383ebb5e435a4 100644
    --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    @@ -174,8 +174,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
     	}
     
     	for (i = 0; i < info->num_planes; i++) {
    -		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
    -		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
    +		unsigned int width = drm_format_info_plane_width(info, mode_cmd->width, i);
    +		unsigned int height = drm_format_info_plane_height(info, mode_cmd->height, i);
     		unsigned int min_size;
     
     		objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
    -- 
    cgit 1.3-korg
    
    
    
1a17ea9861e8

drm/gem: Fix inconsistent plane dimension calculation in drm_gem_fb_init_with_funcs()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAshutosh DesaiApr 20, 2026Fixed in 6.18.32via kernel-cna
1 file changed · +2 3
  • drivers/gpu/drm/drm_gem_framebuffer_helper.c+2 3 modified
    diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    index 4bc89d33df5930..daa5471365c456 100644
    --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    @@ -171,8 +171,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
     	}
     
     	for (i = 0; i < info->num_planes; i++) {
    -		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
    -		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
    +		unsigned int width = drm_format_info_plane_width(info, mode_cmd->width, i);
    +		unsigned int height = drm_format_info_plane_height(info, mode_cmd->height, i);
     		unsigned int min_size;
     
     		objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
    -- 
    cgit 1.3-korg
    
    
    
c5fc49d8470c

drm/gem: Fix inconsistent plane dimension calculation in drm_gem_fb_init_with_funcs()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitAshutosh DesaiApr 20, 2026Fixed in 7.0.9via kernel-cna
1 file changed · +2 3
  • drivers/gpu/drm/drm_gem_framebuffer_helper.c+2 3 modified
    diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    index 9166c353f131cb..88808e972cc156 100644
    --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    @@ -172,8 +172,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
     	}
     
     	for (i = 0; i < info->num_planes; i++) {
    -		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
    -		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
    +		unsigned int width = drm_format_info_plane_width(info, mode_cmd->width, i);
    +		unsigned int height = drm_format_info_plane_height(info, mode_cmd->height, i);
     		unsigned int min_size;
     
     		objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
    -- 
    cgit 1.3-korg
    
    
    
1a17ea9861e8

drm/gem: Fix inconsistent plane dimension calculation in drm_gem_fb_init_with_funcs()

1 file changed · +2 3
  • drivers/gpu/drm/drm_gem_framebuffer_helper.c+2 3 modified
    diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    index 4bc89d33df5930..daa5471365c456 100644
    --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    @@ -171,8 +171,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
     	}
     
     	for (i = 0; i < info->num_planes; i++) {
    -		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
    -		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
    +		unsigned int width = drm_format_info_plane_width(info, mode_cmd->width, i);
    +		unsigned int height = drm_format_info_plane_height(info, mode_cmd->height, i);
     		unsigned int min_size;
     
     		objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
    -- 
    cgit 1.3-korg
    
    
    
1da4ab7189f1

drm/gem: Fix inconsistent plane dimension calculation in drm_gem_fb_init_with_funcs()

1 file changed · +2 3
  • drivers/gpu/drm/drm_gem_framebuffer_helper.c+2 3 modified
    diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    index 3bdb6ba37ff42f..2383ebb5e435a4 100644
    --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    @@ -174,8 +174,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
     	}
     
     	for (i = 0; i < info->num_planes; i++) {
    -		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
    -		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
    +		unsigned int width = drm_format_info_plane_width(info, mode_cmd->width, i);
    +		unsigned int height = drm_format_info_plane_height(info, mode_cmd->height, i);
     		unsigned int min_size;
     
     		objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
    -- 
    cgit 1.3-korg
    
    
    
3d4c2268bd72

drm/gem: Fix inconsistent plane dimension calculation in drm_gem_fb_init_with_funcs()

1 file changed · +2 3
  • drivers/gpu/drm/drm_gem_framebuffer_helper.c+2 3 modified
    diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    index 9166c353f131cb..88808e972cc156 100644
    --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    @@ -172,8 +172,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
     	}
     
     	for (i = 0; i < info->num_planes; i++) {
    -		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
    -		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
    +		unsigned int width = drm_format_info_plane_width(info, mode_cmd->width, i);
    +		unsigned int height = drm_format_info_plane_height(info, mode_cmd->height, i);
     		unsigned int min_size;
     
     		objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
    -- 
    cgit 1.3-korg
    
    
    
6b992591e04f

drm/gem: Fix inconsistent plane dimension calculation in drm_gem_fb_init_with_funcs()

1 file changed · +2 3
  • drivers/gpu/drm/drm_gem_framebuffer_helper.c+2 3 modified
    diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    index 3bdb6ba37ff42f..2383ebb5e435a4 100644
    --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    @@ -174,8 +174,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
     	}
     
     	for (i = 0; i < info->num_planes; i++) {
    -		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
    -		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
    +		unsigned int width = drm_format_info_plane_width(info, mode_cmd->width, i);
    +		unsigned int height = drm_format_info_plane_height(info, mode_cmd->height, i);
     		unsigned int min_size;
     
     		objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
    -- 
    cgit 1.3-korg
    
    
    
c5fc49d8470c

drm/gem: Fix inconsistent plane dimension calculation in drm_gem_fb_init_with_funcs()

1 file changed · +2 3
  • drivers/gpu/drm/drm_gem_framebuffer_helper.c+2 3 modified
    diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    index 9166c353f131cb..88808e972cc156 100644
    --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
    @@ -172,8 +172,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
     	}
     
     	for (i = 0; i < info->num_planes; i++) {
    -		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
    -		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
    +		unsigned int width = drm_format_info_plane_width(info, mode_cmd->width, i);
    +		unsigned int height = drm_format_info_plane_height(info, mode_cmd->height, i);
     		unsigned int min_size;
     
     		objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Inconsistent plane dimension calculation in drm_gem_fb_init_with_funcs() uses plain integer division instead of round-up division, causing an unsigned integer wraparound in the GEM object size check."

Attack vector

An attacker with the ability to create a DRM framebuffer via the ioctl interface can supply a pixel format such as NV12 (vsub=2) with a 1-pixel-tall framebuffer. The inconsistent dimension calculation causes the GEM size validation to compute height=0 instead of height=1, leading to an unsigned integer wraparound in the `min_size` calculation. This allows a tiny GEM object to pass the size guard, and subsequent GPU access to the chroma plane reads or writes out-of-bounds memory. [patch_id=2897741]

Affected code

The vulnerability resides in `drm_gem_fb_init_with_funcs()` in `drivers/gpu/drm/drm_gem_framebuffer_helper.c`. The function computed sub-sampled plane dimensions using plain integer division (`mode_cmd->width / (i ? info->hsub : 1)`) instead of the round-up helpers `drm_format_info_plane_width()` and `drm_format_info_plane_height()` used by the ioctl-level `framebuffer_check()`. [patch_id=2897741]

What the fix does

The patch replaces the open-coded integer divisions with calls to `drm_format_info_plane_width()` and `drm_format_info_plane_height()`, which use `DIV_ROUND_UP()` and therefore match the calculation already performed in `framebuffer_check()`. This ensures that the plane dimensions used for the GEM object size check are consistent with the dimensions used at the ioctl level, preventing the truncation-to-zero that caused the unsigned wraparound. [patch_id=2897741]

Preconditions

  • inputThe attacker must be able to issue DRM ioctl calls to create a framebuffer with a multi-plane pixel format (e.g., NV12) and a small dimension (e.g., 1 pixel tall).
  • authThe attacker must have access to a DRM device node (local user access to /dev/dri/card*).

Generated on May 28, 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.