From 13c10b4ca41e4c03a4d500a9fd0c25244c1faab6 Mon Sep 17 00:00:00 2001 From: Leo Famulari Date: Wed, 5 Oct 2016 13:08:08 -0400 Subject: [PATCH] gnu: libx11: Fix CVE-2016-{7942,7943}. * gnu/packages/patches/libx11-CVE-2016-7942.patch, gnu/packages/patches/libx11-CVE-2016-7943.patch: New files. * gnu/local.mk (dist_patch_DATA): Add them. * gnu/packages/xorg.scm (libx11)[replacement]: New field. (libx11/fixed): New variable. --- gnu/local.mk | 2 + .../patches/libx11-CVE-2016-7942.patch | 76 ++++++++++++ .../patches/libx11-CVE-2016-7943.patch | 113 ++++++++++++++++++ gnu/packages/xorg.scm | 9 ++ 4 files changed, 200 insertions(+) create mode 100644 gnu/packages/patches/libx11-CVE-2016-7942.patch create mode 100644 gnu/packages/patches/libx11-CVE-2016-7943.patch diff --git a/gnu/local.mk b/gnu/local.mk index a609bf697c..03d07f60cf 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -669,6 +669,8 @@ dist_patch_DATA = \ %D%/packages/patches/libwmf-CVE-2015-0848+CVE-2015-4588.patch \ %D%/packages/patches/libwmf-CVE-2015-4695.patch \ %D%/packages/patches/libwmf-CVE-2015-4696.patch \ + %D%/packages/patches/libx11-CVE-2016-7942.patch \ + %D%/packages/patches/libx11-CVE-2016-7943.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/libx11-CVE-2016-7942.patch b/gnu/packages/patches/libx11-CVE-2016-7942.patch new file mode 100644 index 0000000000..75770235ef --- /dev/null +++ b/gnu/packages/patches/libx11-CVE-2016-7942.patch @@ -0,0 +1,76 @@ +Fix CVE-2016-7942: + +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7942 + +Patch copied from upstream source repository: + +https://cgit.freedesktop.org/xorg/lib/libX11/commit/?id=8ea762f94f4c942d898fdeb590a1630c83235c17 + +From 8ea762f94f4c942d898fdeb590a1630c83235c17 Mon Sep 17 00:00:00 2001 +From: Tobias Stoeckmann +Date: Sun, 25 Sep 2016 21:25:25 +0200 +Subject: [PATCH] Validation of server responses in XGetImage() + +Check if enough bytes were received for specified image type and +geometry. Otherwise GetPixel and other functions could trigger an +out of boundary read later on. + +Signed-off-by: Tobias Stoeckmann +Reviewed-by: Matthieu Herrb +--- + src/GetImage.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +diff --git a/src/GetImage.c b/src/GetImage.c +index c461abc..ff32d58 100644 +--- a/src/GetImage.c ++++ b/src/GetImage.c +@@ -59,6 +59,7 @@ XImage *XGetImage ( + char *data; + unsigned long nbytes; + XImage *image; ++ int planes; + LockDisplay(dpy); + GetReq (GetImage, req); + /* +@@ -91,18 +92,28 @@ XImage *XGetImage ( + return (XImage *) NULL; + } + _XReadPad (dpy, data, nbytes); +- if (format == XYPixmap) +- image = XCreateImage(dpy, _XVIDtoVisual(dpy, rep.visual), +- Ones (plane_mask & +- (((unsigned long)0xFFFFFFFF) >> (32 - rep.depth))), +- format, 0, data, width, height, dpy->bitmap_pad, 0); +- else /* format == ZPixmap */ +- image = XCreateImage (dpy, _XVIDtoVisual(dpy, rep.visual), +- rep.depth, ZPixmap, 0, data, width, height, +- _XGetScanlinePad(dpy, (int) rep.depth), 0); ++ if (format == XYPixmap) { ++ image = XCreateImage(dpy, _XVIDtoVisual(dpy, rep.visual), ++ Ones (plane_mask & ++ (((unsigned long)0xFFFFFFFF) >> (32 - rep.depth))), ++ format, 0, data, width, height, dpy->bitmap_pad, 0); ++ planes = image->depth; ++ } else { /* format == ZPixmap */ ++ image = XCreateImage (dpy, _XVIDtoVisual(dpy, rep.visual), ++ rep.depth, ZPixmap, 0, data, width, height, ++ _XGetScanlinePad(dpy, (int) rep.depth), 0); ++ planes = 1; ++ } + + if (!image) + Xfree(data); ++ if (planes < 1 || image->height < 1 || image->bytes_per_line < 1 || ++ INT_MAX / image->height <= image->bytes_per_line || ++ INT_MAX / planes <= image->height * image->bytes_per_line || ++ nbytes < planes * image->height * image->bytes_per_line) { ++ XDestroyImage(image); ++ image = NULL; ++ } + UnlockDisplay(dpy); + SyncHandle(); + return (image); +-- +2.10.1 + diff --git a/gnu/packages/patches/libx11-CVE-2016-7943.patch b/gnu/packages/patches/libx11-CVE-2016-7943.patch new file mode 100644 index 0000000000..7bcbc58dd4 --- /dev/null +++ b/gnu/packages/patches/libx11-CVE-2016-7943.patch @@ -0,0 +1,113 @@ +Fix CVE-2016-7943: + +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7943. + +Patch copied from upstream source repository: + +https://cgit.freedesktop.org/xorg/lib/libX11/commit/?id=8c29f1607a31dac0911e45a0dd3d74173822b3c9 + +From 8c29f1607a31dac0911e45a0dd3d74173822b3c9 Mon Sep 17 00:00:00 2001 +From: Tobias Stoeckmann +Date: Sun, 25 Sep 2016 21:22:57 +0200 +Subject: [PATCH] The validation of server responses avoids out of boundary + accesses. + +v2: FontNames.c return a NULL list whenever a single +length field from the server is incohent. + +Signed-off-by: Tobias Stoeckmann +Reviewed-by: Matthieu Herrb +--- + src/FontNames.c | 23 +++++++++++++++++------ + src/ListExt.c | 12 ++++++++---- + src/ModMap.c | 3 ++- + 3 files changed, 27 insertions(+), 11 deletions(-) + +diff --git a/src/FontNames.c b/src/FontNames.c +index 21dcafe..e55f338 100644 +--- a/src/FontNames.c ++++ b/src/FontNames.c +@@ -66,7 +66,7 @@ int *actualCount) /* RETURN */ + + if (rep.nFonts) { + flist = Xmalloc (rep.nFonts * sizeof(char *)); +- if (rep.length < (INT_MAX >> 2)) { ++ if (rep.length > 0 && rep.length < (INT_MAX >> 2)) { + rlen = rep.length << 2; + ch = Xmalloc(rlen + 1); + /* +1 to leave room for last null-terminator */ +@@ -93,11 +93,22 @@ int *actualCount) /* RETURN */ + if (ch + length < chend) { + flist[i] = ch + 1; /* skip over length */ + ch += length + 1; /* find next length ... */ +- length = *(unsigned char *)ch; +- *ch = '\0'; /* and replace with null-termination */ +- count++; +- } else +- flist[i] = NULL; ++ if (ch <= chend) { ++ length = *(unsigned char *)ch; ++ *ch = '\0'; /* and replace with null-termination */ ++ count++; ++ } else { ++ Xfree(flist); ++ flist = NULL; ++ count = 0; ++ break; ++ } ++ } else { ++ Xfree(flist); ++ flist = NULL; ++ count = 0; ++ break; ++ } + } + } + *actualCount = count; +diff --git a/src/ListExt.c b/src/ListExt.c +index be6b989..0516e45 100644 +--- a/src/ListExt.c ++++ b/src/ListExt.c +@@ -55,7 +55,7 @@ char **XListExtensions( + + if (rep.nExtensions) { + list = Xmalloc (rep.nExtensions * sizeof (char *)); +- if (rep.length < (INT_MAX >> 2)) { ++ if (rep.length > 0 && rep.length < (INT_MAX >> 2)) { + rlen = rep.length << 2; + ch = Xmalloc (rlen + 1); + /* +1 to leave room for last null-terminator */ +@@ -80,9 +80,13 @@ char **XListExtensions( + if (ch + length < chend) { + list[i] = ch+1; /* skip over length */ + ch += length + 1; /* find next length ... */ +- length = *ch; +- *ch = '\0'; /* and replace with null-termination */ +- count++; ++ if (ch <= chend) { ++ length = *ch; ++ *ch = '\0'; /* and replace with null-termination */ ++ count++; ++ } else { ++ list[i] = NULL; ++ } + } else + list[i] = NULL; + } +diff --git a/src/ModMap.c b/src/ModMap.c +index a809aa2..49a5d08 100644 +--- a/src/ModMap.c ++++ b/src/ModMap.c +@@ -42,7 +42,8 @@ XGetModifierMapping(register Display *dpy) + GetEmptyReq(GetModifierMapping, req); + (void) _XReply (dpy, (xReply *)&rep, 0, xFalse); + +- if (rep.length < (INT_MAX >> 2)) { ++ if (rep.length < (INT_MAX >> 2) && ++ (rep.length >> 1) == rep.numKeyPerModifier) { + nbytes = (unsigned long)rep.length << 2; + res = Xmalloc(sizeof (XModifierKeymap)); + if (res) +-- +2.10.1 + diff --git a/gnu/packages/xorg.scm b/gnu/packages/xorg.scm index 0d3cdce37c..83dfd5d798 100644 --- a/gnu/packages/xorg.scm +++ b/gnu/packages/xorg.scm @@ -5181,6 +5181,7 @@ draggable titlebars and borders.") (define-public libx11 (package (name "libx11") + (replacement libx11/fixed) (version "1.6.3") (source (origin @@ -5213,6 +5214,14 @@ draggable titlebars and borders.") (description "Xorg Core X11 protocol client library.") (license license:x11))) +(define libx11/fixed + (package + (inherit libx11) + (source (origin + (inherit (package-source libx11)) + (patches (search-patches + "libx11-CVE-2016-7942.patch" + "libx11-CVE-2016-7943.patch")))))) ;; packages of height 5 in the propagated-inputs tree