From 8e36132efa16f92af09300c0e440d869744345fb Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Sat, 14 Mar 2026 15:39:47 +0000 Subject: [PATCH] plugin/amdgpu: fix resource leaks in drm restore error paths The exit label in amdgpu_plugin_drm_restore_file() returns immediately when ret < 0 without freeing the dmabufs array or deinitializing the amdgpu device handle. Move cleanup before the error check so resources are always released. Replace xzalloc() with xmalloc() and memset(0xff) for the dmabufs array because zero is a valid fd number and would cause the cleanup loop to close fd 0 (stdin) for unpopulated entries. Initializing to KFD_INVALID_FD (0xffffffff) lets the exit block tell which fds were actually opened. Guard amdgpu_device_deinitialize() behind a dev_initialized flag to avoid calling it when initialization failed, and close dmabuf_fd when drmPrimeFDToHandle() fails. To prevent double-closing fds that restore_bo_contents_drm() already closed, only run the close loop when the BO content restore was not reached. Signed-off-by: Radostin Stoyanov --- plugins/amdgpu/amdgpu_plugin_drm.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/plugins/amdgpu/amdgpu_plugin_drm.c b/plugins/amdgpu/amdgpu_plugin_drm.c index 0432ce48c..4d94344a3 100644 --- a/plugins/amdgpu/amdgpu_plugin_drm.c +++ b/plugins/amdgpu/amdgpu_plugin_drm.c @@ -479,18 +479,22 @@ int amdgpu_plugin_drm_restore_file(int fd, CriuRenderNode *rd) { int ret = 0; bool retry_needed = false; + bool dev_initialized = false; + bool bo_restore_called = false; uint32_t major, minor; amdgpu_device_handle h_dev; int device_fd; - int *dmabufs = xzalloc(sizeof(int) * rd->num_of_bos); + int *dmabufs = xmalloc(sizeof(int) * rd->num_of_bos); if (!dmabufs) return -ENOMEM; + memset(dmabufs, 0xff, sizeof(int) * rd->num_of_bos); ret = amdgpu_device_initialize(fd, &major, &minor, &h_dev); if (ret) { pr_info("Error in init amdgpu device\n"); goto exit; } + dev_initialized = true; device_fd = amdgpu_device_get_fd(h_dev); @@ -520,6 +524,7 @@ int amdgpu_plugin_drm_restore_file(int fd, CriuRenderNode *rd) ret = drmPrimeFDToHandle(device_fd, dmabuf_fd, &handle); if (ret) { pr_perror("Failed to get handle from dmabuf fd"); + close(dmabuf_fd); goto exit; } } else { @@ -601,18 +606,26 @@ int amdgpu_plugin_drm_restore_file(int fd, CriuRenderNode *rd) if (ret) goto exit; - ret = amdgpu_device_deinitialize(h_dev); - if (rd->num_of_bos > 0) { + bo_restore_called = true; ret = restore_bo_contents_drm(rd->drm_render_minor, rd, fd, dmabufs); if (ret) goto exit; } exit: + if (dev_initialized) + amdgpu_device_deinitialize(h_dev); + if (ret < 0 && !bo_restore_called) { + for (int i = 0; i < rd->num_of_bos; i++) { + if (dmabufs[i] != KFD_INVALID_FD) + close(dmabufs[i]); + } + } + xfree(dmabufs); + if (ret < 0) return ret; - xfree(dmabufs); return retry_needed; }