All of lore.kernel.org
 help / color / mirror / Atom feed
From: Keith Packard <keithp@keithp.com>
To: linux-kernel@vger.kernel.org, Dave Airlie <airlied@redhat.com>
Cc: Keith Packard <keithp@keithp.com>, dri-devel@lists.freedesktop.org
Subject: [PATCH 3/4] drm: Check mode object lease status in all master ioctl paths
Date: Sat,  1 Apr 2017 10:08:40 -0700	[thread overview]
Message-ID: <20170401170841.2643-4-keithp@keithp.com> (raw)
In-Reply-To: <20170401170841.2643-1-keithp@keithp.com>

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.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 drivers/gpu/drm/drm_atomic.c      |  3 +++
 drivers/gpu/drm/drm_auth.c        |  2 +-
 drivers/gpu/drm/drm_color_mgmt.c  |  3 +++
 drivers/gpu/drm/drm_connector.c   | 52 ++++++++++++++++++++++++++-------------
 drivers/gpu/drm/drm_crtc.c        | 15 ++++++++---
 drivers/gpu/drm/drm_encoder.c     | 18 +++++++++++---
 drivers/gpu/drm/drm_mode_object.c |  3 +++
 drivers/gpu/drm/drm_plane.c       | 36 +++++++++++++++++++++++----
 include/drm/drm_lease.h           |  4 +++
 include/drm/drm_mode_object.h     |  1 +
 10 files changed, 108 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index fdfb1ec17e66..a3cb95f7f1c1 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -2134,6 +2134,9 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 			goto out;
 		}
 
+		if ((ret = drm_lease_check(file_priv->master, obj->id)) < 0)
+			goto out;
+
 		if (!obj->properties) {
 			drm_mode_object_unreference(obj);
 			ret = -ENOENT;
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_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index 6543ebde501a..f8d7a499cf95 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -206,6 +206,9 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
 		goto out;
 	}
 
+	if ((ret = drm_lease_check(file_priv->master, crtc->base.id)) < 0)
+		goto out;
+
 	if (crtc->funcs->gamma_set == NULL) {
 		ret = -ENOSYS;
 		goto out;
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 7a7019ac9388..a95db57dd966 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1079,6 +1079,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 	struct drm_mode_modeinfo u_mode;
 	struct drm_mode_modeinfo __user *mode_ptr;
 	uint32_t __user *encoder_ptr;
+	bool leased;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
@@ -1093,9 +1094,16 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 		goto out_unlock;
 	}
 
-	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
-		if (connector->encoder_ids[i] != 0)
-			encoders_count++;
+	leased = drm_lease_check(file_priv->master, connector->base.id) == 0;
+
+	DRM_DEBUG_LEASE("connector %d leased %s\n", connector->base.id, leased ? "true" : "false");
+
+	if (leased) {
+		for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
+			if (connector->encoder_ids[i] != 0 &&
+			    drm_lease_check(file_priv->master, connector->encoder_ids[i]) == 0)
+				encoders_count++;
+	}
 
 	if (out_resp->count_modes == 0) {
 		connector->funcs->fill_modes(connector,
@@ -1104,21 +1112,29 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 	}
 
 	/* delayed so we get modes regardless of pre-fill_modes state */
-	list_for_each_entry(mode, &connector->modes, head)
-		if (drm_mode_expose_to_userspace(mode, file_priv))
-			mode_count++;
+	if (leased)
+		list_for_each_entry(mode, &connector->modes, head)
+			if (drm_mode_expose_to_userspace(mode, file_priv))
+				mode_count++;
 
 	out_resp->connector_id = connector->base.id;
 	out_resp->connector_type = connector->connector_type;
 	out_resp->connector_type_id = connector->connector_type_id;
-	out_resp->mm_width = connector->display_info.width_mm;
-	out_resp->mm_height = connector->display_info.height_mm;
-	out_resp->subpixel = connector->display_info.subpixel_order;
-	out_resp->connection = connector->status;
+	if (leased) {
+		out_resp->mm_width = connector->display_info.width_mm;
+		out_resp->mm_height = connector->display_info.height_mm;
+		out_resp->subpixel = connector->display_info.subpixel_order;
+		out_resp->connection = connector->status;
+	} else {
+		out_resp->mm_width = 0;
+		out_resp->mm_height = 0;
+		out_resp->subpixel = 0;
+		out_resp->connection = connector_status_disconnected;
+	}
 
 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
 	encoder = drm_connector_get_encoder(connector);
-	if (encoder)
+	if (encoder && leased)
 		out_resp->encoder_id = encoder->base.id;
 	else
 		out_resp->encoder_id = 0;
@@ -1145,12 +1161,14 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 	}
 	out_resp->count_modes = mode_count;
 
