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 <rstoyanov@fedoraproject.org>
This commit is contained in:
Radostin Stoyanov 2026-03-14 15:39:47 +00:00
parent b8d118a758
commit 8e36132efa

View file

@ -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;
}