[PATCH v3 wayland] wayland-server: log an error for events with wrong client objects

Derek Foreman derekf at osg.samsung.com
Mon Dec 12 20:14:45 UTC 2016


Check that all the objects in an event belong to the same client as
the resource posting it.  This prevents a compositor from accidentally
mixing client objects and posting an event that causes a client to
abort with a cryptic message.

Instead the client will now be disconnected as it is when the compositor
tries to send a null for a non-nullable object, and a log message
will be printed by the compositor.

Signed-off-by: Derek Foreman <derekf at osg.samsung.com>
---

This started life as an assert, became an abort, and now it's a log
and disconnect.  Log and disconnect is already how we manage nullable
violation on the compositor side, so I'm hoping it won't be too
controversial.

For EFL clients the disconnect is recoverable under some circumstances with
our session recovery protocol, but the current client-abort()s behaviour
is not.

Changes from v1:
uses get_next_arguemnts and arg_count_for_signature instead of a bespoke
implementation.

Changes from v2:
Tests new_id objects as well
logs and disconnects instead of assert()/abort()
superficial changes to the log text



 src/wayland-server.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/src/wayland-server.c b/src/wayland-server.c
index 9d7d9c1..d9c7750 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -160,6 +160,35 @@ log_closure(struct wl_resource *resource,
 	}
 }
 
+static bool
+verify_objects(struct wl_resource *resource, uint32_t opcode,
+	      union wl_argument *args)
+{
+	struct wl_object *object = &resource->object;
+	const char *signature = object->interface->events[opcode].signature;
+	struct argument_details arg;
+	struct wl_resource *res;
+	int count, i;
+
+	count = arg_count_for_signature(signature);
+	for (i = 0; i < count; i++) {
+		signature = get_next_argument(signature, &arg);
+		switch (arg.type) {
+		case 'n':
+		case 'o':
+			res = (struct wl_resource *) (args[i].o);
+			if (res && res->client != resource->client) {
+				wl_log("compositor bug: The compositor "
+				       "tried to use an object from one "
+				       "client in an event for a different "
+				       "client.\n");
+				return false;
+			}
+		}
+	}
+	return true;
+}
+
 WL_EXPORT void
 wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode,
 			     union wl_argument *args)
@@ -167,6 +196,10 @@ wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode,
 	struct wl_closure *closure;
 	struct wl_object *object = &resource->object;
 
+	if (!verify_objects(resource, opcode, args)) {
+		resource->client->error = 1;
+		return;
+	}
 	closure = wl_closure_marshal(object, opcode, args,
 				     &object->interface->events[opcode]);
 
@@ -206,6 +239,10 @@ wl_resource_queue_event_array(struct wl_resource *resource, uint32_t opcode,
 	struct wl_closure *closure;
 	struct wl_object *object = &resource->object;
 
+	if (!verify_objects(resource, opcode, args)) {
+		resource->client->error = 1;
+		return;
+	}
 	closure = wl_closure_marshal(object, opcode, args,
 				     &object->interface->events[opcode]);
 
-- 
2.11.0



More information about the wayland-devel mailing list