Attempts to modify un-leased objects are rejected with an error.
Information returned about unleased objects is modified to make them
appear unusable and/or disconnected.

Changes for v2 as suggested by Daniel Vetter <daniel.vet...@ffwll.ch>:

With the change in the __drm_mode_object_find API to pass the
file_priv along, we can now centralize most of the lease-based access
checks in that function.

A few places skip that API and require in-line checks.

Signed-off-by: Keith Packard <kei...@keithp.com>
---
 drivers/gpu/drm/drm_auth.c        |  2 +-
 drivers/gpu/drm/drm_connector.c   |  8 +++---
 drivers/gpu/drm/drm_encoder.c     |  8 +++---
 drivers/gpu/drm/drm_mode_config.c | 52 ++++++++++++++++++++++++---------------
 drivers/gpu/drm/drm_mode_object.c | 22 +++++++++++++++++
 drivers/gpu/drm/drm_plane.c       |  6 +++--
 6 files changed, 69 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index 1db4f63860d1..44c99d12f4c1 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -303,7 +303,7 @@ void drm_master_release(struct drm_file *file_priv)
  */
 bool drm_is_current_master(struct drm_file *fpriv)
 {
-       return fpriv->is_master && fpriv->master == fpriv->minor->dev->master;
+       return fpriv->is_master && drm_lease_owner(fpriv->master) == 
fpriv->minor->dev->master;
 }
 EXPORT_SYMBOL(drm_is_current_master);
 
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 670c20d5660c..dbf34f08363b 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1094,7 +1094,8 @@ int drm_mode_getconnector(struct drm_device *dev, void 
*data,
        }
 
        for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
