From 215f894965df5fb0bb45b107d84524e700d2073c Mon Sep 17 00:00:00 2001 From: Michal Srb Date: Wed, 24 May 2017 15:54:40 +0300 Subject: dix: Disallow GenericEvent in SendEvent request. The SendEvent request holds xEvent which is exactly 32 bytes long, no more, no less. Both ProcSendEvent and SProcSendEvent verify that the received data exactly match the request size. However nothing stops the client from passing in event with xEvent::type = GenericEvent and any value of xGenericEvent::length. In the case of ProcSendEvent, the event will be eventually passed to WriteEventsToClient which will see that it is Generic event and copy the arbitrary length from the receive buffer (and possibly past it) and send it to the other client. This allows clients to copy unitialized heap memory out of X server or to crash it. In case of SProcSendEvent, it will attempt to swap the incoming event by calling a swapping function from the EventSwapVector array. The swapped event is written to target buffer, which in this case is local xEvent variable. The xEvent variable is 32 bytes long, but the swapping functions for GenericEvents expect that the target buffer has size matching the size of the source GenericEvent. This allows clients to cause stack buffer overflows. Signed-off-by: Michal Srb Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer diff --git a/dix/events.c b/dix/events.c index 3e3a01e..d3a33ea 100644 --- a/dix/events.c +++ b/dix/events.c @@ -5366,6 +5366,12 @@ ProcSendEvent(ClientPtr client) client->errorValue = stuff->event.u.u.type; return BadValue; } + /* Generic events can have variable size, but SendEvent request holds + exactly 32B of event data. */ + if (stuff->event.u.u.type == GenericEvent) { + client->errorValue = stuff->event.u.u.type; + return BadValue; + } if (stuff->event.u.u.type == ClientMessage && stuff->event.u.u.detail != 8 && stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) { diff --git a/dix/swapreq.c b/dix/swapreq.c index 719e9b8..6785059 100644 --- a/dix/swapreq.c +++ b/dix/swapreq.c @@ -292,6 +292,13 @@ SProcSendEvent(ClientPtr client) swapl(&stuff->destination); swapl(&stuff->eventMask); + /* Generic events can have variable size, but SendEvent request holds + exactly 32B of event data. */ + if (stuff->event.u.u.type == GenericEvent) { + client->errorValue = stuff->event.u.u.type; + return BadValue; + } + /* Swap event */ proc = EventSwapVector[stuff->event.u.u.type & 0177]; if (!proc || proc == NotImplemented) /* no swapping proc; invalid event type? */ -- cgit v0.10.2 From 8caed4df36b1f802b4992edcfd282cbeeec35d9d Mon Sep 17 00:00:00 2001 From: Michal Srb Date: Wed, 24 May 2017 15:54:41 +0300 Subject: Xi: Verify all events in ProcXSendExtensionEvent. The requirement is that events have type in range EXTENSION_EVENT_BASE..lastEvent, but it was tested only for first event of all. Signed-off-by: Michal Srb Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer diff --git a/Xi/sendexev.c b/Xi/sendexev.c index 1cf118a..5e63bfc 100644 --- a/Xi/sendexev.c +++ b/Xi/sendexev.c @@ -117,7 +117,7 @@ SProcXSendExtensionEvent(ClientPtr client) int ProcXSendExtensionEvent(ClientPtr client) { - int ret; + int ret, i; DeviceIntPtr dev; xEvent *first; XEventClass *list; @@ -141,10 +141,12 @@ ProcXSendExtensionEvent(ClientPtr client) /* The client's event type must be one defined by an extension. */ first = ((xEvent *) &stuff[1]); - if (!((EXTENSION_EVENT_BASE <= first->u.u.type) && - (first->u.u.type < lastEvent))) { - client->errorValue = first->u.u.type; - return BadValue; + for (i = 0; i < stuff->num_events; i++) { + if (!((EXTENSION_EVENT_BASE <= first[i].u.u.type) && + (first[i].u.u.type < lastEvent))) { + client->errorValue = first[i].u.u.type; + return BadValue; + } } list = (XEventClass *) (first + stuff->num_events); -- cgit v0.10.2 From ba336b24052122b136486961c82deac76bbde455 Mon Sep 17 00:00:00 2001 From: Michal Srb Date: Wed, 24 May 2017 15:54:42 +0300 Subject: Xi: Do not try to swap GenericEvent. The SProcXSendExtensionEvent must not attempt to swap GenericEvent because it is assuming that the event has fixed size and gives the swapping function xEvent-sized buffer. A GenericEvent would be later rejected by ProcXSendExtensionEvent anyway. Signed-off-by: Michal Srb Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer diff --git a/Xi/sendexev.c b/Xi/sendexev.c index 5e63bfc..5c2e0fc 100644 --- a/Xi/sendexev.c +++ b/Xi/sendexev.c @@ -95,9 +95,17 @@ SProcXSendExtensionEvent(ClientPtr client) eventP = (xEvent *) &stuff[1]; for (i = 0; i < stuff->num_events; i++, eventP++) { + if (eventP->u.u.type == GenericEvent) { + client->errorValue = eventP->u.u.type; + return BadValue; + } + proc = EventSwapVector[eventP->u.u.type & 0177]; - if (proc == NotImplemented) /* no swapping proc; invalid event type? */ + /* no swapping proc; invalid event type? */ + if (proc == NotImplemented) { + client->errorValue = eventP->u.u.type; return BadValue; + } (*proc) (eventP, &eventT); *eventP = eventT; } -- cgit v0.10.2