drm_atomic_private_obj_init() initializes the modeset lock and adds the object to the privobj_list before calling atomic_create_state().
However, if atomic_create_state() fails, the function returns the error directly without removing the object from the list or cleaning up the lock. This leaves a dangling entry in privobj_list and a leaked lock. Fix this by unwinding both operations in an error path. Suggested-by: Laurent Pinchart <[email protected]> Signed-off-by: Maxime Ripard <[email protected]> --- drivers/gpu/drm/drm_atomic.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 9bb761eda59f..9973becb75ae 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1027,25 +1027,34 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, int drm_atomic_private_obj_init(struct drm_device *dev, struct drm_private_obj *obj, const struct drm_private_state_funcs *funcs) { struct drm_private_state *state; + int ret; + memset(obj, 0, sizeof(*obj)); drm_modeset_lock_init(&obj->lock); obj->dev = dev; obj->funcs = funcs; list_add_tail(&obj->head, &dev->mode_config.privobj_list); state = obj->funcs->atomic_create_state(obj); - if (IS_ERR(state)) - return PTR_ERR(state); + if (IS_ERR(state)) { + ret = PTR_ERR(state); + goto err_list_del; + } obj->state = state; return 0; + +err_list_del: + list_del(&obj->head); + drm_modeset_lock_fini(&obj->lock); + return ret; } EXPORT_SYMBOL(drm_atomic_private_obj_init); /** * drm_atomic_private_obj_fini - finalize private object -- 2.55.0
