From ffc011d6a30d5e772e4f849abc5c60faf3ecb91a Mon Sep 17 00:00:00 2001
From: Philipp Zabel
Date: Thu, 11 Mar 2021 11:04:32 +0100
Subject: [PATCH] backend-drm: check that outputs and heads are in fact ours
As a first step towards heterogeneous outputs, ignore other backends'
heads and outputs. This is done by checking the destroy callbacks for
heads and outputs.
See: https://gitlab.freedesktop.org/wayland/weston/-/issues/268
Signed-off-by: Philipp Zabel
---
libweston/backend-drm/drm-internal.h | 16 ++++++++++
libweston/backend-drm/drm-virtual.c | 2 +-
libweston/backend-drm/drm.c | 42 ++++++++++++++++++---------
libweston/backend-drm/kms.c | 2 ++
libweston/backend-drm/state-propose.c | 2 ++
5 files changed, 50 insertions(+), 14 deletions(-)
diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h
index 77200f2f..60ab2352 100644
--- a/libweston/backend-drm/drm-internal.h
+++ b/libweston/backend-drm/drm-internal.h
@@ -584,15 +584,31 @@ struct drm_output {
submit_frame_cb virtual_submit_frame;
};
+void
+drm_head_destroy(struct weston_head *head_base);
+
static inline struct drm_head *
to_drm_head(struct weston_head *base)
{
+ if (base->backend_id != drm_head_destroy)
+ return NULL;
return container_of(base, struct drm_head, base);
}
+void
+drm_output_destroy(struct weston_output *output_base);
+void
+drm_virtual_output_destroy(struct weston_output *output_base);
+
static inline struct drm_output *
to_drm_output(struct weston_output *base)
{
+ if (
+#ifdef BUILD_DRM_VIRTUAL
+ base->destroy != drm_virtual_output_destroy &&
+#endif
+ base->destroy != drm_output_destroy)
+ return NULL;
return container_of(base, struct drm_output, base);
}
diff --git a/libweston/backend-drm/drm-virtual.c b/libweston/backend-drm/drm-virtual.c
index 8f1d3abf..cf8de76a 100644
--- a/libweston/backend-drm/drm-virtual.c
+++ b/libweston/backend-drm/drm-virtual.c
@@ -245,7 +245,7 @@ drm_virtual_output_deinit(struct weston_output *base)
drm_virtual_crtc_destroy(output->crtc);
}
-static void
+void
drm_virtual_output_destroy(struct weston_output *base)
{
struct drm_output *output = to_drm_output(base);
diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c
index aa55fc41..f06d8c72 100644
--- a/libweston/backend-drm/drm.c
+++ b/libweston/backend-drm/drm.c
@@ -164,9 +164,6 @@ drm_output_pageflip_timer_create(struct drm_output *output)
return 0;
}
-static void
-drm_output_destroy(struct weston_output *output_base);
-
/**
* Returns true if the plane can be used on the given output for its current
* repaint cycle.
@@ -214,6 +211,8 @@ drm_head_find_by_connector(struct drm_backend *backend, uint32_t connector_id)
wl_list_for_each(base,
&backend->compositor->head_list, compositor_link) {
head = to_drm_head(base);
+ if (!head)
+ continue;
if (head->connector.connector_id == connector_id)
return head;
}
@@ -451,6 +450,7 @@ drm_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
struct drm_pending_state *pending_state;
struct drm_device *device;
+ assert(output);
assert(!output->virtual);
device = output->device;
@@ -689,8 +689,11 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
struct drm_output *output = to_drm_output(output_base);
struct drm_device *device = output->device;
struct drm_backend *b = device->backend;
- struct drm_mode *drm_mode = drm_output_choose_mode(output, mode);
+ struct drm_mode *drm_mode;
+
+ assert(output);
+ drm_mode = drm_output_choose_mode(output, mode);
if (!drm_mode) {
weston_log("%s: invalid resolution %dx%d\n",
output_base->name, mode->width, mode->height);
@@ -1053,6 +1056,7 @@ drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
struct drm_output_state *state;
int ret;
+ assert(output);
assert(!output->virtual);
if (output->state_cur->dpms == level)
@@ -1491,6 +1495,8 @@ drm_output_pick_crtc(struct drm_output *output)
match = false;
wl_list_for_each(base, &compositor->head_list, compositor_link) {
head = to_drm_head(base);
+ if (!head)
+ continue;
if (head->base.output == &output->base)
continue;
@@ -1808,6 +1814,7 @@ drm_output_enable(struct weston_output *base)
struct drm_backend *b = device->backend;
int ret;
+ assert(output);
assert(!output->virtual);
if (output->gbm_format == DRM_FORMAT_INVALID) {
@@ -1885,15 +1892,13 @@ drm_output_deinit(struct weston_output *base)
}
}
-static void
-drm_head_destroy(struct drm_head *head);
-
-static void
+void
drm_output_destroy(struct weston_output *base)
{
struct drm_output *output = to_drm_output(base);
struct drm_device *device = output->device;
+ assert(output);
assert(!output->virtual);
if (output->page_flip_pending || output->atomic_complete_pending) {
@@ -1927,6 +1932,7 @@ drm_output_disable(struct weston_output *base)
{
struct drm_output *output = to_drm_output(base);
+ assert(output);
assert(!output->virtual);
if (output->page_flip_pending || output->atomic_complete_pending) {
@@ -2197,6 +2203,8 @@ drm_head_create(struct drm_device *device, drmModeConnector *conn,
weston_head_init(&head->base, name);
free(name);
+ head->base.backend_id = drm_head_destroy;
+
ret = drm_head_update_info(head, conn);
if (ret < 0)
goto err_update;
@@ -2226,9 +2234,13 @@ err:
return -1;
}
-static void
-drm_head_destroy(struct drm_head *head)
+void
+drm_head_destroy(struct weston_head *base)
{
+ struct drm_head *head = to_drm_head(base);
+
+ assert(head);
+
weston_head_release(&head->base);
drm_connector_fini(&head->connector);
@@ -2466,6 +2478,8 @@ drm_backend_update_connectors(struct drm_device *device,
wl_list_for_each_safe(base, base_next,
&b->compositor->head_list, compositor_link) {
head = to_drm_head(base);
+ if (!head)
+ continue;
connector_id = head->connector.connector_id;
if (head->connector.device != device)
@@ -2476,7 +2490,7 @@ drm_backend_update_connectors(struct drm_device *device,
weston_log("DRM: head '%s' (connector %d) disappeared.\n",
head->base.name, connector_id);
- drm_head_destroy(head);
+ drm_head_destroy(base);
}
/* Destroy writeback objects of writeback connectors that have
@@ -2630,8 +2644,10 @@ drm_destroy(struct weston_compositor *ec)
wl_list_for_each_safe(crtc, crtc_tmp, &b->drm->crtc_list, link)
drm_crtc_destroy(crtc);
- wl_list_for_each_safe(base, next, &ec->head_list, compositor_link)
- drm_head_destroy(to_drm_head(base));
+ wl_list_for_each_safe(base, next, &ec->head_list, compositor_link) {
+ if (to_drm_head(base))
+ drm_head_destroy(base);
+ }
wl_list_for_each_safe(writeback, writeback_tmp,
&b->drm->writeback_connector_list, link)
diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c
index dbdf72e4..d1be5dbe 100644
--- a/libweston/backend-drm/kms.c
+++ b/libweston/backend-drm/kms.c
@@ -487,6 +487,8 @@ drm_output_set_gamma(struct weston_output *output_base,
struct drm_output *output = to_drm_output(output_base);
struct drm_device *device = output->device;
+ assert(output);
+
/* check */
if (output_base->gamma_size != size)
return;
diff --git a/libweston/backend-drm/state-propose.c b/libweston/backend-drm/state-propose.c
index 83b0e049..1f4dccc7 100644
--- a/libweston/backend-drm/state-propose.c
+++ b/libweston/backend-drm/state-propose.c
@@ -926,6 +926,8 @@ drm_assign_planes(struct weston_output *output_base)
struct weston_plane *primary = &output_base->compositor->primary_plane;
enum drm_output_propose_state_mode mode = DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY;
+ assert(output);
+
drm_debug(b, "\t[repaint] preparing state for output %s (%lu)\n",
output_base->name, (unsigned long) output_base->id);