Dave Airlie had at least the refcount leak fixed in a later patch (but
that patch does other things which need a bit more work). But we still
have the trouble that silly userspace could hit the WARN_ON in
drm_mode_object_find.

Fix this all up to make sure we don't leak objects, and don't spew
into demsg.

Fixes: d0f37cf62979 ("drm/mode: move framebuffer reference into object.")
Testcase: igt/kms_addfb_basic/invalid-*-prop*
Cc: Dave Airlie <airlied at gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter at intel.com>
---
 drivers/gpu/drm/drm_crtc.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 52e6001a40e4..4089c81fe710 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -389,9 +389,7 @@ struct drm_mode_object *drm_mode_object_find(struct 
drm_device *dev,
 {
        struct drm_mode_object *obj = NULL;

-       /* Framebuffers are reference counted and need their own lookup
-        * function.*/
-       WARN_ON(type == DRM_MODE_OBJECT_FB || type == DRM_MODE_OBJECT_BLOB);
+       WARN_ON(type == DRM_MODE_OBJECT_BLOB);
        obj = _object_find(dev, id, type);
        return obj;
 }
@@ -5005,7 +5003,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device 
*dev, void *data,
        }
        if (!obj->properties) {
                ret = -EINVAL;
-               goto out;
+               goto out_unref;
        }

        ret = get_properties(obj, file_priv->atomic,
@@ -5013,6 +5011,8 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device 
*dev, void *data,
                        (uint64_t __user *)(unsigned 
long)(arg->prop_values_ptr),
                        &arg->count_props);

+out_unref:
+       drm_mode_object_unreference(obj);
 out:
        drm_modeset_unlock_all(dev);
        return ret;
@@ -5055,20 +5055,20 @@ int drm_mode_obj_set_property_ioctl(struct drm_device 
*dev, void *data,
                goto out;
        }
        if (!arg_obj->properties)
-               goto out;
+               goto out_unref;

        for (i = 0; i < arg_obj->properties->count; i++)
                if (arg_obj->properties->properties[i]->base.id == arg->prop_id)
                        break;

        if (i == arg_obj->properties->count)
-               goto out;
+               goto out_unref;

        prop_obj = drm_mode_object_find(dev, arg->prop_id,
                                        DRM_MODE_OBJECT_PROPERTY);
        if (!prop_obj) {
                ret = -ENOENT;
-               goto out;
+               goto out_unref;
        }
        property = obj_to_property(prop_obj);

@@ -5091,6 +5091,8 @@ int drm_mode_obj_set_property_ioctl(struct drm_device 
*dev, void *data,

        drm_property_change_valid_put(property, ref);

+out_unref:
+       drm_mode_object_unreference(arg_obj);
 out:
        drm_modeset_unlock_all(dev);
        return ret;
-- 
2.5.0

Reply via email to