Skip to content

Commit d7e9a2d

Browse files
pvts-matPlaidCat
authored andcommitted
drm/gem: Ignore color planes that are unused by framebuffer format
jira VULN-136703 cve-pre CVE-2025-38449 commit-author Thomas Zimmermann <tzimmermann@suse.de> commit 746b9c6 upstream-diff | drivers/gpu/drm/drm_gem_atomic_helper.c The upstream change to `drm_gem_plane_helper_prepare_fb()' breaks the loop which was introduced in the non-backported commit 1ea28bc ("drm: handle kernel fences in drm_gem_plane_helper_prepare_fb v2"). Adapted it to cover the first plane only as it's present in the LTS 8.6 codebase. drivers/gpu/drm/drm_gem_framebuffer_helper.c Used the existing `dma_buf_map' name of the struct instead of `iosys_map'. The struct renaming was done in 7938f42 ("dma-buf-map: Rename to iosys-map"), missing from LTS 8.6. It cannot be backported due to its scope, also the change it introduces is purely syntactic and can be corrected for easily. include/drm/drm_gem_framebuffer_helper.h Same as above. Only handle color planes that exist in a framebuffer's color format. Ignore non-existing planes. So far, several helpers assumed that all 4 planes are available and silently ignored non-existing planes. This lead to subtil bugs with uninitialized data in instances of struct iosys_map. [1] Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> Tested-by: Noralf Trønnes <noralf@tronnes.org> Acked-by: Christian König <christian.koenig@amd.com> Link: https://lore.kernel.org/dri-devel/20210730183511.20080-1-tzimmermann@suse.de/T/#md0172b10bb588d8f20f4f456e304f08d2a4505f7 # 1 Link: https://patchwork.freedesktop.org/patch/msgid/20220517113327.26919-3-tzimmermann@suse.de (cherry picked from commit 746b9c6) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
1 parent 88ce18d commit d7e9a2d

3 files changed

Lines changed: 25 additions & 24 deletions

File tree

