From 32b128be01121f0e8e1c3fba627f939586ac9e46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Larumbe?= Date: Fri, 13 Jun 2025 01:39:29 +0100 Subject: [PATCH] panfrost: Fix Panfrost BO leak in error handling path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When panfrost_resource_init_afbc_headers() fails, freeing the newly created resource is not enough, because we need to unreference its BOs. This will also take care of freeing its resource label. Also replace instances of FREE() in error-handling paths with panfrost_resource_destroy(), as it is capable of handling partially initialised resources. Signed-off-by: Adrián Larumbe Fixes: e3f2bc796374 ("panfrost: handle mmap failures") Reviewed-by: Boris Brezillon Part-of: --- src/gallium/drivers/panfrost/pan_resource.c | 64 ++++++++++----------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index f1bd7da23b4..438cecb6b2e 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -180,6 +180,31 @@ adjust_mtk_tiled_props(struct panfrost_resource *rsc, return true; } +static void +panfrost_resource_destroy(struct pipe_screen *screen, struct pipe_resource *pt) +{ + MESA_TRACE_FUNC(); + + struct panfrost_device *dev = pan_device(screen); + struct panfrost_resource *rsrc = (struct panfrost_resource *)pt; + + if (rsrc->scanout) + renderonly_scanout_destroy(rsrc->scanout, dev->ro); + + if (rsrc->shadow_image) + pipe_resource_reference( + (struct pipe_resource **)&rsrc->shadow_image, NULL); + + if (rsrc->bo) + panfrost_bo_unreference(rsrc->bo); + + free(rsrc->index_cache); + free(rsrc->damage.tile_map.data); + + util_range_destroy(&rsrc->valid_buffer_range); + free(rsrc); +} + static struct pipe_resource * panfrost_resource_from_handle(struct pipe_screen *pscreen, const struct pipe_resource *templat, @@ -242,7 +267,7 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen, if (drm_is_mtk_tiled(mod) && !adjust_mtk_tiled_props(rsc, &iprops, whandle->plane, &explicit_layout)) { - FREE(rsc); + panfrost_resource_destroy(pscreen, &rsc->base); return NULL; } @@ -253,7 +278,7 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen, &explicit_layout, &rsc->plane.layout); if (!valid) { - FREE(rsc); + panfrost_resource_destroy(pscreen, &rsc->base); return NULL; } @@ -264,7 +289,7 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen, * memory space to mmap it etc. */ if (!rsc->bo) { - FREE(rsc); + panfrost_resource_destroy(pscreen, &rsc->base); return NULL; } @@ -932,7 +957,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen, if (!so->scanout) { mesa_loge("Failed to create scanout resource\n"); - FREE(so); + panfrost_resource_destroy(screen, &so->base); return NULL; } assert(handle.type == WINSYS_HANDLE_TYPE_FD); @@ -940,7 +965,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen, close(handle.handle); if (!so->bo) { - FREE(so); + panfrost_resource_destroy(screen, &so->base); return NULL; } @@ -958,7 +983,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen, panfrost_bo_create(dev, so->plane.layout.data_size_B, flags, label); if (!so->bo) { - FREE(so); + panfrost_resource_destroy(screen, &so->base); return NULL; } @@ -969,7 +994,7 @@ panfrost_resource_create_with_modifier(struct pipe_screen *screen, if (drm_is_afbc(so->modifier)) { if (panfrost_resource_init_afbc_headers(so)) { - FREE(so); + panfrost_resource_destroy(screen, &so->base); return NULL; } } @@ -1088,31 +1113,6 @@ panfrost_resource_restore_format(struct panfrost_resource *rsrc, rsrc->image.props.extent_px.height = saved->image.props.extent_px.height; } -static void -panfrost_resource_destroy(struct pipe_screen *screen, struct pipe_resource *pt) -{ - MESA_TRACE_FUNC(); - - struct panfrost_device *dev = pan_device(screen); - struct panfrost_resource *rsrc = (struct panfrost_resource *)pt; - - if (rsrc->scanout) - renderonly_scanout_destroy(rsrc->scanout, dev->ro); - - if (rsrc->shadow_image) - pipe_resource_reference( - (struct pipe_resource **)&rsrc->shadow_image, NULL); - - if (rsrc->bo) - panfrost_bo_unreference(rsrc->bo); - - free(rsrc->index_cache); - free(rsrc->damage.tile_map.data); - - util_range_destroy(&rsrc->valid_buffer_range); - free(rsrc); -} - /* Most of the time we can do CPU-side transfers, but sometimes we need to use * the 3D pipe for this. Let's wrap u_blitter to blit to/from staging textures. * Code adapted from freedreno */