Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7de440db authored by Keith Packard's avatar Keith Packard Committed by Dave Airlie
Browse files

drm: Check mode object lease status in all master ioctl paths [v4]



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.vetter@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.

Changes for v3 provided by Dave Airlie <airlied@redhat.com>

 * remove support for leasing encoders.
 * add support for leasing planes.

Changes for v4

 * Only call drm_lease_held if DRIVER_MODESET.

Signed-off-by: default avatarKeith Packard <keithp@keithp.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 2ed077e4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -310,7 +310,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);

+3 −2
Original line number Diff line number Diff line
@@ -226,7 +226,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;
@@ -234,7 +234,8 @@ 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_crtcs = drm_lease_filter_crtcs(file_priv,
							  encoder->possible_crtcs);
	enc_resp->possible_clones = encoder->possible_clones;

	return 0;
+13 −9
Original line number Diff line number Diff line
@@ -122,11 +122,13 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
	count = 0;
	crtc_id = u64_to_user_ptr(card_res->crtc_id_ptr);
	drm_for_each_crtc(crtc, dev) {
		if (drm_lease_held(file_priv, crtc->base.id)) {
			if (count < card_res->count_crtcs &&
			    put_user(crtc->base.id, crtc_id + count))
				return -EFAULT;
			count++;
		}
	}
	card_res->count_crtcs = count;

	count = 0;
@@ -143,6 +145,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
	count = 0;
	connector_id = u64_to_user_ptr(card_res->connector_id_ptr);
	drm_for_each_connector_iter(connector, &conn_iter) {
		if (drm_lease_held(file_priv, connector->base.id)) {
			if (count < card_res->count_connectors &&
			    put_user(connector->base.id, connector_id + count)) {
				drm_connector_list_iter_end(&conn_iter);
@@ -150,6 +153,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
			}
			count++;
		}
	}
	card_res->count_connectors = count;
	drm_connector_list_iter_end(&conn_iter);

+22 −0
Original line number Diff line number Diff line
@@ -104,6 +104,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_PLANE:
		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)
@@ -117,6 +136,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;
+11 −7
Original line number Diff line number Diff line
@@ -479,11 +479,13 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
		    !file_priv->universal_planes)
			continue;

		if (drm_lease_held(file_priv, plane->base.id)) {
			if (count < plane_resp->count_planes &&
			    put_user(plane->base.id, plane_ptr + count))
				return -EFAULT;
			count++;
		}
	}
	plane_resp->count_planes = count;

	return 0;
@@ -504,9 +506,9 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
		return -ENOENT;

	drm_modeset_lock(&plane->mutex, NULL);
	if (plane->state && plane->state->crtc)
	if (plane->state && plane->state->crtc && drm_lease_held(file_priv, plane->state->crtc->base.id))
		plane_resp->crtc_id = plane->state->crtc->base.id;
	else if (!plane->state && plane->crtc)
	else if (!plane->state && 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;
@@ -520,7 +522,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;

	/*
Loading