drivers/gpu/drm/drm_gem_atomic_helper.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ int drm_gem_plane_helper_prepare_fb(struct drm_plane *plane, struct drm_plane_st
147147
return 0;
148148

149149
obj = drm_gem_fb_get_obj(state->fb, 0);
150+
if (!obj)
151+
return -EINVAL;
150152
fence = dma_resv_get_excl_unlocked(obj->resv);
151153
drm_atomic_set_fence_for_plane(state, fence);
152154

drivers/gpu/drm/drm_gem_framebuffer_helper.c

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ drm_gem_fb_init(struct drm_device *dev,
8989
*/
9090
void drm_gem_fb_destroy(struct drm_framebuffer *fb)
9191
{
92-
size_t i;
92+
unsigned int i;
9393

94-
for (i = 0; i < ARRAY_SIZE(fb->obj); i++)
94+
for (i = 0; i < fb->format->num_planes; i++)
9595
drm_gem_object_put(fb->obj[i]);
9696

9797
drm_framebuffer_cleanup(fb);
@@ -326,32 +326,34 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty);
326326
* The argument returns the addresses of the data stored in each BO. This
327327
* is different from @map if the framebuffer's offsets field is non-zero.
328328
*
329+
* Both, @map and @data, must each refer to arrays with at least
330+
* fb->format->num_planes elements.
331+
*
329332
* See drm_gem_fb_vunmap() for unmapping.
330333
*
331334
* Returns:
332335
* 0 on success, or a negative errno code otherwise.
333336
*/
334-
int drm_gem_fb_vmap(struct drm_framebuffer *fb,
335-
struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES],
336-
struct dma_buf_map data[DRM_FORMAT_MAX_PLANES])
337+
int drm_gem_fb_vmap(struct drm_framebuffer *fb, struct dma_buf_map *map,
338+
struct dma_buf_map *data)
337339
{
338340
struct drm_gem_object *obj;
339341
unsigned int i;
340342
int ret;
341343

342-
for (i = 0; i < DRM_FORMAT_MAX_PLANES; ++i) {
344+
for (i = 0; i < fb->format->num_planes; ++i) {
343345
obj = drm_gem_fb_get_obj(fb, i);
344346
if (!obj) {
345-
dma_buf_map_clear(&map[i]);
346-
continue;
347+
ret = -EINVAL;
348+
goto err_drm_gem_vunmap;
347349
}
348350
ret = drm_gem_vmap(obj, &map[i]);
349351
if (ret)
350352
goto err_drm_gem_vunmap;
351353
}
352354

353355
if (data) {
354-
for (i = 0; i < DRM_FORMAT_MAX_PLANES; ++i) {
356+
for (i = 0; i < fb->format->num_planes; ++i) {
355357
memcpy(&data[i], &map[i], sizeof(data[i]));
356358
if (dma_buf_map_is_null(&data[i]))
357359
continue;
@@ -382,10 +384,9 @@ EXPORT_SYMBOL(drm_gem_fb_vmap);
382384
*
383385
* See drm_gem_fb_vmap() for more information.
384386
*/
385-
void drm_gem_fb_vunmap(struct drm_framebuffer *fb,
386-
struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES])
387+
void drm_gem_fb_vunmap(struct drm_framebuffer *fb, struct dma_buf_map *map)
387388
{
388-
unsigned int i = DRM_FORMAT_MAX_PLANES;
389+
unsigned int i = fb->format->num_planes;
389390
struct drm_gem_object *obj;
390391

391392
while (i) {
@@ -440,13 +441,15 @@ int drm_gem_fb_begin_cpu_access(struct drm_framebuffer *fb, enum dma_data_direct
440441
{
441442
struct dma_buf_attachment *import_attach;
442443
struct drm_gem_object *obj;
443-
size_t i;
444+
unsigned int i;
444445
int ret;
445446

446-
for (i = 0; i < ARRAY_SIZE(fb->obj); ++i) {
447+
for (i = 0; i < fb->format->num_planes; ++i) {
447448
obj = drm_gem_fb_get_obj(fb, i);
448-
if (!obj)
449-
continue;
449+
if (!obj) {
450+
ret = -EINVAL;
451+
goto err___drm_gem_fb_end_cpu_access;
452+
}
450453
import_attach = obj->import_attach;
451454
if (!import_attach)
452455
continue;
@@ -476,7 +479,7 @@ EXPORT_SYMBOL(drm_gem_fb_begin_cpu_access);
476479
*/
477480
void drm_gem_fb_end_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir)
478481
{
479-
__drm_gem_fb_end_cpu_access(fb, dir, ARRAY_SIZE(fb->obj));
482+
__drm_gem_fb_end_cpu_access(fb, dir, fb->format->num_planes);
480483
}
481484
EXPORT_SYMBOL(drm_gem_fb_end_cpu_access);
482485

include/drm/drm_gem_framebuffer_helper.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
#include <linux/dma-buf.h>
55
#include <linux/dma-buf-map.h>
66

7-
#include <drm/drm_fourcc.h>
8-
97
struct drm_afbc_framebuffer;
108
struct drm_device;
119
struct drm_fb_helper_surface_size;
@@ -39,11 +37,9 @@ struct drm_framebuffer *
3937
drm_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file,
4038
const struct drm_mode_fb_cmd2 *mode_cmd);
4139

42-
int drm_gem_fb_vmap(struct drm_framebuffer *fb,
43-
struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES],
44-
struct dma_buf_map data[DRM_FORMAT_MAX_PLANES]);
45-
void drm_gem_fb_vunmap(struct drm_framebuffer *fb,
46-
struct dma_buf_map map[static DRM_FORMAT_MAX_PLANES]);
40+
int drm_gem_fb_vmap(struct drm_framebuffer *fb, struct dma_buf_map *map,
41+
struct dma_buf_map *data);
42+
void drm_gem_fb_vunmap(struct drm_framebuffer *fb, struct dma_buf_map *map);
4743
int drm_gem_fb_begin_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir);
4844
void drm_gem_fb_end_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir);
4945

0 commit comments

Comments
 (0)