diff -u xorg-server-1.18.4/debian/changelog xorg-server-1.18.4/debian/changelog --- xorg-server-1.18.4/debian/changelog +++ xorg-server-1.18.4/debian/changelog @@ -1,3 +1,26 @@ +xorg-server (2:1.18.4-0ubuntu0.3) xenial-security; urgency=medium + + * SECURITY UPDATE: DoS and possible code execution in endianness + conversion of X Events + - debian/patches/CVE-2017-10971-1.patch: do not try to swap + GenericEvent in Xi/sendexev.c. + - debian/patches/CVE-2017-10971-2.patch: verify all events in + ProcXSendExtensionEvent in Xi/sendexev.c. + - debian/patches/CVE-2017-10971-3.patch: disallow GenericEvent in + SendEvent request in dix/events.c, dix/swapreq.c. + - CVE-2017-10971 + * SECURITY UPDATE: information leak in XEvent handling + - debian/patches/CVE-2017-10972.patch: zero target buffer in + SProcXSendExtensionEvent in Xi/sendexev.c. + - CVE-2017-10972 + * SECURITY UPDATE: MIT-MAGIC-COOKIES timing attack + - debian/patches/CVE-2017-2624.patch: use timingsafe_memcmp() in + configure.ac, include/dix-config.h.in, include/os.h, + os/mitauth.c, os/timingsafe_memcmp.c. + - CVE-2017-2624 + + -- Marc Deslauriers Mon, 17 Jul 2017 09:38:58 -0400 + xorg-server (2:1.18.4-0ubuntu0.2) xenial; urgency=medium * modesetting-unifdef-slave-support.diff: Fix modesetting slave output diff -u xorg-server-1.18.4/debian/patches/series xorg-server-1.18.4/debian/patches/series --- xorg-server-1.18.4/debian/patches/series +++ xorg-server-1.18.4/debian/patches/series @@ -53,0 +54,5 @@ +CVE-2017-10971-1.patch +CVE-2017-10971-2.patch +CVE-2017-10971-3.patch +CVE-2017-10972.patch +CVE-2017-2624.patch only in patch2: unchanged: --- xorg-server-1.18.4.orig/debian/patches/CVE-2017-10971-1.patch +++ xorg-server-1.18.4/debian/patches/CVE-2017-10971-1.patch @@ -0,0 +1,41 @@ +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 + only in patch2: unchanged: --- xorg-server-1.18.4.orig/debian/patches/CVE-2017-10971-2.patch +++ xorg-server-1.18.4/debian/patches/CVE-2017-10971-2.patch @@ -0,0 +1,43 @@ +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 + +Index: xorg-server-1.19.3/Xi/sendexev.c +=================================================================== +--- xorg-server-1.19.3.orig/Xi/sendexev.c 2017-07-17 09:33:47.024571967 -0400 ++++ xorg-server-1.19.3/Xi/sendexev.c 2017-07-17 09:33:47.024571967 -0400 +@@ -125,7 +125,7 @@ SProcXSendExtensionEvent(ClientPtr clien + int + ProcXSendExtensionEvent(ClientPtr client) + { +- int ret; ++ int ret, i; + DeviceIntPtr dev; + xEvent *first; + XEventClass *list; +@@ -149,10 +149,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); only in patch2: unchanged: --- xorg-server-1.18.4.orig/debian/patches/CVE-2017-10971-3.patch +++ xorg-server-1.18.4/debian/patches/CVE-2017-10971-3.patch @@ -0,0 +1,63 @@ +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 + +Index: xorg-server-1.18.4/dix/events.c +=================================================================== +--- xorg-server-1.18.4.orig/dix/events.c 2017-07-17 09:38:38.656585566 -0400 ++++ xorg-server-1.18.4/dix/events.c 2017-07-17 09:38:38.632585565 -0400 +@@ -5355,6 +5355,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) { +Index: xorg-server-1.18.4/dix/swapreq.c +=================================================================== +--- xorg-server-1.18.4.orig/dix/swapreq.c 2017-07-17 09:38:38.656585566 -0400 ++++ xorg-server-1.18.4/dix/swapreq.c 2017-07-17 09:38:38.636585565 -0400 +@@ -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? */ only in patch2: unchanged: --- xorg-server-1.18.4.orig/debian/patches/CVE-2017-10972.patch +++ xorg-server-1.18.4/debian/patches/CVE-2017-10972.patch @@ -0,0 +1,35 @@ +From 05442de962d3dc624f79fc1a00eca3ffc5489ced Mon Sep 17 00:00:00 2001 +From: Michal Srb +Date: Wed, 24 May 2017 15:54:39 +0300 +Subject: Xi: Zero target buffer in SProcXSendExtensionEvent. + +Make sure that the xEvent eventT is initialized with zeros, the same way as +in SProcSendEvent. + +Some event swapping functions do not overwrite all 32 bytes of xEvent +structure, for example XSecurityAuthorizationRevoked. Two cooperating +clients, one swapped and the other not, can send +XSecurityAuthorizationRevoked event to each other to retrieve old stack data +from X server. This can be potentialy misused to go around ASLR or +stack-protector. + +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 11d8202..1cf118a 100644 +--- a/Xi/sendexev.c ++++ b/Xi/sendexev.c +@@ -78,7 +78,7 @@ SProcXSendExtensionEvent(ClientPtr client) + { + CARD32 *p; + int i; +- xEvent eventT; ++ xEvent eventT = { .u.u.type = 0 }; + xEvent *eventP; + EventSwapPtr proc; + +-- +cgit v0.10.2 + only in patch2: unchanged: --- xorg-server-1.18.4.orig/debian/patches/CVE-2017-2624.patch +++ xorg-server-1.18.4/debian/patches/CVE-2017-2624.patch @@ -0,0 +1,119 @@ +Backport of: + +From d7ac755f0b618eb1259d93c8a16ec6e39a18627c Mon Sep 17 00:00:00 2001 +From: Matthieu Herrb +Date: Tue, 28 Feb 2017 19:18:25 +0100 +Subject: Use timingsafe_memcmp() to compare MIT-MAGIC-COOKIES CVE-2017-2624 + +Provide the function definition for systems that don't have it. + +Signed-off-by: Matthieu Herrb +Reviewed-by: Alan Coopersmith + +Index: xorg-server-1.18.4/configure.ac +=================================================================== +--- xorg-server-1.18.4.orig/configure.ac 2017-07-17 10:23:07.040709996 -0400 ++++ xorg-server-1.18.4/configure.ac 2017-07-17 10:23:29.656711051 -0400 +@@ -220,7 +220,8 @@ AC_CHECK_FUNCS([backtrace ffs geteuid ge + getdtablesize getifaddrs getpeereid getpeerucred getprogname getzoneid \ + mmap posix_fallocate seteuid shmctl64 strncasecmp vasprintf vsnprintf \ + walkcontext]) +-AC_REPLACE_FUNCS([reallocarray strcasecmp strcasestr strlcat strlcpy strndup]) ++AC_REPLACE_FUNCS([reallocarray strcasecmp strcasestr strlcat strlcpy strndup\ ++ timingsafe_memcmp]) + + AC_CHECK_DECLS([program_invocation_short_name], [], [], [[#include ]]) + +Index: xorg-server-1.18.4/include/dix-config.h.in +=================================================================== +--- xorg-server-1.18.4.orig/include/dix-config.h.in 2017-07-17 10:23:07.040709996 -0400 ++++ xorg-server-1.18.4/include/dix-config.h.in 2017-07-17 10:23:07.036709996 -0400 +@@ -232,6 +232,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_SYS_UTSNAME_H + ++/* Define to 1 if you have the `timingsafe_memcmp' function. */ ++#undef HAVE_TIMINGSAFE_MEMCMP ++ + /* Define to 1 if you have the header file. */ + #undef HAVE_TSLIB_H + +Index: xorg-server-1.18.4/include/os.h +=================================================================== +--- xorg-server-1.18.4.orig/include/os.h 2017-07-17 10:23:07.040709996 -0400 ++++ xorg-server-1.18.4/include/os.h 2017-07-17 10:23:07.036709996 -0400 +@@ -590,6 +590,11 @@ extern _X_EXPORT char * + strndup(const char *str, size_t n); + #endif + ++#ifndef HAVE_TIMINGSAFE_MEMCMP ++extern _X_EXPORT int ++timingsafe_memcmp(const void *b1, const void *b2, size_t len); ++#endif ++ + /* Logging. */ + typedef enum _LogParameter { + XLOG_FLUSH, +Index: xorg-server-1.18.4/os/mitauth.c +=================================================================== +--- xorg-server-1.18.4.orig/os/mitauth.c 2017-07-17 10:23:07.040709996 -0400 ++++ xorg-server-1.18.4/os/mitauth.c 2017-07-17 10:23:07.036709996 -0400 +@@ -76,7 +76,7 @@ MitCheckCookie(unsigned short data_lengt + + for (auth = mit_auth; auth; auth = auth->next) { + if (data_length == auth->len && +- memcmp(data, auth->data, (int) data_length) == 0) ++ timingsafe_memcmp(data, auth->data, (int) data_length) == 0) + return auth->id; + } + *reason = "Invalid MIT-MAGIC-COOKIE-1 key"; +Index: xorg-server-1.18.4/os/timingsafe_memcmp.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ xorg-server-1.18.4/os/timingsafe_memcmp.c 2017-07-17 10:23:07.036709996 -0400 +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (c) 2014 Google Inc. ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++ ++int ++timingsafe_memcmp(const void *b1, const void *b2, size_t len) ++{ ++ const unsigned char *p1 = b1, *p2 = b2; ++ size_t i; ++ int res = 0, done = 0; ++ ++ for (i = 0; i < len; i++) { ++ /* lt is -1 if p1[i] < p2[i]; else 0. */ ++ int lt = (p1[i] - p2[i]) >> CHAR_BIT; ++ ++ /* gt is -1 if p1[i] > p2[i]; else 0. */ ++ int gt = (p2[i] - p1[i]) >> CHAR_BIT; ++ ++ /* cmp is 1 if p1[i] > p2[i]; -1 if p1[i] < p2[i]; else 0. */ ++ int cmp = lt - gt; ++ ++ /* set res = cmp if !done. */ ++ res |= cmp & ~done; ++ ++ /* set done if p1[i] != p2[i]. */ ++ done |= lt | gt; ++ } ++ ++ return (res); ++}