* gnu/packages/patches/libxtst-CVE-2016-7951-CVE-2016-7952.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.
* gnu/packages/xorg.scm (libxtst)[replacement]: New field.
(libxtst/fixed): New variable.
---
 gnu/local.mk                                       |   1 +
 .../libxtst-CVE-2016-7951-CVE-2016-7952.patch      | 152 +++++++++++++++++++++
 gnu/packages/xorg.scm                              |   8 ++
 3 files changed, 161 insertions(+)
 create mode 100644 
gnu/packages/patches/libxtst-CVE-2016-7951-CVE-2016-7952.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index ec237d9..7489ab7 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -676,6 +676,7 @@ dist_patch_DATA =                                           
\
   %D%/packages/patches/libxrandr-CVE-2016-7947-CVE-2016-7948.patch     \
   %D%/packages/patches/libxrender-CVE-2016-7949.patch          \
   %D%/packages/patches/libxrender-CVE-2016-7950.patch          \
+  %D%/packages/patches/libxtst-CVE-2016-7951-CVE-2016-7952.patch       \
   %D%/packages/patches/libxslt-generated-ids.patch             \
   %D%/packages/patches/lirc-localstatedir.patch                        \
   %D%/packages/patches/llvm-for-extempore.patch                        \
diff --git a/gnu/packages/patches/libxtst-CVE-2016-7951-CVE-2016-7952.patch 
b/gnu/packages/patches/libxtst-CVE-2016-7951-CVE-2016-7952.patch
new file mode 100644
index 0000000..9df6cf3
--- /dev/null
+++ b/gnu/packages/patches/libxtst-CVE-2016-7951-CVE-2016-7952.patch
@@ -0,0 +1,152 @@
+Fix CVE-2016-7951 and CVE-2016-7952
+
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7951
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7952
+
+Patch copied from upstream source repository:
+
+https://cgit.freedesktop.org/xorg/lib/libXtst/commit/?id=9556ad67af3129ec4a7a4f4b54a0d59701beeae3
+
+From 9556ad67af3129ec4a7a4f4b54a0d59701beeae3 Mon Sep 17 00:00:00 2001
+From: Tobias Stoeckmann <tob...@stoeckmann.org>
+Date: Sun, 25 Sep 2016 21:37:01 +0200
+Subject: [PATCH] Out of boundary access and endless loop in libXtst
+
+A lack of range checks in libXtst allows out of boundary accesses.
+The checks have to be done in-place here, because it cannot be done
+without in-depth knowledge of the read data.
+
+If XRecordStartOfData, XRecordEndOfData, or XRecordClientDied
+without a client sequence have attached data, an endless loop would
+occur. The do-while-loop continues until the current index reaches
+the end. But in these cases, the current index would not be
+incremented, leading to an endless processing.
+
+Signed-off-by: Tobias Stoeckmann <tob...@stoeckmann.org>
+Reviewed-by: Matthieu Herrb <matth...@herrb.eu>
+---
+ src/XRecord.c | 43 +++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 39 insertions(+), 4 deletions(-)
+
+diff --git a/src/XRecord.c b/src/XRecord.c
+index 50420c0..fefd842 100644
+--- a/src/XRecord.c
++++ b/src/XRecord.c
+@@ -749,15 +749,23 @@ parse_reply_call_callback(
+       switch (rep->category) {
+       case XRecordFromServer:
+           if (rep->elementHeader&XRecordFromServerTime) {
++              if (current_index + 4 > rep->length << 2)
++                  return Error;
+               EXTRACT_CARD32(rep->clientSwapped,
+                              reply->buf+current_index,
+                              data->server_time);
+               current_index += 4;
+           }
++          if (current_index + 1 > rep->length << 2)
++              return Error;
+           switch (reply->buf[current_index]) {
+           case X_Reply: /* reply */
++              if (current_index + 8 > rep->length << 2)
++                  return Error;
+               EXTRACT_CARD32(rep->clientSwapped,
+                              reply->buf+current_index+4, datum_bytes);
++              if (datum_bytes < 0 || datum_bytes > ((INT_MAX >> 2) - 8))
++                  return Error;
+               datum_bytes = (datum_bytes+8) << 2;
+               break;
+           default: /* error or event */
+@@ -766,52 +774,73 @@ parse_reply_call_callback(
+           break;
+       case XRecordFromClient:
+           if (rep->elementHeader&XRecordFromClientTime) {
++              if (current_index + 4 > rep->length << 2)
++                  return Error;
+               EXTRACT_CARD32(rep->clientSwapped,
+                              reply->buf+current_index,
+                              data->server_time);
+               current_index += 4;
+           }
+           if (rep->elementHeader&XRecordFromClientSequence) {
++              if (current_index + 4 > rep->length << 2)
++                  return Error;
+               EXTRACT_CARD32(rep->clientSwapped,
+                              reply->buf+current_index,
+                              data->client_seq);
+               current_index += 4;
+           }
++          if (current_index + 4 > rep->length<<2)
++              return Error;
+           if (reply->buf[current_index+2] == 0
+               && reply->buf[current_index+3] == 0) /* needn't swap 0 */
+           {   /* BIG-REQUESTS */
++              if (current_index + 8 > rep->length << 2)
++                  return Error;
+               EXTRACT_CARD32(rep->clientSwapped,
+                              reply->buf+current_index+4, datum_bytes);
+           } else {
+               EXTRACT_CARD16(rep->clientSwapped,
+                              reply->buf+current_index+2, datum_bytes);
+           }
++          if (datum_bytes < 0 || datum_bytes > INT_MAX >> 2)
++              return Error;
+           datum_bytes <<= 2;
+           break;
+       case XRecordClientStarted:
++          if (current_index + 8 > rep->length << 2)
++              return Error;
+           EXTRACT_CARD16(rep->clientSwapped,
+                          reply->buf+current_index+6, datum_bytes);
+           datum_bytes = (datum_bytes+2) << 2;
+           break;
+       case XRecordClientDied:
+           if (rep->elementHeader&XRecordFromClientSequence) {
++              if (current_index + 4 > rep->length << 2)
++                  return Error;
+               EXTRACT_CARD32(rep->clientSwapped,
+                              reply->buf+current_index,
+                              data->client_seq);
+               current_index += 4;
+-          }
+-          /* fall through */
++          } else if (current_index < rep->length << 2)
++              return Error;
++          datum_bytes = 0;
++          break;
+       case XRecordStartOfData:
+       case XRecordEndOfData:
++          if (current_index < rep->length << 2)
++              return Error;
+           datum_bytes = 0;
++          break;
+       }
+ 
+       if (datum_bytes > 0) {
+-          if (current_index + datum_bytes > rep->length << 2)
++          if (INT_MAX - datum_bytes < (rep->length << 2) - current_index) {
+               fprintf(stderr,
+                       "XRecord: %lu-byte reply claims %d-byte element (seq 
%lu)\n",
+-                      (long)rep->length << 2, current_index + datum_bytes,
++                      (unsigned long)rep->length << 2, current_index + 
datum_bytes,
+                       dpy->last_request_read);
++              return Error;
++          }
+           /*
+            * This assignment (and indeed the whole buffer sharing
+            * scheme) assumes arbitrary 4-byte boundaries are
+@@ -863,6 +892,12 @@ XRecordEnableContext(Display *dpy, XRecordContext context,
+           return 0;
+       }
+ 
++      if (rep.length > INT_MAX >> 2) {
++          UnlockDisplay(dpy);
++          SyncHandle();
++          return 0;
++      }
++
+       if (rep.length > 0) {
+           reply = alloc_reply_buffer(info, rep.length<<2);
+           if (!reply) {
+-- 
+2.10.1
+
diff --git a/gnu/packages/xorg.scm b/gnu/packages/xorg.scm
index 2df6631..111de2b 100644
--- a/gnu/packages/xorg.scm
+++ b/gnu/packages/xorg.scm
@@ -4639,6 +4639,7 @@ cannot be adequately worked around on the client side of 
the wire.")
 (define-public libxtst
   (package
     (name "libxtst")
+    (replacement libxtst/fixed)
     (version "1.2.2")
     (source
       (origin
@@ -4674,6 +4675,13 @@ The RECORD extension supports the recording and 
reporting of all core X
 protocol and arbitrary X extension protocol.")
     (license license:x11)))
 
+(define libxtst/fixed
+  (package
+    (inherit libxtst)
+    (source (origin
+              (inherit (package-source libxtst))
+              (patches (search-patches
+                         "libxtst-CVE-2016-7951-CVE-2016-7952.patch"))))))
 
 (define-public libxv
   (package
-- 
2.10.1


Reply via email to