mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 12:43:55 +08:00
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>
This commit is contained in:
parent
2ed077e467
commit
7de440db20
@ -310,7 +310,7 @@ out:
|
||||
*/
|
||||
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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -122,10 +122,12 @@ 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 (count < card_res->count_crtcs &&
|
||||
put_user(crtc->base.id, crtc_id + count))
|
||||
return -EFAULT;
|
||||
count++;
|
||||
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;
|
||||
|
||||
@ -143,12 +145,14 @@ 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 (count < card_res->count_connectors &&
|
||||
put_user(connector->base.id, connector_id + count)) {
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
return -EFAULT;
|
||||
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);
|
||||
return -EFAULT;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
card_res->count_connectors = count;
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
|
@ -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;
|
||||
|
@ -479,10 +479,12 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
|
||||
!file_priv->universal_planes)
|
||||
continue;
|
||||
|
||||
if (count < plane_resp->count_planes &&
|
||||
put_user(plane->base.id, plane_ptr + count))
|
||||
return -EFAULT;
|
||||
count++;
|
||||
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;
|
||||
|
||||
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -1447,10 +1447,12 @@ static void drm_wait_vblank_reply(struct drm_device *dev, unsigned int pipe,
|
||||
int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_vblank_crtc *vblank;
|
||||
union drm_wait_vblank *vblwait = data;
|
||||
int ret;
|
||||
u64 req_seq, seq;
|
||||
unsigned int pipe_index;
|
||||
unsigned int flags, pipe, high_pipe;
|
||||
|
||||
if (!dev->irq_enabled)
|
||||
@ -1472,9 +1474,25 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
|
||||
flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
|
||||
high_pipe = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
|
||||
if (high_pipe)
|
||||
pipe = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
|
||||
pipe_index = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
|
||||
else
|
||||
pipe = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
|
||||
pipe_index = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
|
||||
|
||||
/* Convert lease-relative crtc index into global crtc index */
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
pipe = 0;
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
if (drm_lease_held(file_priv, crtc->base.id)) {
|
||||
if (pipe_index == 0)
|
||||
break;
|
||||
pipe_index--;
|
||||
}
|
||||
pipe++;
|
||||
}
|
||||
} else {
|
||||
pipe = pipe_index;
|
||||
}
|
||||
|
||||
if (pipe >= dev->num_crtcs)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -31,6 +31,4 @@ void drm_lease_revoke(struct drm_master *master);
|
||||
|
||||
uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs);
|
||||
|
||||
uint32_t drm_lease_filter_encoders(struct drm_file *file_priv, uint32_t encoders);
|
||||
|
||||
#endif /* _DRM_LEASE_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user