Skip to content

Commit 7de440d

Browse files
keith-packardairlied
authored andcommitted
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: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
1 parent 2ed077e commit 7de440d

File tree

7 files changed

+70
-23
lines changed

7 files changed

+70
-23
lines changed

drivers/gpu/drm/drm_auth.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ void drm_master_release(struct drm_file *file_priv)
310310
*/
311311
bool drm_is_current_master(struct drm_file *fpriv)
312312
{
313-
return fpriv->is_master && fpriv->master == fpriv->minor->dev->master;
313+
return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master;
314314
}
315315
EXPORT_SYMBOL(drm_is_current_master);
316316

drivers/gpu/drm/drm_encoder.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,16 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
226226

227227
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
228228
crtc = drm_encoder_get_crtc(encoder);
229-
if (crtc)
229+
if (crtc && drm_lease_held(file_priv, crtc->base.id))
230230
enc_resp->crtc_id = crtc->base.id;
231231
else
232232
enc_resp->crtc_id = 0;
233233
drm_modeset_unlock(&dev->mode_config.connection_mutex);
234234

235235
enc_resp->encoder_type = encoder->encoder_type;
236236
enc_resp->encoder_id = encoder->base.id;
237-
enc_resp->possible_crtcs = encoder->possible_crtcs;
237+
enc_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
238+
encoder->possible_crtcs);
238239
enc_resp->possible_clones = encoder->possible_clones;
239240

240241
return 0;

drivers/gpu/drm/drm_mode_config.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,12 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
122122
count = 0;
123123
crtc_id = u64_to_user_ptr(card_res->crtc_id_ptr);
124124
drm_for_each_crtc(crtc, dev) {
125-
if (count < card_res->count_crtcs &&
126-
put_user(crtc->base.id, crtc_id + count))
127-
return -EFAULT;
128-
count++;
125+
if (drm_lease_held(file_priv, crtc->base.id)) {
126+
if (count < card_res->count_crtcs &&
127+
put_user(crtc->base.id, crtc_id + count))
128+
return -EFAULT;
129+
count++;
130+
}
129131
}
130132
card_res->count_crtcs = count;
131133

@@ -143,12 +145,14 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
143145
count = 0;
144146
connector_id = u64_to_user_ptr(card_res->connector_id_ptr);
145147
drm_for_each_connector_iter(connector, &conn_iter) {
146-
if (count < card_res->count_connectors &&
147-
put_user(connector->base.id, connector_id + count)) {
148-
drm_connector_list_iter_end(&conn_iter);
149-
return -EFAULT;
148+
if (drm_lease_held(file_priv, connector->base.id)) {
149+
if (count < card_res->count_connectors &&
150+
put_user(connector->base.id, connector_id + count)) {
151+
drm_connector_list_iter_end(&conn_iter);
152+
return -EFAULT;
153+
}
154+
count++;
150155
}
151-
count++;
152156
}
153157
card_res->count_connectors = count;
154158
drm_connector_list_iter_end(&conn_iter);

drivers/gpu/drm/drm_mode_object.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,25 @@ void drm_mode_object_unregister(struct drm_device *dev,
104104
mutex_unlock(&dev->mode_config.idr_mutex);
105105
}
106106

107+
/**
108+
* drm_lease_required - check types which must be leased to be used
109+
* @type: type of object
110+
*
111+
* Returns whether the provided type of drm_mode_object must
112+
* be owned or leased to be used by a process.
113+
*/
114+
static bool drm_lease_required(uint32_t type)
115+
{
116+
switch(type) {
117+
case DRM_MODE_OBJECT_CRTC:
118+
case DRM_MODE_OBJECT_CONNECTOR:
119+
case DRM_MODE_OBJECT_PLANE:
120+
return true;
121+
default:
122+
return false;
123+
}
124+
}
125+
107126
struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
108127
struct drm_file *file_priv,
109128
uint32_t id, uint32_t type)
@@ -117,6 +136,9 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
117136
if (obj && obj->id != id)
118137
obj = NULL;
119138

139+
if (obj && drm_lease_required(obj->type) && !_drm_lease_held(file_priv, obj->id))
140+
obj = NULL;
141+
120142
if (obj && obj->free_cb) {
121143
if (!kref_get_unless_zero(&obj->refcount))
122144
obj = NULL;

drivers/gpu/drm/drm_plane.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -479,10 +479,12 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
479479
!file_priv->universal_planes)
480480
continue;
481481

482-
if (count < plane_resp->count_planes &&
483-
put_user(plane->base.id, plane_ptr + count))
484-
return -EFAULT;
485-
count++;
482+
if (drm_lease_held(file_priv, plane->base.id)) {
483+
if (count < plane_resp->count_planes &&
484+
put_user(plane->base.id, plane_ptr + count))
485+
return -EFAULT;
486+
count++;
487+
}
486488
}
487489
plane_resp->count_planes = count;
488490

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

506508
drm_modeset_lock(&plane->mutex, NULL);
507-
if (plane->state && plane->state->crtc)
509+
if (plane->state && plane->state->crtc && drm_lease_held(file_priv, plane->state->crtc->base.id))
508510
plane_resp->crtc_id = plane->state->crtc->base.id;
509-
else if (!plane->state && plane->crtc)
511+
else if (!plane->state && plane->crtc && drm_lease_held(file_priv, plane->crtc->base.id))
510512
plane_resp->crtc_id = plane->crtc->base.id;
511513
else
512514
plane_resp->crtc_id = 0;
@@ -520,7 +522,9 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
520522
drm_modeset_unlock(&plane->mutex);
521523

522524
plane_resp->plane_id = plane->base.id;
523-
plane_resp->possible_crtcs = plane->possible_crtcs;
525+
plane_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
526+
plane->possible_crtcs);
527+
524528
plane_resp->gamma_size = 0;
525529

526530
/*

drivers/gpu/drm/drm_vblank.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,10 +1447,12 @@ static void drm_wait_vblank_reply(struct drm_device *dev, unsigned int pipe,
14471447
int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
14481448
struct drm_file *file_priv)
14491449
{
1450+
struct drm_crtc *crtc;
14501451
struct drm_vblank_crtc *vblank;
14511452
union drm_wait_vblank *vblwait = data;
14521453
int ret;
14531454
u64 req_seq, seq;
1455+
unsigned int pipe_index;
14541456
unsigned int flags, pipe, high_pipe;
14551457

14561458
if (!dev->irq_enabled)
@@ -1472,9 +1474,25 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
14721474
flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
14731475
high_pipe = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
14741476
if (high_pipe)
1475-
pipe = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
1477+
pipe_index = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
14761478
else
1477-
pipe = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
1479+
pipe_index = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
1480+
1481+
/* Convert lease-relative crtc index into global crtc index */
1482+
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
1483+
pipe = 0;
1484+
drm_for_each_crtc(crtc, dev) {
1485+
if (drm_lease_held(file_priv, crtc->base.id)) {
1486+
if (pipe_index == 0)
1487+
break;
1488+
pipe_index--;
1489+
}
1490+
pipe++;
1491+
}
1492+
} else {
1493+
pipe = pipe_index;
1494+
}
1495+
14781496
if (pipe >= dev->num_crtcs)
14791497
return -EINVAL;
14801498

include/drm/drm_lease.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,4 @@ void drm_lease_revoke(struct drm_master *master);
3131

3232
uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs);
3333

34-
uint32_t drm_lease_filter_encoders(struct drm_file *file_priv, uint32_t encoders);
35-
3634
#endif /* _DRM_LEASE_H_ */

0 commit comments

Comments
 (0)