-               if (connector->encoder_ids[i] != 0)
+               if (connector->encoder_ids[i] != 0 &&
+                   drm_lease_held(file_priv, connector->encoder_ids[i]))
                        encoders_count++;
 
        if (out_resp->count_modes == 0) {
@@ -1118,7 +1119,7 @@ int drm_mode_getconnector(struct drm_device *dev, void 
*data,
 
        drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
        encoder = drm_connector_get_encoder(connector);
-       if (encoder)
+       if (encoder && drm_lease_held(file_priv, encoder->base.id))
                out_resp->encoder_id = encoder->base.id;
        else
                out_resp->encoder_id = 0;
@@ -1156,7 +1157,8 @@ int drm_mode_getconnector(struct drm_device *dev, void 
*data,
                copied = 0;
                encoder_ptr = (uint32_t __user *)(unsigned 
long)(out_resp->encoders_ptr);
                for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-                       if (connector->encoder_ids[i] != 0) {
+                       if (connector->encoder_ids[i] != 0 &&
+                           drm_lease_held(file_priv, 
connector->encoder_ids[i])) {
                                if (put_user(connector->encoder_ids[i],
                                             encoder_ptr + copied)) {
                                        ret = -EFAULT;
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index dbaedd4e12e6..512d0b6cb7d2 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -211,7 +211,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
 
        drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
        crtc = drm_encoder_get_crtc(encoder);
-       if (crtc)
+       if (crtc && drm_lease_held(file_priv, crtc->base.id))
                enc_resp->crtc_id = crtc->base.id;
        else
                enc_resp->crtc_id = 0;
@@ -219,8 +219,10 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
 
        enc_resp->encoder_type = encoder->encoder_type;
        enc_resp->encoder_id = encoder->base.id;
-       enc_resp->possible_crtcs = encoder->possible_crtcs;
-       enc_resp->possible_clones = encoder->possible_clones;
+       enc_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
+                                                         
encoder->possible_crtcs);
+       enc_resp->possible_clones = drm_lease_filter_encoders(file_priv,
+                                                             
encoder->possible_clones);
 
        return 0;
 }
diff --git a/drivers/gpu/drm/drm_mode_config.c 
b/drivers/gpu/drm/drm_mode_config.c
index 2735a5847ffa..bb6b64e594b7 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -131,14 +131,20 @@ int drm_mode_getresources(struct drm_device *dev, void 
*data,
        /* mode_config.mutex protects the connector list against e.g. DP MST
         * connector hot-adding. CRTC/Plane lists are invariant. */
        mutex_lock(&dev->mode_config.mutex);
-       drm_for_each_crtc(crtc, dev)
-               crtc_count++;
+       drm_for_each_crtc(crtc, dev) {
+               if (drm_lease_held(file_priv, crtc->base.id))
+                       crtc_count++;
+       }
 
-       drm_for_each_connector(connector, dev)
-               connector_count++;
+       drm_for_each_connector(connector, dev) {
+               if (drm_lease_held(file_priv, connector->base.id))
+                       connector_count++;
+       }
 
-       drm_for_each_encoder(encoder, dev)
-               encoder_count++;
+       drm_for_each_encoder(encoder, dev) {
+               if (drm_lease_held(file_priv, encoder->base.id))
+                       encoder_count++;
+       }
 
        card_res->max_height = dev->mode_config.max_height;
        card_res->min_height = dev->mode_config.min_height;
@@ -150,11 +156,13 @@ int drm_mode_getresources(struct drm_device *dev, void 
*data,
                copied = 0;
                crtc_id = (uint32_t __user *)(unsigned 
long)card_res->crtc_id_ptr;
                drm_for_each_crtc(crtc, dev) {
-                       if (put_user(crtc->base.id, crtc_id + copied)) {
-                               ret = -EFAULT;
-                               goto out;
+                       if (drm_lease_held(file_priv, crtc->base.id)) {
+                               if (put_user(crtc->base.id, crtc_id + copied)) {
+                                       ret = -EFAULT;
+                                       goto out;
+                               }
+                               copied++;
                        }
-                       copied++;
                }
        }
        card_res->count_crtcs = crtc_count;
@@ -164,12 +172,14 @@ int drm_mode_getresources(struct drm_device *dev, void 
*data,
                copied = 0;
                encoder_id = (uint32_t __user *)(unsigned 
long)card_res->encoder_id_ptr;
                drm_for_each_encoder(encoder, dev) {
-                       if (put_user(encoder->base.id, encoder_id +
-                                    copied)) {
-                               ret = -EFAULT;
-                               goto out;
+                       if (drm_lease_held(file_priv, encoder->base.id)) {
+                               if (put_user(encoder->base.id, encoder_id +
+                                            copied)) {
+                                       ret = -EFAULT;
+                                       goto out;
+                               }
+                               copied++;
                        }
-                       copied++;
                }
        }
        card_res->count_encoders = encoder_count;
@@ -179,12 +189,14 @@ int drm_mode_getresources(struct drm_device *dev, void 
*data,
                copied = 0;
                connector_id = (uint32_t __user *)(unsigned 
long)card_res->connector_id_ptr;
                drm_for_each_connector(connector, dev) {
-                       if (put_user(connector->base.id,
-                                    connector_id + copied)) {
-                               ret = -EFAULT;
-                               goto out;
+                       if (drm_lease_held(file_priv, connector->base.id)) {
+                               if (put_user(connector->base.id,
+                                            connector_id + copied)) {
+                                       ret = -EFAULT;
+                                       goto out;
+                               }
+                               copied++;
                        }
-                       copied++;
                }
        }
        card_res->count_connectors = connector_count;
diff --git a/drivers/gpu/drm/drm_mode_object.c 
b/drivers/gpu/drm/drm_mode_object.c
index daddc7640139..9763787492cc 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -107,6 +107,25 @@ void drm_mode_object_unregister(struct drm_device *dev,
        mutex_unlock(&dev->mode_config.idr_mutex);
 }
 
+/**
+ * drm_lease_required - check types which must be leased to be used
+ * @type: type of object
+ *
+ * Returns whether the provided type of drm_mode_object must
+ * be owned or leased to be used by a process.
+ */
+static bool drm_lease_required(uint32_t type)
+{
+       switch(type) {
+       case DRM_MODE_OBJECT_CRTC:
+       case DRM_MODE_OBJECT_CONNECTOR:
+       case DRM_MODE_OBJECT_ENCODER:
+               return true;
+       default:
+               return false;
+       }
+}
+
 struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
                                               struct drm_file *file_priv,
                                               uint32_t id, uint32_t type)
@@ -120,6 +139,9 @@ struct drm_mode_object *__drm_mode_object_find(struct 
drm_device *dev,
        if (obj && obj->id != id)
                obj = NULL;
 
+       if (obj && drm_lease_required(obj->type) && !_drm_lease_held(file_priv, 
obj->id))
+               obj = NULL;
+
        if (obj && obj->free_cb) {
                if (!kref_get_unless_zero(&obj->refcount))
                        obj = NULL;
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 819f74616f34..c9c687cdc747 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -392,7 +392,7 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
                return -ENOENT;
 
        drm_modeset_lock(&plane->mutex, NULL);
-       if (plane->crtc)
+       if (plane->crtc && drm_lease_held(file_priv, plane->crtc->base.id))
                plane_resp->crtc_id = plane->crtc->base.id;
        else
                plane_resp->crtc_id = 0;
@@ -404,7 +404,9 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
        drm_modeset_unlock(&plane->mutex);
 
        plane_resp->plane_id = plane->base.id;
-       plane_resp->possible_crtcs = plane->possible_crtcs;
+       plane_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
+                                                           
plane->possible_crtcs);
+
        plane_resp->gamma_size = 0;
 
        /*
-- 
2.11.0

Reply via email to