- fb_helper: Fix NULL deref in legacy drivers (Noralf)

- leases: Ensure lessees can't connect to objects outside their perview (Daniel)
 - leases: Enforce that lessees hold the lease for implicitly set planes (Daniel)
 - leases: A few non-functional cleanups (Daniel)
 
 Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
 Cc: Noralf Trønnes <noralf@tronnes.org>
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEfxcpfMSgdnQMs+QqlvcN/ahKBwoFAlzAxJ0ACgkQlvcN/ahK
 BwrfwggAheZ3GKONVBmhjkWkLNh00a0nbw0M7iFkJkvCtTEJTqUi+ZtAKhJHM/oh
 LwvzalBLTVtYtsmwm9PGCRPS5gHKK2/Nv7+sWpUlieQyyaGvBIFwqx0RuH1wQKO+
 +igT81sJbnIFvO4nkX4sSg3S52EFHd7CLalxA8QORhZ6QyvJ2Eay1YdeBYpR8wXc
 lI4FMGei8KhckP80U8BO/NwCGYLa9y0H+fsCrSqy1b5FJ8qmvJYU7sGNoGFHS3Nq
 HoWG6uaCc9jVHVElw9UD9bvE4R/TQg5g8/irBhcElCVQ0cxqGORRcSMLxGGrcrRi
 1VF2W9kTF4TgCwDb5Q9pp6+RgLujkg==
 =rSSS
 -----END PGP SIGNATURE-----

Merge tag 'drm-misc-next-fixes-2019-04-24' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

- fb_helper: Fix NULL deref in legacy drivers (Noralf)
- leases: Ensure lessees can't connect to objects outside their perview (Daniel)
- leases: Enforce that lessees hold the lease for implicitly set planes (Daniel)
- leases: A few non-functional cleanups (Daniel)

Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Noralf Trønnes <noralf@tronnes.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Sean Paul <sean@poorly.run>
Link: https://patchwork.freedesktop.org/patch/msgid/20190424210604.GA32581@art_vandelay
This commit is contained in:
Dave Airlie 2019-04-26 11:35:40 +10:00
commit 5a67928651
8 changed files with 45 additions and 27 deletions

View File

