xorg-server: Changes to 'ubuntu-trusty'
debian/changelog | 38
debian/patches/CVE-2014-8xxx/0000-glx-check-return.patch | 184 ++
debian/patches/CVE-2014-8xxx/0000-regionsize-size_t.patch | 31
debian/patches/CVE-2014-8xxx/0001-unchecked-malloc-may-allow-unauthed-client-to-crash-.patch | 40
debian/patches/CVE-2014-8xxx/0002-dix-integer-overflow-in-ProcPutImage-CVE-2014-8092-1.patch | 34
debian/patches/CVE-2014-8xxx/0003-dix-integer-overflow-in-GetHosts-CVE-2014-8092-2-4.patch | 47
debian/patches/CVE-2014-8xxx/0004-dix-integer-overflow-in-RegionSizeof-CVE-2014-8092-3.patch | 125 +
debian/patches/CVE-2014-8xxx/0005-dix-integer-overflow-in-REQUEST_FIXED_SIZE-CVE-2014-.patch | 34
debian/patches/CVE-2014-8xxx/0006-dri2-integer-overflow-in-ProcDRI2GetBuffers-CVE-2014.patch | 35
debian/patches/CVE-2014-8xxx/0007-dbe-unvalidated-lengths-in-DbeSwapBuffers-calls-CVE-.patch | 73
debian/patches/CVE-2014-8xxx/0008-Xi-unvalidated-lengths-in-Xinput-extension-CVE-2014-.patch | 551 ++++++
debian/patches/CVE-2014-8xxx/0009-xcmisc-unvalidated-length-in-SProcXCMiscGetXIDList-C.patch | 27
debian/patches/CVE-2014-8xxx/0010-Xv-unvalidated-lengths-in-XVideo-extension-swapped-p.patch | 176 +
debian/patches/CVE-2014-8xxx/0011-dri3-unvalidated-lengths-in-DRI3-extension-swapped-p.patch | 64
debian/patches/CVE-2014-8xxx/0012-present-unvalidated-lengths-in-Present-extension-pro.patch | 68
debian/patches/CVE-2014-8xxx/0013-randr-unvalidated-lengths-in-RandR-extension-swapped.patch | 51
debian/patches/CVE-2014-8xxx/0014-render-check-request-size-before-reading-it-CVE-2014.patch | 36
debian/patches/CVE-2014-8xxx/0015-render-unvalidated-lengths-in-Render-extn.-swapped-p.patch | 140 +
debian/patches/CVE-2014-8xxx/0016-xfixes-unvalidated-length-in-SProcXFixesSelectSelect.patch | 27
debian/patches/CVE-2014-8xxx/0017-Add-request-length-checking-test-cases-for-some-Xinp.patch | 195 ++
debian/patches/CVE-2014-8xxx/0018-Add-request-length-checking-test-cases-for-some-Xinp.patch | 86
debian/patches/CVE-2014-8xxx/0019-Add-REQUEST_FIXED_SIZE-testcases-to-test-misc.c.patch | 74
debian/patches/CVE-2014-8xxx/0020-glx-Be-more-paranoid-about-variable-length-requests-.patch | 44
debian/patches/CVE-2014-8xxx/0021-glx-Be-more-strict-about-rejecting-invalid-image-siz.patch | 165 +
debian/patches/CVE-2014-8xxx/0022-glx-Additional-paranoia-in-__glXGetAnswerBuffer-__GL.patch | 59
debian/patches/CVE-2014-8xxx/0023-glx-Fix-image-size-computation-for-EXT_texture_integ.patch | 59
debian/patches/CVE-2014-8xxx/0024-glx-Add-safe_-add-mul-pad-v3-CVE-2014-8093-4-6.patch | 79
debian/patches/CVE-2014-8xxx/0025-glx-Length-checking-for-GLXRender-requests-v2-CVE-20.patch | 72
debian/patches/CVE-2014-8xxx/0026-glx-Integer-overflow-protection-for-non-generated-re.patch | 225 ++
debian/patches/CVE-2014-8xxx/0027-glx-Length-checking-for-RenderLarge-requests-v2-CVE-.patch | 155 +
debian/patches/CVE-2014-8xxx/0028-glx-Top-level-length-checking-for-swapped-VendorPriv.patch | 51
debian/patches/CVE-2014-8xxx/0029-glx-Request-length-checks-for-SetClientInfoARB-CVE-2.patch | 74
debian/patches/CVE-2014-8xxx/0030-glx-Length-checking-for-non-generated-vendor-private.patch | 45
debian/patches/CVE-2014-8xxx/0031-glx-Length-checking-for-non-generated-single-request.patch | 561 ++++++
debian/patches/CVE-2014-8xxx/0032-glx-Pass-remaining-request-length-into-varsize-v2-CV.patch | 913 ++++++++++
debian/patches/CVE-2014-8xxx/0033-glx-Fix-mask-truncation-in-__glXGetAnswerBuffer-CVE-.patch | 34
debian/patches/CVE-2014-8xxx/0034-CVE-2014-8097-additional.patch | 47
debian/patches/CVE-2014-8xxx/0035-CVE-2014-8098-additional.patch | 36
debian/patches/CVE-2014-8xxx/0036-CVE-2014-8092-additional.patch | 28
debian/patches/CVE-2014-8xxx/0037-CVE-2014-8092-additional-2.patch | 29
debian/patches/series | 41
41 files changed, 4853 insertions(+)
New commits:
commit 72ff20cdc71762bc9da451b6a999ef4a64238a8e
Author: Timo Aaltonen <tjaalton@debian.org>
Date: Wed Dec 10 19:10:24 2014 +0200
release to trusty-proposed
diff --git a/debian/changelog b/debian/changelog
index 5c0d482..74075e3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+xorg-server (2:1.15.1-0ubuntu2.6) trusty-proposed; urgency=medium
+
+ * Re-apply changes between -0u2.1..-0u2.3.
+
+ -- Timo Aaltonen <tjaalton@debian.org> Wed, 10 Dec 2014 19:06:02 +0200
+
xorg-server (2:1.15.1-0ubuntu2.5) trusty-security; urgency=medium
* SECURITY UPDATE: Dec 2014 security issues - additional fixes
commit 9ddbe364768127f584e991592eda9b2d072f62a7
Author: Timo Aaltonen <tjaalton@debian.org>
Date: Wed Dec 10 19:05:10 2014 +0200
import changes from -0ubuntu2.5
diff --git a/debian/changelog b/debian/changelog
index 1c184d2..5c0d482 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,35 @@
+xorg-server (2:1.15.1-0ubuntu2.5) trusty-security; urgency=medium
+
+ * SECURITY UPDATE: Dec 2014 security issues - additional fixes
+ - debian/patches/CVE-2014-8xxx/003[4567]*.patch: add additional
+ fixes not included in original pre-advisory bundle.
+
+ -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Tue, 09 Dec 2014 17:12:42 -0500
+
+xorg-server (2:1.15.1-0ubuntu2.4) trusty-security; urgency=medium
+
+ * SECURITY UPDATE: Dec 2014 protocol handling security issues
+ - debian/patches/CVE-2014-8xxx/*.patch: patches from upstream to fix
+ a multitude of security issues, including a couple of pre-requisite
+ fixes from git.
+ - CVE-2014-8091
+ - CVE-2014-8092
+ - CVE-2014-8093
+ - CVE-2014-8094
+ - CVE-2014-8095
+ - CVE-2014-8096
+ - CVE-2014-8097
+ - CVE-2014-8098
+ - CVE-2014-8099
+ - CVE-2014-8100
+ - CVE-2014-8101
+ - CVE-2014-8102
+ - CVE-2014-8103
+ * This package does _not_ contain the changes from 2:1.15.1-0ubuntu2.3
+ in trusty-proposed.
+
+ -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Mon, 08 Dec 2014 15:42:08 -0500
+
xorg-server (2:1.15.1-0ubuntu2.3) trusty-proposed; urgency=medium
* Actually fix the cirrus VGA corruption in gnome-terminal.
diff --git a/debian/patches/CVE-2014-8xxx/0000-glx-check-return.patch b/debian/patches/CVE-2014-8xxx/0000-glx-check-return.patch
new file mode 100644
index 0000000..a652174
--- /dev/null
+++ b/debian/patches/CVE-2014-8xxx/0000-glx-check-return.patch
@@ -0,0 +1,184 @@
+From 61a292adf45405641de1c522a04c148e0a152acd Mon Sep 17 00:00:00 2001
+From: Keith Packard <keithp@keithp.com>
+Date: Thu, 9 Oct 2014 15:17:17 +0200
+Subject: glx: check return from __glXGetAnswerBuffer
+
+This function can return NULL; make sure every caller tests for that.
+
+Reviewed-by: Adam Jackson <ajax@redhat.com>
+Signed-off-by: Keith Packard <keithp@keithp.com>
+
+diff --git a/glx/indirect_dispatch.c b/glx/indirect_dispatch.c
+index 329b2e6..f6cabef 100644
+--- a/glx/indirect_dispatch.c
++++ b/glx/indirect_dispatch.c
+@@ -2464,6 +2464,9 @@ __glXDisp_AreTexturesResident(__GLXclientState * cl, GLbyte * pc)
+ GLboolean answerBuffer[200];
+ GLboolean *residences =
+ __glXGetAnswerBuffer(cl, n, answerBuffer, sizeof(answerBuffer), 1);
++
++ if (residences == NULL)
++ return BadAlloc;
+ retval =
+ glAreTexturesResident(n, (const GLuint *) (pc + 4), residences);
+ __glXSendReply(cl->client, residences, n, 1, GL_TRUE, retval);
+@@ -2488,6 +2491,9 @@ __glXDisp_AreTexturesResidentEXT(__GLXclientState * cl, GLbyte * pc)
+ GLboolean answerBuffer[200];
+ GLboolean *residences =
+ __glXGetAnswerBuffer(cl, n, answerBuffer, sizeof(answerBuffer), 1);
++
++ if (residences == NULL)
++ return BadAlloc;
+ retval =
+ glAreTexturesResident(n, (const GLuint *) (pc + 4), residences);
+ __glXSendReply(cl->client, residences, n, 1, GL_TRUE, retval);
+@@ -2593,6 +2599,9 @@ __glXDisp_GenTextures(__GLXclientState * cl, GLbyte * pc)
+ GLuint *textures =
+ __glXGetAnswerBuffer(cl, n * 4, answerBuffer, sizeof(answerBuffer),
+ 4);
++
++ if (textures == NULL)
++ return BadAlloc;
+ glGenTextures(n, textures);
+ __glXSendReply(cl->client, textures, n, 4, GL_TRUE, 0);
+ error = Success;
+@@ -2616,6 +2625,9 @@ __glXDisp_GenTexturesEXT(__GLXclientState * cl, GLbyte * pc)
+ GLuint *textures =
+ __glXGetAnswerBuffer(cl, n * 4, answerBuffer, sizeof(answerBuffer),
+ 4);
++
++ if (textures == NULL)
++ return BadAlloc;
+ glGenTextures(n, textures);
+ __glXSendReply(cl->client, textures, n, 4, GL_TRUE, 0);
+ error = Success;
+@@ -3883,6 +3895,9 @@ __glXDisp_GenQueries(__GLXclientState * cl, GLbyte * pc)
+ GLuint *ids =
+ __glXGetAnswerBuffer(cl, n * 4, answerBuffer, sizeof(answerBuffer),
+ 4);
++
++ if (ids == NULL)
++ return BadAlloc;
+ GenQueries(n, ids);
+ __glXSendReply(cl->client, ids, n, 4, GL_TRUE, 0);
+ error = Success;
+@@ -4253,6 +4268,9 @@ __glXDisp_GenProgramsARB(__GLXclientState * cl, GLbyte * pc)
+ GLuint *programs =
+ __glXGetAnswerBuffer(cl, n * 4, answerBuffer, sizeof(answerBuffer),
+ 4);
++
++ if (programs == NULL)
++ return BadAlloc;
+ GenProgramsARB(n, programs);
+ __glXSendReply(cl->client, programs, n, 4, GL_TRUE, 0);
+ error = Success;
+@@ -4630,6 +4648,10 @@ __glXDisp_GenFramebuffers(__GLXclientState * cl, GLbyte * pc)
+ GLuint *framebuffers =
+ __glXGetAnswerBuffer(cl, n * 4, answerBuffer, sizeof(answerBuffer),
+ 4);
++
++ if (framebuffers == NULL)
++ return BadAlloc;
++
+ GenFramebuffers(n, framebuffers);
+ __glXSendReply(cl->client, framebuffers, n, 4, GL_TRUE, 0);
+ error = Success;
+@@ -4655,6 +4677,9 @@ __glXDisp_GenRenderbuffers(__GLXclientState * cl, GLbyte * pc)
+ GLuint *renderbuffers =
+ __glXGetAnswerBuffer(cl, n * 4, answerBuffer, sizeof(answerBuffer),
+ 4);
++
++ if (renderbuffers == NULL)
++ return BadAlloc;
+ GenRenderbuffers(n, renderbuffers);
+ __glXSendReply(cl->client, renderbuffers, n, 4, GL_TRUE, 0);
+ error = Success;
+diff --git a/glx/indirect_dispatch_swap.c b/glx/indirect_dispatch_swap.c
+index 647d0c9..c0bb64d 100644
+--- a/glx/indirect_dispatch_swap.c
++++ b/glx/indirect_dispatch_swap.c
+@@ -2731,6 +2731,9 @@ __glXDispSwap_AreTexturesResident(__GLXclientState * cl, GLbyte * pc)
+ GLboolean answerBuffer[200];
+ GLboolean *residences =
+ __glXGetAnswerBuffer(cl, n, answerBuffer, sizeof(answerBuffer), 1);
++
++ if (residences == NULL)
++ return BadAlloc;
+ retval =
+ glAreTexturesResident(n,
+ (const GLuint *)
+@@ -2759,6 +2762,9 @@ __glXDispSwap_AreTexturesResidentEXT(__GLXclientState * cl, GLbyte * pc)
+ GLboolean answerBuffer[200];
+ GLboolean *residences =
+ __glXGetAnswerBuffer(cl, n, answerBuffer, sizeof(answerBuffer), 1);
++
++ if (residences == NULL)
++ return BadAlloc;
+ retval =
+ glAreTexturesResident(n,
+ (const GLuint *)
+@@ -2878,6 +2884,9 @@ __glXDispSwap_GenTextures(__GLXclientState * cl, GLbyte * pc)
+ GLuint *textures =
+ __glXGetAnswerBuffer(cl, n * 4, answerBuffer, sizeof(answerBuffer),
+ 4);
++
++ if (textures == NULL)
++ return BadAlloc;
+ glGenTextures(n, textures);
+ (void) bswap_32_array((uint32_t *) textures, n);
+ __glXSendReplySwap(cl->client, textures, n, 4, GL_TRUE, 0);
+@@ -2903,6 +2912,9 @@ __glXDispSwap_GenTexturesEXT(__GLXclientState * cl, GLbyte * pc)
+ GLuint *textures =
+ __glXGetAnswerBuffer(cl, n * 4, answerBuffer, sizeof(answerBuffer),
+ 4);
++
++ if (textures == NULL)
++ return BadAlloc;
+ glGenTextures(n, textures);
+ (void) bswap_32_array((uint32_t *) textures, n);
+ __glXSendReplySwap(cl->client, textures, n, 4, GL_TRUE, 0);
+@@ -4290,6 +4302,9 @@ __glXDispSwap_GenQueries(__GLXclientState * cl, GLbyte * pc)
+ GLuint *ids =
+ __glXGetAnswerBuffer(cl, n * 4, answerBuffer, sizeof(answerBuffer),
+ 4);
++ if (ids == NULL)
++ return BadAlloc;
++
+ GenQueries(n, ids);
+ (void) bswap_32_array((uint32_t *) ids, n);
+ __glXSendReplySwap(cl->client, ids, n, 4, GL_TRUE, 0);
+@@ -4697,6 +4712,9 @@ __glXDispSwap_GenProgramsARB(__GLXclientState * cl, GLbyte * pc)
+ GLuint *programs =
+ __glXGetAnswerBuffer(cl, n * 4, answerBuffer, sizeof(answerBuffer),
+ 4);
++ if (programs == NULL)
++ return BadAlloc;
++
+ GenProgramsARB(n, programs);
+ (void) bswap_32_array((uint32_t *) programs, n);
+ __glXSendReplySwap(cl->client, programs, n, 4, GL_TRUE, 0);
+@@ -5122,6 +5140,10 @@ __glXDispSwap_GenFramebuffers(__GLXclientState * cl, GLbyte * pc)
+ GLuint *framebuffers =
+ __glXGetAnswerBuffer(cl, n * 4, answerBuffer, sizeof(answerBuffer),
+ 4);
++
++ if (framebuffers == NULL)
++ return BadAlloc;
++
+ GenFramebuffers(n, framebuffers);
+ (void) bswap_32_array((uint32_t *) framebuffers, n);
+ __glXSendReplySwap(cl->client, framebuffers, n, 4, GL_TRUE, 0);
+@@ -5149,6 +5171,10 @@ __glXDispSwap_GenRenderbuffers(__GLXclientState * cl, GLbyte * pc)
+ GLuint *renderbuffers =
+ __glXGetAnswerBuffer(cl, n * 4, answerBuffer, sizeof(answerBuffer),
+ 4);
++
++ if (renderbuffers == NULL)
++ return BadAlloc;
++
+ GenRenderbuffers(n, renderbuffers);
+ (void) bswap_32_array((uint32_t *) renderbuffers, n);
+ __glXSendReplySwap(cl->client, renderbuffers, n, 4, GL_TRUE, 0);
+--
+cgit v0.10.2
+
diff --git a/debian/patches/CVE-2014-8xxx/0000-regionsize-size_t.patch b/debian/patches/CVE-2014-8xxx/0000-regionsize-size_t.patch
new file mode 100644
index 0000000..12025f6
--- /dev/null
+++ b/debian/patches/CVE-2014-8xxx/0000-regionsize-size_t.patch
@@ -0,0 +1,31 @@
+From 995ecfb51d4ab8197e4591d5c0957e08a0bd6a59 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer@who-t.net>
+Date: Thu, 30 Oct 2014 09:00:21 +1000
+Subject: include: change RegionSize() to take a size_t
+
+/usr/include/xorg/regionstr.h:130:36: warning: implicit conversion changes
+signedness: 'int' to 'unsigned long' [-Wsign-conversion]
+ return (sizeof(RegDataRec) + ((n) * sizeof(BoxRec)));
+ ^ ~
+
+Really only just pushes the problem to the caller, but maybe that motivates
+someone to fix it.
+
+Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+
+diff --git a/include/regionstr.h b/include/regionstr.h
+index 4a0725d..515e93f 100644
+--- a/include/regionstr.h
++++ b/include/regionstr.h
+@@ -125,7 +125,7 @@ RegionEnd(RegionPtr reg)
+ }
+
+ static inline size_t
+-RegionSizeof(int n)
++RegionSizeof(size_t n)
+ {
+ return (sizeof(RegDataRec) + ((n) * sizeof(BoxRec)));
+ }
+--
+cgit v0.10.2
+
diff --git a/debian/patches/CVE-2014-8xxx/0001-unchecked-malloc-may-allow-unauthed-client-to-crash-.patch b/debian/patches/CVE-2014-8xxx/0001-unchecked-malloc-may-allow-unauthed-client-to-crash-.patch
new file mode 100644
index 0000000..b5fbb7d
--- /dev/null
+++ b/debian/patches/CVE-2014-8xxx/0001-unchecked-malloc-may-allow-unauthed-client-to-crash-.patch
@@ -0,0 +1,40 @@
+From d2f5bd2c3e3cbe4778749d457550355d344ca62a Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Fri, 17 Jan 2014 18:54:03 -0800
+Subject: [PATCH 01/33] unchecked malloc may allow unauthed client to crash
+ Xserver [CVE-2014-8091]
+
+authdes_ezdecode() calls malloc() using a length provided by the
+connection handshake sent by a newly connected client in order
+to authenticate to the server, so should be treated as untrusted.
+
+It didn't check if malloc() failed before writing to the newly
+allocated buffer, so could lead to a server crash if the server
+fails to allocate memory (up to UINT16_MAX bytes, since the len
+field is a CARD16 in the X protocol).
+
+Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
+Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+---
+ os/rpcauth.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/os/rpcauth.c b/os/rpcauth.c
+index d60ea35..413cc61 100644
+--- a/os/rpcauth.c
++++ b/os/rpcauth.c
+@@ -66,6 +66,10 @@ authdes_ezdecode(const char *inmsg, int len)
+ SVCXPRT xprt;
+
+ temp_inmsg = malloc(len);
++ if (temp_inmsg == NULL) {
++ why = AUTH_FAILED; /* generic error, since there is no AUTH_BADALLOC */
++ return NULL;
++ }
+ memmove(temp_inmsg, inmsg, len);
+
+ memset((char *) &msg, 0, sizeof(msg));
+--
+1.7.9.2
+
diff --git a/debian/patches/CVE-2014-8xxx/0002-dix-integer-overflow-in-ProcPutImage-CVE-2014-8092-1.patch b/debian/patches/CVE-2014-8xxx/0002-dix-integer-overflow-in-ProcPutImage-CVE-2014-8092-1.patch
new file mode 100644
index 0000000..085109a
--- /dev/null
+++ b/debian/patches/CVE-2014-8xxx/0002-dix-integer-overflow-in-ProcPutImage-CVE-2014-8092-1.patch
@@ -0,0 +1,34 @@
+From 7e17b41d2907afd82d668f25694e1da12e34895e Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Wed, 22 Jan 2014 21:11:16 -0800
+Subject: [PATCH 02/33] dix: integer overflow in ProcPutImage() [CVE-2014-8092
+ 1/4]
+
+ProcPutImage() calculates a length field from a width, left pad and depth
+specified by the client (if the specified format is XYPixmap).
+
+The calculations for the total amount of memory the server needs for the
+pixmap can overflow a 32-bit number, causing out-of-bounds memory writes
+on 32-bit systems (since the length is stored in a long int variable).
+
+Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
+Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+---
+ dix/dispatch.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+Index: xorg-server-1.15.1/dix/dispatch.c
+===================================================================
+--- xorg-server-1.15.1.orig/dix/dispatch.c 2014-12-04 11:52:11.007847226 -0500
++++ xorg-server-1.15.1/dix/dispatch.c 2014-12-04 11:52:10.975847036 -0500
+@@ -1957,6 +1957,9 @@
+ tmpImage = (char *) &stuff[1];
+ lengthProto = length;
+
++ if (lengthProto >= (INT32_MAX / stuff->height))
++ return BadLength;
++
+ if ((bytes_to_int32(lengthProto * stuff->height) +
+ bytes_to_int32(sizeof(xPutImageReq))) != client->req_len)
+ return BadLength;
diff --git a/debian/patches/CVE-2014-8xxx/0003-dix-integer-overflow-in-GetHosts-CVE-2014-8092-2-4.patch b/debian/patches/CVE-2014-8xxx/0003-dix-integer-overflow-in-GetHosts-CVE-2014-8092-2-4.patch
new file mode 100644
index 0000000..d5f2d75
--- /dev/null
+++ b/debian/patches/CVE-2014-8xxx/0003-dix-integer-overflow-in-GetHosts-CVE-2014-8092-2-4.patch
@@ -0,0 +1,47 @@
+From 2f605f86acec5ce853f764c41f8c737154a274f5 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Mon, 6 Jan 2014 23:30:14 -0800
+Subject: [PATCH 03/33] dix: integer overflow in GetHosts() [CVE-2014-8092
+ 2/4]
+
+GetHosts() iterates over all the hosts it has in memory, and copies
+them to a buffer. The buffer length is calculated by iterating over
+all the hosts and adding up all of their combined length. There is a
+potential integer overflow, if there are lots and lots of hosts (with
+a combined length of > ~4 gig). This should be possible by repeatedly
+calling ProcChangeHosts() on 64bit machines with enough memory.
+
+This patch caps the list at 1mb, because multi-megabyte hostname
+lists for X access control are insane.
+
+Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
+Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+---
+ os/access.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+Index: xorg-server-1.16.0/os/access.c
+===================================================================
+--- xorg-server-1.16.0.orig/os/access.c 2014-12-04 11:11:43.752542885 -0500
++++ xorg-server-1.16.0/os/access.c 2014-12-04 11:11:43.748542843 -0500
+@@ -1323,6 +1323,10 @@
+ for (host = validhosts; host; host = host->next) {
+ nHosts++;
+ n += pad_to_int32(host->len) + sizeof(xHostEntry);
++ /* Could check for INT_MAX, but in reality having more than 1mb of
++ hostnames in the access list is ridiculous */
++ if (n >= 1048576)
++ break;
+ }
+ if (n) {
+ *data = ptr = malloc(n);
+@@ -1331,6 +1335,8 @@
+ }
+ for (host = validhosts; host; host = host->next) {
+ len = host->len;
++ if ((ptr + sizeof(xHostEntry) + len) > (data + n))
++ break;
+ ((xHostEntry *) ptr)->family = host->family;
+ ((xHostEntry *) ptr)->length = len;
+ ptr += sizeof(xHostEntry);
diff --git a/debian/patches/CVE-2014-8xxx/0004-dix-integer-overflow-in-RegionSizeof-CVE-2014-8092-3.patch b/debian/patches/CVE-2014-8xxx/0004-dix-integer-overflow-in-RegionSizeof-CVE-2014-8092-3.patch
new file mode 100644
index 0000000..552bd8b
--- /dev/null
+++ b/debian/patches/CVE-2014-8xxx/0004-dix-integer-overflow-in-RegionSizeof-CVE-2014-8092-3.patch
@@ -0,0 +1,125 @@
+From d7b2f5c06259c7e6ba037909adec4c2a5a8b15ec Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Wed, 22 Jan 2014 22:37:15 -0800
+Subject: [PATCH 04/33] dix: integer overflow in RegionSizeof() [CVE-2014-8092
+ 3/4]
+
+RegionSizeof contains several integer overflows if a large length
+value is passed in. Once we fix it to return 0 on overflow, we
+also have to fix the callers to handle this error condition
+
+v2: Fixed limit calculation in RegionSizeof as pointed out by jcristau.
+
+Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
+Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+Reviewed-by: Julien Cristau <jcristau@debian.org>
+---
+ dix/region.c | 20 +++++++++++++-------
+ include/regionstr.h | 10 +++++++---
+ 2 files changed, 20 insertions(+), 10 deletions(-)
+
+Index: xorg-server-1.15.1/dix/region.c
+===================================================================
+--- xorg-server-1.15.1.orig/dix/region.c 2014-12-05 08:24:42.034665485 -0500
++++ xorg-server-1.15.1/dix/region.c 2014-12-05 08:24:42.030665458 -0500
+@@ -169,7 +169,6 @@
+ ((r1)->y1 <= (r2)->y1) && \
+ ((r1)->y2 >= (r2)->y2) )
+
+-#define xallocData(n) malloc(RegionSizeof(n))
+ #define xfreeData(reg) if ((reg)->data && (reg)->data->size) free((reg)->data)
+
+ #define RECTALLOC_BAIL(pReg,n,bail) \
+@@ -205,8 +204,9 @@
+ #define DOWNSIZE(reg,numRects) \
+ if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
+ { \
+- RegDataPtr NewData; \
+- NewData = (RegDataPtr)realloc((reg)->data, RegionSizeof(numRects)); \
++ size_t NewSize = RegionSizeof(numRects); \
++ RegDataPtr NewData = \
++ (NewSize > 0) ? realloc((reg)->data, NewSize) : NULL ; \
+ if (NewData) \
+ { \
+ NewData->size = (numRects); \
+@@ -345,17 +345,20 @@
+ RegionRectAlloc(RegionPtr pRgn, int n)
+ {
+ RegDataPtr data;
++ size_t rgnSize;
+
+ if (!pRgn->data) {
+ n++;
+- pRgn->data = xallocData(n);
++ rgnSize = RegionSizeof(n);
++ pRgn->data = (rgnSize > 0) ? malloc(rgnSize) : NULL;
+ if (!pRgn->data)
+ return RegionBreak(pRgn);
+ pRgn->data->numRects = 1;
+ *RegionBoxptr(pRgn) = pRgn->extents;
+ }
+ else if (!pRgn->data->size) {
+- pRgn->data = xallocData(n);
++ rgnSize = RegionSizeof(n);
++ pRgn->data = (rgnSize > 0) ? malloc(rgnSize) : NULL;
+ if (!pRgn->data)
+ return RegionBreak(pRgn);
+ pRgn->data->numRects = 0;
+@@ -367,7 +370,8 @@
+ n = 250;
+ }
+ n += pRgn->data->numRects;
+- data = (RegDataPtr) realloc(pRgn->data, RegionSizeof(n));
++ rgnSize = RegionSizeof(n);
++ data = (rgnSize > 0) ? realloc(pRgn->data, rgnSize) : NULL;
+ if (!data)
+ return RegionBreak(pRgn);
+ pRgn->data = data;
+@@ -1312,6 +1316,7 @@
+ {
+
+ RegionPtr pRgn;
++ size_t rgnSize;
+ RegDataPtr pData;
+ BoxPtr pBox;
+ int i;
+@@ -1338,7 +1343,8 @@
+ }
+ return pRgn;
+ }
+- pData = xallocData(nrects);
++ rgnSize = RegionSizeof(nrects);
++ pData = (rgnSize > 0) ? malloc(rgnSize) : NULL;
+ if (!pData) {
+ RegionBreak(pRgn);
+ return pRgn;
+Index: xorg-server-1.15.1/include/regionstr.h
+===================================================================
+--- xorg-server-1.15.1.orig/include/regionstr.h 2014-12-05 08:24:42.034665485 -0500
++++ xorg-server-1.15.1/include/regionstr.h 2014-12-05 08:24:42.030665458 -0500
+@@ -127,7 +127,10 @@
+ static inline size_t
+ RegionSizeof(size_t n)
+ {
+- return (sizeof(RegDataRec) + ((n) * sizeof(BoxRec)));
++ if (n < ((INT_MAX - sizeof(RegDataRec)) / sizeof(BoxRec)))
++ return (sizeof(RegDataRec) + ((n) * sizeof(BoxRec)));
++ else
++ return 0;
+ }
+
+ static inline void
+@@ -138,9 +141,10 @@
+ (_pReg)->data = (RegDataPtr) NULL;
+ }
+ else {
++ size_t rgnSize;
+ (_pReg)->extents = RegionEmptyBox;
+- if (((_size) > 1) && ((_pReg)->data =
+- (RegDataPtr) malloc(RegionSizeof(_size)))) {
++ if (((_size) > 1) && ((rgnSize = RegionSizeof(_size)) > 0) &&
++ (((_pReg)->data = malloc(rgnSize)) != NULL)) {
+ (_pReg)->data->size = (_size);
+ (_pReg)->data->numRects = 0;
+ }
diff --git a/debian/patches/CVE-2014-8xxx/0005-dix-integer-overflow-in-REQUEST_FIXED_SIZE-CVE-2014-.patch b/debian/patches/CVE-2014-8xxx/0005-dix-integer-overflow-in-REQUEST_FIXED_SIZE-CVE-2014-.patch
new file mode 100644
index 0000000..1009488
--- /dev/null
+++ b/debian/patches/CVE-2014-8xxx/0005-dix-integer-overflow-in-REQUEST_FIXED_SIZE-CVE-2014-.patch
@@ -0,0 +1,34 @@
+From 7d4f361a216718fc7333ab805dafdb9e5c85c180 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Wed, 22 Jan 2014 23:44:46 -0800
+Subject: [PATCH 05/33] dix: integer overflow in REQUEST_FIXED_SIZE()
+ [CVE-2014-8092 4/4]
+
+Force use of 64-bit integers when evaluating data provided by clients
+in 32-bit fields which can overflow when added or multiplied during
+checks.
+
+Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
+Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+---
+ include/dix.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/include/dix.h b/include/dix.h
+index 991a3ce..e0c6ed8 100644
+--- a/include/dix.h
++++ b/include/dix.h
+@@ -76,7 +76,8 @@ SOFTWARE.
+
+ #define REQUEST_FIXED_SIZE(req, n)\
+ if (((sizeof(req) >> 2) > client->req_len) || \
+- (((sizeof(req) + (n) + 3) >> 2) != client->req_len)) \
++ ((n >> 2) >= client->req_len) || \
++ ((((uint64_t) sizeof(req) + (n) + 3) >> 2) != (uint64_t) client->req_len)) \
+ return(BadLength)
+
+ #define LEGAL_NEW_RESOURCE(id,client)\
+--
+1.7.9.2
+
diff --git a/debian/patches/CVE-2014-8xxx/0006-dri2-integer-overflow-in-ProcDRI2GetBuffers-CVE-2014.patch b/debian/patches/CVE-2014-8xxx/0006-dri2-integer-overflow-in-ProcDRI2GetBuffers-CVE-2014.patch
new file mode 100644
index 0000000..430e956
--- /dev/null
+++ b/debian/patches/CVE-2014-8xxx/0006-dri2-integer-overflow-in-ProcDRI2GetBuffers-CVE-2014.patch
@@ -0,0 +1,35 @@
+From f07eb544bbcfd9d4c64f036b654f4567f1fd2b9c Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Wed, 22 Jan 2014 23:40:18 -0800
+Subject: [PATCH 06/33] dri2: integer overflow in ProcDRI2GetBuffers()
+ [CVE-2014-8094]
+
+ProcDRI2GetBuffers() tries to validate a length field (count).
+There is an integer overflow in the validation. This can cause
+out of bound reads and memory corruption later on.
+
+Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
+Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+Reviewed-by: Julien Cristau <jcristau@debian.org>
+---
+ hw/xfree86/dri2/dri2ext.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
+index ffd66fa..221ec53 100644
+--- a/hw/xfree86/dri2/dri2ext.c
++++ b/hw/xfree86/dri2/dri2ext.c
+@@ -270,6 +270,9 @@ ProcDRI2GetBuffers(ClientPtr client)
+ unsigned int *attachments;
+
+ REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * 4);
++ if (stuff->count > (INT_MAX / 4))
++ return BadLength;
++
+ if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
+ &pDrawable, &status))
+ return status;
+--
+1.7.9.2
+
diff --git a/debian/patches/CVE-2014-8xxx/0007-dbe-unvalidated-lengths-in-DbeSwapBuffers-calls-CVE-.patch b/debian/patches/CVE-2014-8xxx/0007-dbe-unvalidated-lengths-in-DbeSwapBuffers-calls-CVE-.patch
new file mode 100644
index 0000000..0167ec0
--- /dev/null
+++ b/debian/patches/CVE-2014-8xxx/0007-dbe-unvalidated-lengths-in-DbeSwapBuffers-calls-CVE-.patch
@@ -0,0 +1,73 @@
+From 0d50f11aa10fe64c74ab7b3c572cc2f3ff583020 Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Wed, 22 Jan 2014 23:12:04 -0800
+Subject: [PATCH 07/33] dbe: unvalidated lengths in DbeSwapBuffers calls
+ [CVE-2014-8097]
+
+ProcDbeSwapBuffers() has a 32bit (n) length value that it uses to read
+from a buffer. The length is never validated, which can lead to out of
+bound reads, and possibly returning the data read from out of bounds to
+the misbehaving client via an X Error packet.
+
+SProcDbeSwapBuffers() swaps data (for correct endianness) before
+handing it off to the real proc. While doing the swapping, the
+length field is not validated, which can cause memory corruption.
+
+v2: reorder checks to avoid compilers optimizing out checks for overflow
+that happen after we'd already have done the overflowing multiplications.
+
+Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
+Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+---
+ dbe/dbe.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/dbe/dbe.c b/dbe/dbe.c
+index 527588c..df2ad5c 100644
+--- a/dbe/dbe.c
++++ b/dbe/dbe.c
+@@ -450,18 +450,20 @@ ProcDbeSwapBuffers(ClientPtr client)
+ DbeSwapInfoPtr swapInfo;
+ xDbeSwapInfo *dbeSwapInfo;
+ int error;
+- register int i, j;
+- int nStuff;
++ unsigned int i, j;
++ unsigned int nStuff;
+
+ REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq);
+ nStuff = stuff->n; /* use local variable for performance. */
+
+ if (nStuff == 0) {
++ REQUEST_SIZE_MATCH(xDbeSwapBuffersReq);
+ return Success;
+ }
+
+ if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec))
+ return BadAlloc;
++ REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, nStuff * sizeof(xDbeSwapInfo));
+
+ /* Get to the swap info appended to the end of the request. */
+ dbeSwapInfo = (xDbeSwapInfo *) &stuff[1];
+@@ -914,13 +916,16 @@ static int
+ SProcDbeSwapBuffers(ClientPtr client)
+ {
+ REQUEST(xDbeSwapBuffersReq);
+- register int i;
++ unsigned int i;
+ xDbeSwapInfo *pSwapInfo;
+
+ swaps(&stuff->length);
+ REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq);
+
+ swapl(&stuff->n);
++ if (stuff->n > UINT32_MAX / sizeof(DbeSwapInfoRec))
++ return BadAlloc;
++ REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, stuff->n * sizeof(xDbeSwapInfo));
+
+ if (stuff->n != 0) {
+ pSwapInfo = (xDbeSwapInfo *) stuff + 1;
+--
+1.7.9.2
+
diff --git a/debian/patches/CVE-2014-8xxx/0008-Xi-unvalidated-lengths-in-Xinput-extension-CVE-2014-.patch b/debian/patches/CVE-2014-8xxx/0008-Xi-unvalidated-lengths-in-Xinput-extension-CVE-2014-.patch
new file mode 100644
index 0000000..421f070
--- /dev/null
+++ b/debian/patches/CVE-2014-8xxx/0008-Xi-unvalidated-lengths-in-Xinput-extension-CVE-2014-.patch
@@ -0,0 +1,551 @@
+From 54fa1f815507cd27280f661be7a64f2f2e6c579e Mon Sep 17 00:00:00 2001
+From: Alan Coopersmith <alan.coopersmith@oracle.com>
+Date: Sun, 26 Jan 2014 10:54:41 -0800
+Subject: [PATCH 08/33] Xi: unvalidated lengths in Xinput extension
+ [CVE-2014-8095]
+
+Multiple functions in the Xinput extension handling of requests from
+clients failed to check that the length of the request sent by the
+client was large enough to perform all the required operations and
+thus could read or write to memory outside the bounds of the request
+buffer.
+
+This commit includes the creation of a new REQUEST_AT_LEAST_EXTRA_SIZE
+macro in include/dix.h for the common case of needing to ensure a
+request is large enough to include both the request itself and a
+minimum amount of extra data following the request header.
+
+Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
+Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+---
+ Xi/chgdctl.c | 8 ++++++--
+ Xi/chgfctl.c | 2 ++
+ Xi/sendexev.c | 3 +++
+ Xi/xiallowev.c | 2 ++
+ Xi/xichangecursor.c | 2 +-
+ Xi/xichangehierarchy.c | 35 ++++++++++++++++++++++++++++++++---
+ Xi/xigetclientpointer.c | 1 +
+ Xi/xigrabdev.c | 9 ++++++++-
+ Xi/xipassivegrab.c | 12 ++++++++++--
+ Xi/xiproperty.c | 14 ++++++--------
+ Xi/xiquerydevice.c | 1 +
+ Xi/xiquerypointer.c | 2 ++
+ Xi/xiselectev.c | 8 ++++++++
+ Xi/xisetclientpointer.c | 3 ++-
+ Xi/xisetdevfocus.c | 4 ++++
+ Xi/xiwarppointer.c | 2 ++
+ include/dix.h | 4 ++++
+ 17 files changed, 94 insertions(+), 18 deletions(-)
+
+diff --git a/Xi/chgdctl.c b/Xi/chgdctl.c
+index d078aa2..b3ee867 100644
+--- a/Xi/chgdctl.c
++++ b/Xi/chgdctl.c
+@@ -78,7 +78,7 @@ SProcXChangeDeviceControl(ClientPtr client)
+
+ REQUEST(xChangeDeviceControlReq);
+ swaps(&stuff->length);
+- REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq);
++ REQUEST_AT_LEAST_EXTRA_SIZE(xChangeDeviceControlReq, sizeof(xDeviceCtl));
+ swaps(&stuff->control);
+ ctl = (xDeviceCtl *) &stuff[1];
+ swaps(&ctl->control);
+@@ -115,7 +115,7 @@ ProcXChangeDeviceControl(ClientPtr client)
+ xDeviceEnableCtl *e;
+
+ REQUEST(xChangeDeviceControlReq);
+- REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq);
++ REQUEST_AT_LEAST_EXTRA_SIZE(xChangeDeviceControlReq, sizeof(xDeviceCtl));
+
+ len = stuff->length - bytes_to_int32(sizeof(xChangeDeviceControlReq));
+ ret = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess);
+@@ -192,6 +192,10 @@ ProcXChangeDeviceControl(ClientPtr client)
+ break;
+ case DEVICE_ENABLE:
+ e = (xDeviceEnableCtl *) &stuff[1];
++ if ((len != bytes_to_int32(sizeof(xDeviceEnableCtl)))) {
++ ret = BadLength;
++ goto out;
++ }
+
+ if (IsXTestDevice(dev, NULL))
+ status = !Success;
+diff --git a/Xi/chgfctl.c b/Xi/chgfctl.c
+index 6dcf60c..224c2ba 100644
+--- a/Xi/chgfctl.c
++++ b/Xi/chgfctl.c
+@@ -467,6 +467,8 @@ ProcXChangeFeedbackControl(ClientPtr client)
+ xStringFeedbackCtl *f = ((xStringFeedbackCtl *) &stuff[1]);
+
+ if (client->swapped) {
++ if (len < bytes_to_int32(sizeof(xStringFeedbackCtl)))
++ return BadLength;
+ swaps(&f->num_keysyms);
+ }
+ if (len !=
+diff --git a/Xi/sendexev.c b/Xi/sendexev.c
+index 3c21386..183f88d 100644
+--- a/Xi/sendexev.c
++++ b/Xi/sendexev.c
+@@ -135,6 +135,9 @@ ProcXSendExtensionEvent(ClientPtr client)
+ if (ret != Success)
+ return ret;
+
++ if (stuff->num_events == 0)
++ return ret;
++
+ /* The client's event type must be one defined by an extension. */
+
+ first = ((xEvent *) &stuff[1]);
+diff --git a/Xi/xiallowev.c b/Xi/xiallowev.c
+index ebef233..ca263ef 100644
+--- a/Xi/xiallowev.c
++++ b/Xi/xiallowev.c
+@@ -48,6 +48,7 @@ int
+ SProcXIAllowEvents(ClientPtr client)
+ {
+ REQUEST(xXIAllowEventsReq);
++ REQUEST_AT_LEAST_SIZE(xXIAllowEventsReq);
+
+ swaps(&stuff->length);
+ swaps(&stuff->deviceid);
+@@ -55,6 +56,7 @@ SProcXIAllowEvents(ClientPtr client)
+ if (stuff->length > 3) {
+ xXI2_2AllowEventsReq *req_xi22 = (xXI2_2AllowEventsReq *) stuff;
+
++ REQUEST_AT_LEAST_SIZE(xXI2_2AllowEventsReq);
+ swapl(&req_xi22->touchid);
+ swapl(&req_xi22->grab_window);
+ }
+diff --git a/Xi/xichangecursor.c b/Xi/xichangecursor.c
+index 7a1bb7a..8e6255b 100644
+--- a/Xi/xichangecursor.c
++++ b/Xi/xichangecursor.c
+@@ -57,11 +57,11 @@ int
+ SProcXIChangeCursor(ClientPtr client)
+ {
+ REQUEST(xXIChangeCursorReq);
++ REQUEST_SIZE_MATCH(xXIChangeCursorReq);
+ swaps(&stuff->length);
+ swapl(&stuff->win);
+ swapl(&stuff->cursor);
+ swaps(&stuff->deviceid);
+- REQUEST_SIZE_MATCH(xXIChangeCursorReq);
+ return (ProcXIChangeCursor(client));
+ }
+
+diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c
+index 9e36354..2732445 100644
+--- a/Xi/xichangehierarchy.c
++++ b/Xi/xichangehierarchy.c
+@@ -411,7 +411,7 @@ int
+ ProcXIChangeHierarchy(ClientPtr client)
+ {
+ xXIAnyHierarchyChangeInfo *any;
+- int required_len = sizeof(xXIChangeHierarchyReq);
++ size_t len; /* length of data remaining in request */
+ int rc = Success;
+ int flags[MAXDEVICES] = { 0 };
+
+@@ -421,21 +421,46 @@ ProcXIChangeHierarchy(ClientPtr client)
+ if (!stuff->num_changes)
+ return rc;
+
++ if (stuff->length > (INT_MAX >> 2))
++ return BadAlloc;
++ len = (stuff->length << 2) - sizeof(xXIAnyHierarchyChangeInfo);
++
+ any = (xXIAnyHierarchyChangeInfo *) &stuff[1];
+ while (stuff->num_changes--) {
++ if (len < sizeof(xXIAnyHierarchyChangeInfo)) {
++ rc = BadLength;
++ goto unwind;
++ }
++
+ SWAPIF(swaps(&any->type));
+ SWAPIF(swaps(&any->length));
+
+- required_len += any->length;
+- if ((stuff->length * 4) < required_len)
++ if ((any->length > (INT_MAX >> 2)) || (len < (any->length << 2)))
+ return BadLength;
+
++#define CHANGE_SIZE_MATCH(type) \
++ do { \
++ if ((len < sizeof(type)) || (any->length != (sizeof(type) >> 2))) { \
++ rc = BadLength; \
++ goto unwind; \
++ } \
++ } while(0)
++
+ switch (any->type) {
+ case XIAddMaster:
+ {
+ xXIAddMasterInfo *c = (xXIAddMasterInfo *) any;
+
++ /* Variable length, due to appended name string */
++ if (len < sizeof(xXIAddMasterInfo)) {
++ rc = BadLength;
++ goto unwind;
++ }
+ SWAPIF(swaps(&c->name_len));
++ if (c->name_len > (len - sizeof(xXIAddMasterInfo))) {
++ rc = BadLength;
++ goto unwind;
++ }
+
+ rc = add_master(client, c, flags);
+ if (rc != Success)
+@@ -446,6 +471,7 @@ ProcXIChangeHierarchy(ClientPtr client)
+ {
+ xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any;
+
++ CHANGE_SIZE_MATCH(xXIRemoveMasterInfo);
+ rc = remove_master(client, r, flags);
+ if (rc != Success)
+ goto unwind;
+@@ -455,6 +481,7 @@ ProcXIChangeHierarchy(ClientPtr client)
+ {
+ xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any;
+
++ CHANGE_SIZE_MATCH(xXIDetachSlaveInfo);
+ rc = detach_slave(client, c, flags);
+ if (rc != Success)
+ goto unwind;
+@@ -464,6 +491,7 @@ ProcXIChangeHierarchy(ClientPtr client)
+ {
+ xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any;
+
++ CHANGE_SIZE_MATCH(xXIAttachSlaveInfo);
+ rc = attach_slave(client, c, flags);
+ if (rc != Success)
+ goto unwind;
+@@ -471,6 +499,7 @@ ProcXIChangeHierarchy(ClientPtr client)
+ break;
+ }
+
Reply to: