aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeonardo Arena <rnalrd@alpinelinux.org>2016-10-19 10:08:20 +0000
committerLeonardo Arena <rnalrd@alpinelinux.org>2016-10-19 10:08:20 +0000
commit844d03dc7da8ceadec964dc59dc4ba8c7d691ff4 (patch)
treeb44434758a1fbab0b404266d9907208972e70a73
parent518828b1c11d1427085dbd4f8b605bc64593347f (diff)
main/libxtst: security fix (CVE-2016-7951, CVE-2016-7952)
Fixes #6285
-rw-r--r--main/libxtst/APKBUILD17
-rw-r--r--main/libxtst/CVE-2016-7951-7952.patch140
2 files changed, 153 insertions, 4 deletions
diff --git a/main/libxtst/APKBUILD b/main/libxtst/APKBUILD
index 789296d83c8..c5db84c6ad6 100644
--- a/main/libxtst/APKBUILD
+++ b/main/libxtst/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=libxtst
pkgver=1.2.2
-pkgrel=0
+pkgrel=1
pkgdesc="X11 Testing -- Resource extension library"
url="http://xorg.freedesktop.org/"
arch="all"
@@ -11,8 +11,14 @@ depends=
depends_dev="recordproto libx11-dev libxext-dev inputproto libxi-dev"
makedepends="$depends_dev"
source="http://xorg.freedesktop.org/releases/individual/lib/libXtst-$pkgver.tar.bz2
+ CVE-2016-7951-7952.patch
"
+# secfixes:
+# 1.2.2-r1:
+# - CVE-2016-7951
+# - CVE-2016-7952
+
_builddir="$srcdir"/libXtst-$pkgver
prepare() {
cd "$_builddir"
@@ -39,6 +45,9 @@ package() {
install -D -m644 COPYING "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
}
-md5sums="25c6b366ac3dc7a12c5d79816ce96a59 libXtst-1.2.2.tar.bz2"
-sha256sums="ef0a7ffd577e5f1a25b1663b375679529663a1880151beaa73e9186c8309f6d9 libXtst-1.2.2.tar.bz2"
-sha512sums="1cf040f16d426e6a6d1cf8c0f966c171418c082165ae6e9bed6285cd45f144e4ef58bf74c6d34fd81e6894534d21df55efe5d0bc0b2a28f9bb9d74e168dd7369 libXtst-1.2.2.tar.bz2"
+md5sums="25c6b366ac3dc7a12c5d79816ce96a59 libXtst-1.2.2.tar.bz2
+b4e55214fd232d320a8605866323d558 CVE-2016-7951-7952.patch"
+sha256sums="ef0a7ffd577e5f1a25b1663b375679529663a1880151beaa73e9186c8309f6d9 libXtst-1.2.2.tar.bz2
+1ec9df4e192cc5f25f740bad5ff6ddd4ff71b627bd678b512d4e45e22e1748a5 CVE-2016-7951-7952.patch"
+sha512sums="1cf040f16d426e6a6d1cf8c0f966c171418c082165ae6e9bed6285cd45f144e4ef58bf74c6d34fd81e6894534d21df55efe5d0bc0b2a28f9bb9d74e168dd7369 libXtst-1.2.2.tar.bz2
+2f36a94c4ab7107b5d9616bbcf4149cd5a693545e28f2785cd71a46699a8326111d4493b51405df18c314833dfe52438a48f08b50921958124875cf16b977e6d CVE-2016-7951-7952.patch"
diff --git a/main/libxtst/CVE-2016-7951-7952.patch b/main/libxtst/CVE-2016-7951-7952.patch
new file mode 100644
index 00000000000..cd09d793e60
--- /dev/null
+++ b/main/libxtst/CVE-2016-7951-7952.patch
@@ -0,0 +1,140 @@
+From 9556ad67af3129ec4a7a4f4b54a0d59701beeae3 Mon Sep 17 00:00:00 2001
+From: Tobias Stoeckmann <tobias@stoeckmann.org>
+Date: Sun, 25 Sep 2016 21:37:01 +0200
+Subject: 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 <tobias@stoeckmann.org>
+Reviewed-by: Matthieu Herrb <matthieu@herrb.eu>
+
+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) {
+--
+cgit v0.10.2
+