-	ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
-			(uint32_t __user *)(unsigned long)(out_resp->props_ptr),
-			(uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
-			&out_resp->count_props);
-	if (ret)
-		goto out;
+	if (leased) {
+		ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
+						     (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
+						     (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
+						     &out_resp->count_props);
+		if (ret)
+			goto out;
+	}
 
 	if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
 		copied = 0;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index e75f62cd8a65..95026ca74568 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -347,6 +347,7 @@ int drm_mode_getcrtc(struct drm_device *dev,
 {
 	struct drm_mode_crtc *crtc_resp = data;
 	struct drm_crtc *crtc;
+	bool leased;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
@@ -355,9 +356,13 @@ int drm_mode_getcrtc(struct drm_device *dev,
 	if (!crtc)
 		return -ENOENT;
 
+	leased = drm_lease_check(file_priv->master, crtc->base.id) == 0;
+
+	DRM_DEBUG_LEASE("crtc %d leased %s\n", crtc->base.id, leased ? "true" : "false");
+
 	drm_modeset_lock_crtc(crtc, crtc->primary);
 	crtc_resp->gamma_size = crtc->gamma_size;
-	if (crtc->primary->fb)
+	if (crtc->primary->fb && leased)
 		crtc_resp->fb_id = crtc->primary->fb->base.id;
 	else
 		crtc_resp->fb_id = 0;
@@ -365,7 +370,7 @@ int drm_mode_getcrtc(struct drm_device *dev,
 	if (crtc->state) {
 		crtc_resp->x = crtc->primary->state->src_x >> 16;
 		crtc_resp->y = crtc->primary->state->src_y >> 16;
-		if (crtc->state->enable) {
+		if (crtc->state->enable && leased) {
 			drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
 			crtc_resp->mode_valid = 1;
 
@@ -375,7 +380,7 @@ int drm_mode_getcrtc(struct drm_device *dev,
 	} else {
 		crtc_resp->x = crtc->x;
 		crtc_resp->y = crtc->y;
-		if (crtc->enabled) {
+		if (crtc->enabled && leased) {
 			drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode);
 			crtc_resp->mode_valid = 1;
 
@@ -529,6 +534,10 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
 	}
 	DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
 
+	if ((ret = drm_lease_check(file_priv->master, crtc->base.id)) < 0) {
+		DRM_DEBUG_KMS("CRTC lease not held\n");
+		goto out;
+	}
 	if (crtc_req->mode_valid) {
 		/* If we have a mode we need a framebuffer. */
 		/* If we pass -1, set the mode with the currently bound fb */
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index 992879f15f23..24d03e13f522 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -201,6 +201,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
 	struct drm_mode_get_encoder *enc_resp = data;
 	struct drm_encoder *encoder;
 	struct drm_crtc *crtc;
+	bool leased;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
@@ -209,9 +210,13 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
 	if (!encoder)
 		return -ENOENT;
 
+	leased = drm_lease_check(file_priv->master, encoder->base.id) == 0;
+
+	DRM_DEBUG_LEASE("encoder %d leased %s\n", encoder->base.id, leased ? "true" : "false");
+
 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
 	crtc = drm_encoder_get_crtc(encoder);
-	if (crtc)
+	if (crtc && leased)
 		enc_resp->crtc_id = crtc->base.id;
 	else
 		enc_resp->crtc_id = 0;
@@ -219,8 +224,15 @@ 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;
+	if (leased) {
+		enc_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv->master,
+								  encoder->possible_crtcs);
+		enc_resp->possible_clones = drm_lease_filter_encoders(file_priv->master,
+								      encoder->possible_clones);
+	} else {
+		enc_resp->possible_crtcs = 0;
+		enc_resp->possible_clones = 0;
+	}
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index 9f17085b1fdd..9f8559d82a17 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -404,6 +404,9 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
 		goto out;
 	}
 
+	if ((ret = drm_lease_check(file_priv->master, arg->obj_id)) != 0)
+		goto out;
+
 	if (!arg_obj->properties)
 		goto out_unref;
 
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 62b98f386fd1..df811869c1dd 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -383,6 +383,7 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
 	struct drm_mode_get_plane *plane_resp = data;
 	struct drm_plane *plane;
 	uint32_t __user *format_ptr;
+	bool leased;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
@@ -391,27 +392,34 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
 	if (!plane)
 		return -ENOENT;
 
+	leased = drm_lease_check(file_priv->master, plane->base.id) == 0;
+
 	drm_modeset_lock(&plane->mutex, NULL);
-	if (plane->crtc)
+	if (plane->crtc && leased)
 		plane_resp->crtc_id = plane->crtc->base.id;
 	else
 		plane_resp->crtc_id = 0;
 
-	if (plane->fb)
+	if (plane->fb && leased)
 		plane_resp->fb_id = plane->fb->base.id;
 	else
 		plane_resp->fb_id = 0;
 	drm_modeset_unlock(&plane->mutex);
 
 	plane_resp->plane_id = plane->base.id;
-	plane_resp->possible_crtcs = plane->possible_crtcs;
+	if (leased)
+		plane_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv->master,
+								    plane->possible_crtcs);
+	else
+		plane_resp->possible_crtcs = 0;
+
 	plane_resp->gamma_size = 0;
 
 	/*
 	 * This ioctl is called twice, once to determine how much space is
 	 * needed, and the 2nd time to fill it.
 	 */
-	if (plane->format_count &&
+	if (plane->format_count && leased &&
 	    (plane_resp->count_format_types >= plane->format_count)) {
 		format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
 		if (copy_to_user(format_ptr,
@@ -420,7 +428,10 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
 			return -EFAULT;
 		}
 	}
-	plane_resp->count_format_types = plane->format_count;
+	if (leased)
+		plane_resp->count_format_types = plane->format_count;
+	else
+		plane_resp->count_format_types = 0;
 
 	return 0;
 }
@@ -551,6 +562,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
 	struct drm_plane *plane;
 	struct drm_crtc *crtc = NULL;
 	struct drm_framebuffer *fb = NULL;
+	int ret;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
@@ -566,6 +578,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
 		return -ENOENT;
 	}
 
+	if ((ret = drm_lease_check(file_priv->master, plane->base.id)) < 0) {
+		DRM_DEBUG_KMS("Plane lease not held: %d error %d\n",
+			      plane->base.id, ret);
+		return ret;
+	}
+
 	if (plane_req->fb_id) {
 		fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
 		if (!fb) {
@@ -687,6 +705,11 @@ static int drm_mode_cursor_common(struct drm_device *dev,
 		DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
 		return -ENOENT;
 	}
+	if ((ret = drm_lease_check(file_priv->master, crtc->base.id)) < 0) {
+		DRM_DEBUG_KMS("CRTC lease not held %d error %d\n",
+			      crtc->base.id, ret);
+		goto out;
+	}
 
 	/*
 	 * If this crtc has a universal cursor plane, call that plane's update
@@ -785,6 +808,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
 	if (!crtc)
 		return -ENOENT;
 
+	if ((ret = drm_lease_check(file_priv->master, crtc->base.id)) < 0)
+		return ret;
+
 	if (crtc->funcs->page_flip_target) {
 		u32 current_vblank;
 		int r;
diff --git a/include/drm/drm_lease.h b/include/drm/drm_lease.h
index e02adf3e42fd..8f91fc4226e3 100644
--- a/include/drm/drm_lease.h
+++ b/include/drm/drm_lease.h
@@ -48,4 +48,8 @@ static inline int drm_lease_check(struct drm_master *master, int id) {
 	return 0;
 }
 
+uint32_t drm_lease_filter_crtcs(struct drm_master *master, uint32_t crtcs);
+
+uint32_t drm_lease_filter_encoders(struct drm_master *master, uint32_t encoders);
+
 #endif /* _DRM_LEASE_H_ */
diff --git a/include/drm/drm_mode_object.h b/include/drm/drm_mode_object.h
index 43460b21d112..07830182598b 100644
--- a/include/drm/drm_mode_object.h
+++ b/include/drm/drm_mode_object.h
@@ -24,6 +24,7 @@
 #define __DRM_MODESET_H__
 
 #include <linux/kref.h>
+#include <drm/drm_lease.h>
 struct drm_object_properties;
 struct drm_property;
 struct drm_device;
-- 
2.11.0

  parent reply	other threads:[~2017-04-01 17:17 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-01 17:08 [PATCH 0/4] drm: Add mode resource leasing Keith Packard
2017-04-01 17:08 ` [PATCH 1/4] drm: Add new LEASE debug level Keith Packard
2017-04-01 17:08 ` [PATCH 2/4] drm: Add drm_object lease infrastructure Keith Packard
2017-04-02 13:38   ` Daniel Vetter
2017-04-02 13:38     ` Daniel Vetter
2017-04-02 16:31     ` Keith Packard
2017-04-10  5:16       ` Michel Dänzer
2017-04-10  5:16         ` Michel Dänzer
2017-04-02 17:51   ` Daniel Vetter
2017-04-02 17:51     ` Daniel Vetter
2017-04-02 19:59     ` Keith Packard
2017-04-01 17:08 ` Keith Packard [this message]
2017-04-02 13:19   ` [PATCH 3/4] drm: Check mode object lease status in all master ioctl paths Daniel Vetter
2017-04-02 13:19     ` Daniel Vetter
2017-04-02 16:37     ` Keith Packard
2017-04-03  7:49       ` Daniel Vetter
2017-04-03  7:49         ` Daniel Vetter
2017-04-10  1:06     ` Keith Packard
2017-04-10  1:06       ` Keith Packard
2017-04-01 17:08 ` [PATCH 4/4] drm: Add four ioctls for managing drm mode object leases Keith Packard
2017-04-02 13:23   ` Daniel Vetter
2017-04-02 13:23     ` Daniel Vetter
2017-04-02 16:44     ` Keith Packard
2017-04-29  6:06 ` [PATCH 0/5] drm: Add mode resource leasing [v2] Keith Packard
2017-04-29  6:06   ` Keith Packard
2017-04-29  6:06   ` [PATCH 1/5] drm: Pass struct drm_file * to __drm_mode_object_find Keith Packard
2017-04-29  6:06     ` Keith Packard
2017-04-29  6:06   ` [PATCH 2/5] drm: Add new LEASE debug level Keith Packard
2017-04-29  6:06     ` Keith Packard
2017-04-29  6:07   ` [PATCH 3/5] drm: Add drm_object lease infrastructure [v2] Keith Packard
2017-04-29  6:07     ` Keith Packard
2017-04-29  6:07   ` [PATCH 4/5] drm: Check mode object lease status in all master ioctl paths [v2] Keith Packard
2017-04-29  6:07     ` Keith Packard
2017-04-29  6:07   ` [PATCH 5/5] drm: Add three ioctls for managing drm mode object leases [v2] Keith Packard
2017-04-29  6:07     ` Keith Packard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170401170841.2643-4-keithp@keithp.com \
    --to=keithp@keithp.com \
    --cc=airlied@redhat.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.