@ -512,8 +512,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc,
} }
static int drm_atomic_plane_set_property(struct drm_plane *plane, static int drm_atomic_plane_set_property(struct drm_plane *plane,
struct drm_plane_state *state, struct drm_property *property, struct drm_plane_state *state, struct drm_file *file_priv,
uint64_t val) struct drm_property *property, uint64_t val)
{ {
struct drm_device *dev = plane->dev; struct drm_device *dev = plane->dev;
struct drm_mode_config *config = &dev->mode_config; struct drm_mode_config *config = &dev->mode_config;
@ -521,7 +521,8 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
int ret; int ret;
if (property == config->prop_fb_id) { if (property == config->prop_fb_id) {
struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val); struct drm_framebuffer *fb;
fb = drm_framebuffer_lookup(dev, file_priv, val);
drm_atomic_set_fb_for_plane(state, fb); drm_atomic_set_fb_for_plane(state, fb);
if (fb) if (fb)
drm_framebuffer_put(fb); drm_framebuffer_put(fb);
@ -537,7 +538,9 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
return -EINVAL; return -EINVAL;
} else if (property == config->prop_crtc_id) { } else if (property == config->prop_crtc_id) {
struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val); struct drm_crtc *crtc = drm_crtc_find(dev, file_priv, val);
if (val && !crtc)
return -EACCES;
return drm_atomic_set_crtc_for_plane(state, crtc); return drm_atomic_set_crtc_for_plane(state, crtc);
} else if (property == config->prop_crtc_x) { } else if (property == config->prop_crtc_x) {
state->crtc_x = U642I64(val); state->crtc_x = U642I64(val);
@ -668,14 +671,16 @@ static int drm_atomic_set_writeback_fb_for_connector(
} }
static int drm_atomic_connector_set_property(struct drm_connector *connector, static int drm_atomic_connector_set_property(struct drm_connector *connector,
struct drm_connector_state *state, struct drm_property *property, struct drm_connector_state *state, struct drm_file *file_priv,
uint64_t val) struct drm_property *property, uint64_t val)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_mode_config *config = &dev->mode_config; struct drm_mode_config *config = &dev->mode_config;
if (property == config->prop_crtc_id) { if (property == config->prop_crtc_id) {
struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val); struct drm_crtc *crtc = drm_crtc_find(dev, file_priv, val);
if (val && !crtc)
return -EACCES;
return drm_atomic_set_crtc_for_connector(state, crtc); return drm_atomic_set_crtc_for_connector(state, crtc);
} else if (property == config->dpms_property) { } else if (property == config->dpms_property) {
/* setting DPMS property requires special handling, which /* setting DPMS property requires special handling, which
@ -736,8 +741,10 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
} else if (property == connector->colorspace_property) { } else if (property == connector->colorspace_property) {
state->colorspace = val; state->colorspace = val;
} else if (property == config->writeback_fb_id_property) { } else if (property == config->writeback_fb_id_property) {
struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val); struct drm_framebuffer *fb;
int ret = drm_atomic_set_writeback_fb_for_connector(state, fb); int ret;
fb = drm_framebuffer_lookup(dev, file_priv, val);
ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
if (fb) if (fb)
drm_framebuffer_put(fb); drm_framebuffer_put(fb);
return ret; return ret;
@ -934,6 +941,7 @@ out:
} }
int drm_atomic_set_property(struct drm_atomic_state *state, int drm_atomic_set_property(struct drm_atomic_state *state,
struct drm_file *file_priv,
struct drm_mode_object *obj, struct drm_mode_object *obj,
struct drm_property *prop, struct drm_property *prop,
uint64_t prop_value) uint64_t prop_value)
@ -956,7 +964,8 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
} }
ret = drm_atomic_connector_set_property(connector, ret = drm_atomic_connector_set_property(connector,
connector_state, prop, prop_value); connector_state, file_priv,
prop, prop_value);
break; break;
} }
case DRM_MODE_OBJECT_CRTC: { case DRM_MODE_OBJECT_CRTC: {
@ -984,7 +993,8 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
} }
ret = drm_atomic_plane_set_property(plane, ret = drm_atomic_plane_set_property(plane,
plane_state, prop, prop_value); plane_state, file_priv,
prop, prop_value);
break; break;
} }
default: default:
@ -1354,8 +1364,8 @@ retry:
goto out; goto out;
} }
ret = drm_atomic_set_property(state, obj, prop, ret = drm_atomic_set_property(state, file_priv,
prop_value); obj, prop, prop_value);
if (ret) { if (ret) {
drm_mode_object_put(obj); drm_mode_object_put(obj);
goto out; goto out;

View File

@ -108,8 +108,6 @@ struct drm_master *drm_master_create(struct drm_device *dev)
master->dev = dev; master->dev = dev;
/* initialize the tree of output resource lessees */ /* initialize the tree of output resource lessees */
master->lessor = NULL;
master->lessee_id = 0;
INIT_LIST_HEAD(&master->lessees); INIT_LIST_HEAD(&master->lessees);
INIT_LIST_HEAD(&master->lessee_list); INIT_LIST_HEAD(&master->lessee_list);
idr_init(&master->leases); idr_init(&master->leases);

View File

@ -559,6 +559,10 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
plane = crtc->primary; plane = crtc->primary;
/* allow disabling with the primary plane leased */
if (crtc_req->mode_valid && !drm_lease_held(file_priv, plane->base.id))
return -EACCES;
mutex_lock(&crtc->dev->mode_config.mutex); mutex_lock(&crtc->dev->mode_config.mutex);
DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx,
DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret); DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);

View File

@ -214,6 +214,7 @@ int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
struct drm_connector *connector, struct drm_connector *connector,
int mode); int mode);
int drm_atomic_set_property(struct drm_atomic_state *state, int drm_atomic_set_property(struct drm_atomic_state *state,
struct drm_file *file_priv,
struct drm_mode_object *obj, struct drm_mode_object *obj,
struct drm_property *prop, struct drm_property *prop,
uint64_t prop_value); uint64_t prop_value);

View File

@ -2588,6 +2588,9 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper,
int num_connectors_detected = 0; int num_connectors_detected = 0;
struct drm_modeset_acquire_ctx ctx; struct drm_modeset_acquire_ctx ctx;
if (!drm_drv_uses_atomic_modeset(dev))
return false;
save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL); save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL);
if (!save_enabled) if (!save_enabled)
return false; return false;

