[RFC wayland] wayland-server: assert instead of posting events with wrong client objects

Pekka Paalanen ppaalanen at gmail.com
Thu Dec 8 20:54:40 UTC 2016


On Thu, 8 Dec 2016 13:28:41 -0600
Derek Foreman <derekf at osg.samsung.com> wrote:

> On 02/12/16 02:07 AM, Pekka Paalanen wrote:
> > On Thu,  1 Dec 2016 17:19:41 -0600
> > Derek Foreman <derekf at osg.samsung.com> wrote:
> >  
> >> 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
> >> kill itself.
> >>
> >> It's intended that the compositor killing itself be easier to debug
> >> than the client killing itself for something that it's completely
> >> innocent of.
> >>
> >> Signed-off-by: Derek Foreman <derekf at osg.samsung.com>
> >> ---
> >>
> >> Recently caught a bug in Enlightenment where we were posting keyboard enter
> >> events with a surface from another client.  In most cases this results in
> >> the client disconnecting itself due to the target object being the wrong type.
> >> It might be more hilarious if the types just magically happened to match.
> >>
> >> Are we interested in this level of footgun protection?
> >>
> >> It's also been suggested that this might be better if conditional on
> >> WAYLAND_DEBUG.  
> >
> > Hi Derek,
> >
> > this is something I have been wanting for a long time. So far I only
> > wrote down what we should have with libwayland-client:
> > https://phabricator.freedesktop.org/T50  
> 
> That is a nice list. :)
> 
> Glad I'm not the only one that wants this.

Hi,

a quick reply in the middle of the night...

> > IMO, your check should not be an assert, it should be an unconditional
> > abort() with no way to disable it and a clear log message. Like a
> > segfault is, only better.
> >
> > A compositor that handles SEGVs and ABRTs will then also provide a
> > backtrace that should be very helpful in squashing the bug.
> >
> > However, it seems our existing convention is to just kill the client on
> > compositor programming errors (e.g. wl_closure_marshal() failing on
> > nullable violation). I don't really like that, but it's a precedent and
> > the very least we can detect the problem and yell rather than have
> > clients mysteriously fail.  
> 
> I think it would be trivial to catch nullable violation from the 
> compositor in the same place where I'm testing for accidental mixing of 
> client objects.
> 
> I don't think we should remove any client side sanity checks, but adding 
> that check on the compositor side seems like a win for debugging to me. 
> Should I do this too?

Sure. The nullable violation is already checked, it might only miss
a good log message. Server makes a mistake, the client is
disconnected when the error is detected...

> > libwayland-client does call wl_abort() on such failures.
> >  
> >>  src/wayland-server.c | 23 +++++++++++++++++++++++
> >>  1 file changed, 23 insertions(+)
> >>
> >> diff --git a/src/wayland-server.c b/src/wayland-server.c
> >> index 9d7d9c1..bf1719a 100644
> >> --- a/src/wayland-server.c
> >> +++ b/src/wayland-server.c
> >> @@ -160,6 +160,27 @@ log_closure(struct wl_resource *resource,
> >>  	}
> >>  }
> >>
> >> +static bool
> >> +clients_match(struct wl_resource *resource, uint32_t opcode,
> >> +	      union wl_argument *args)
> >> +{
> >> +	struct wl_object *object = &resource->object;
> >> +	const char *sig = object->interface->events[opcode].signature;
> >> +
> >> +	for (;*sig;sig++) {
> >> +		if (*sig == '?')
> >> +			continue;  
> >
> > How about skipping version numbers as well?  
> 
> Are there actually version numbers that have a place in the signature 
> but no associated argument?  My read of get_next_argument left me 
> thinking that only ? was present without an argument.
> 
> This is really an academic question because...
> 
> > I believe there should be similar parsing functions elsewhere to either
> > follow or even reuse/refactor.  
> 
> Yes, there's get_next_argument, which I've re-written my patch to use. 
> So I think that should handle any appropriate skipping that I may have 
> otherwise missed?

I'd hope so.

> >> +
> >> +		if (*sig == 'o') {  
> >
> > I think you would also want to handle new_id args. Events with new_id
> > are rare, but they do exist (wl_data_device.data_offer).  
> 
> I'm not sure how to do this.  new_id will just give me a number, and I 
> think it would be complicated to ensure that the id is for the correct 
> client?

I thought that when sending events with new_id, the compositor
passes in wl_resource, not an uint32_t. It needs to create the
wl_resource right before sending the event, IIRC.


Thanks,
pq

> I wouldn't mind putting this down for "further work at a later date". :)
> 
> I'll follow up shortly with a new patch.
> 
> Thanks,
> Derek
> 
> >> +			struct wl_resource *res = (struct wl_resource *) (args->o);
> >> +			if (res && res->client != resource->client)
> >> +				return false;
> >> +		}
> >> +		args++;
> >> +	}
> >> +	return true;
> >> +}
> >> +
> >>  WL_EXPORT void
> >>  wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode,
> >>  			     union wl_argument *args)
> >> @@ -167,6 +188,7 @@ wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode,
> >>  	struct wl_closure *closure;
> >>  	struct wl_object *object = &resource->object;
> >>
> >> +	assert(clients_match(resource, opcode, args));
> >>  	closure = wl_closure_marshal(object, opcode, args,
> >>  				     &object->interface->events[opcode]);
> >>
> >> @@ -206,6 +228,7 @@ wl_resource_queue_event_array(struct wl_resource *resource, uint32_t opcode,
> >>  	struct wl_closure *closure;
> >>  	struct wl_object *object = &resource->object;
> >>
> >> +	assert(clients_match(resource, opcode, args));
> >>  	closure = wl_closure_marshal(object, opcode, args,
> >>  				     &object->interface->events[opcode]);
> >>  
> >
> > A good idea, all in all.
> >
> >
> > Thanks,
> > pq
> >  
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 801 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20161208/bc3a7511/attachment.sig>


More information about the wayland-devel mailing list