[PATCH 06/15] drm: Drop modeset_lock_all from the getproperty ioctl

Alex Deucher alexdeucher at gmail.com
Thu Apr 13 20:03:16 UTC 2017


On Mon, Apr 3, 2017 at 4:32 AM, Daniel Vetter <daniel.vetter at ffwll.ch> wrote:
> Properties, i.e. the struct drm_property specifying the type and value
> range of a property, not the instantiation on a given object, are
> invariant over the lifetime of a driver.
>
> Hence no locking at all is needed, we can just remove it.
>
> While at it give the function some love and simplify it, to get it
> under the 80 char limit:
> - Straighten the loops to reduce the nesting.
> - use u64_to_user_ptr casting helper
> - use put_user for fixed u64 copies.
>
> Note there's a small behavioural change in that we now copy parts of
> the values to userspace if the arrays are a bit too small. Since
> userspace will immediately retry anyway, this doesn't matter.
>
> Signed-off-by: Daniel Vetter <daniel.vetter at intel.com>

This causes a segfault in our ddx:
https://bugs.freedesktop.org/show_bug.cgi?id=100673

Alex


> ---
>  drivers/gpu/drm/drm_property.c | 72 +++++++++++++++++-------------------------
>  1 file changed, 29 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
> index b17959c3e099..3feef0659940 100644
> --- a/drivers/gpu/drm/drm_property.c
> +++ b/drivers/gpu/drm/drm_property.c
> @@ -442,8 +442,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
>         struct drm_property *property;
>         int enum_count = 0;
>         int value_count = 0;
> -       int ret = 0, i;
> -       int copied;
> +       int i, copied;
>         struct drm_property_enum *prop_enum;
>         struct drm_mode_property_enum __user *enum_ptr;
>         uint64_t __user *values_ptr;
> @@ -451,55 +450,43 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
>         if (!drm_core_check_feature(dev, DRIVER_MODESET))
>                 return -EINVAL;
>
> -       drm_modeset_lock_all(dev);
>         property = drm_property_find(dev, out_resp->prop_id);
> -       if (!property) {
> -               ret = -ENOENT;
> -               goto done;
> -       }
> -
> -       if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
> -                       drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
> -               list_for_each_entry(prop_enum, &property->enum_list, head)
> -                       enum_count++;
> -       }
> -
> -       value_count = property->num_values;
> +       if (!property)
> +               return -ENOENT;
>
>         strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
>         out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
>         out_resp->flags = property->flags;
>
> -       if ((out_resp->count_values >= value_count) && value_count) {
> -               values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
> -               for (i = 0; i < value_count; i++) {
> -                       if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
> -                               ret = -EFAULT;
> -                               goto done;
> -                       }
> +       value_count = property->num_values;
> +       values_ptr = u64_to_user_ptr(out_resp->values_ptr);
> +
> +       for (i = 0; i < value_count; i++) {
> +               if (i < out_resp->count_values &&
> +                   put_user(property->values[i], values_ptr + i)) {
> +                       return -EFAULT;
>                 }
>         }
>         out_resp->count_values = value_count;
>
> +       copied = 0;
> +       enum_ptr = u64_to_user_ptr(out_resp->enum_blob_ptr);
> +
>         if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
> -                       drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
> -               if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
> -                       copied = 0;
> -                       enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
> -                       list_for_each_entry(prop_enum, &property->enum_list, head) {
> -
> -                               if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
> -                                       ret = -EFAULT;
> -                                       goto done;
> -                               }
> -
> -                               if (copy_to_user(&enum_ptr[copied].name,
> -                                                &prop_enum->name, DRM_PROP_NAME_LEN)) {
> -                                       ret = -EFAULT;
> -                                       goto done;
> -                               }
> -                               copied++;
> -                       }
> +           drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
> +               list_for_each_entry(prop_enum, &property->enum_list, head) {
> +                       enum_count++;
> +                       if (out_resp->count_enum_blobs <= enum_count)
> +                               continue;
> +
> +                       if (copy_to_user(&enum_ptr[copied].value,
> +                                        &prop_enum->value, sizeof(uint64_t)))
> +                               return -EFAULT;
> +
> +                       if (copy_to_user(&enum_ptr[copied].name,
> +                                        &prop_enum->name, DRM_PROP_NAME_LEN))
> +                               return -EFAULT;
> +                       copied++;
>                 }
>                 out_resp->count_enum_blobs = enum_count;
>         }
> @@ -514,9 +501,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
>          */
>         if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
>                 out_resp->count_enum_blobs = 0;
> -done:
> -       drm_modeset_unlock_all(dev);
> -       return ret;
> +
> +       return 0;
>  }
>
>  static void drm_property_free_blob(struct kref *kref)
> --
> 2.11.0
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


More information about the dri-devel mailing list