View File

@ -111,7 +111,7 @@ static bool _drm_has_leased(struct drm_master *master, int id)
*/ */
bool _drm_lease_held(struct drm_file *file_priv, int id) bool _drm_lease_held(struct drm_file *file_priv, int id)
{ {
if (file_priv == NULL || file_priv->master == NULL) if (!file_priv || !file_priv->master)
return true; return true;
return _drm_lease_held_master(file_priv->master, id); return _drm_lease_held_master(file_priv->master, id);
@ -133,7 +133,7 @@ bool drm_lease_held(struct drm_file *file_priv, int id)
struct drm_master *master; struct drm_master *master;
bool ret; bool ret;
if (file_priv == NULL || file_priv->master == NULL) if (!file_priv || !file_priv->master || !file_priv->master->lessor)
return true; return true;
master = file_priv->master; master = file_priv->master;
@ -159,7 +159,7 @@ uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in)
int count_in, count_out; int count_in, count_out;
uint32_t crtcs_out = 0; uint32_t crtcs_out = 0;
if (file_priv == NULL || file_priv->master == NULL) if (!file_priv || !file_priv->master || !file_priv->master->lessor)
return crtcs_in; return crtcs_in;
master = file_priv->master; master = file_priv->master;
@ -220,8 +220,6 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr
error = 0; error = 0;
if (!idr_find(&dev->mode_config.object_idr, object)) if (!idr_find(&dev->mode_config.object_idr, object))
error = -ENOENT; error = -ENOENT;
else if (!_drm_lease_held_master(lessor, object))
error = -EACCES;
else if (_drm_has_leased(lessor, object)) else if (_drm_has_leased(lessor, object))
error = -EBUSY; error = -EBUSY;
@ -403,11 +401,6 @@ static int fill_object_idr(struct drm_device *dev,
/* step one - get references to all the mode objects /* step one - get references to all the mode objects
and check for validity. */ and check for validity. */
for (o = 0; o < object_count; o++) { for (o = 0; o < object_count; o++) {
if ((int) object_ids[o] < 0) {
ret = -EINVAL;
goto out_free_objects;
}
objects[o] = drm_mode_object_find(dev, lessor_priv, objects[o] = drm_mode_object_find(dev, lessor_priv,
object_ids[o], object_ids[o],
DRM_MODE_OBJECT_ANY); DRM_MODE_OBJECT_ANY);

View File

@ -451,6 +451,7 @@ static int set_property_legacy(struct drm_mode_object *obj,
} }
static int set_property_atomic(struct drm_mode_object *obj, static int set_property_atomic(struct drm_mode_object *obj,
struct drm_file *file_priv,
struct drm_property *prop, struct drm_property *prop,
uint64_t prop_value) uint64_t prop_value)
{ {
@ -477,7 +478,7 @@ retry:
obj_to_connector(obj), obj_to_connector(obj),
prop_value); prop_value);
} else { } else {
ret = drm_atomic_set_property(state, obj, prop, prop_value); ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value);
if (ret) if (ret)
goto out; goto out;
ret = drm_atomic_commit(state); ret = drm_atomic_commit(state);
@ -520,7 +521,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
goto out_unref; goto out_unref;
if (drm_drv_uses_atomic_modeset(property->dev)) if (drm_drv_uses_atomic_modeset(property->dev))
ret = set_property_atomic(arg_obj, property, arg->value); ret = set_property_atomic(arg_obj, file_priv, property, arg->value);
else else
ret = set_property_legacy(arg_obj, property, arg->value); ret = set_property_legacy(arg_obj, property, arg->value);

View File

@ -960,6 +960,11 @@ retry:
if (ret) if (ret)
goto out; goto out;
if (!drm_lease_held(file_priv, crtc->cursor->base.id)) {
ret = -EACCES;
goto out;
}
ret = drm_mode_cursor_universal(crtc, req, file_priv, &ctx); ret = drm_mode_cursor_universal(crtc, req, file_priv, &ctx);
goto out; goto out;
} }
@ -1062,6 +1067,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
plane = crtc->primary; plane = crtc->primary;
if (!drm_lease_held(file_priv, plane->base.id))
return -EACCES;
if (crtc->funcs->page_flip_target) { if (crtc->funcs->page_flip_target) {
u32 current_vblank; u32 current_vblank;
int r; int r;