Fixes for CVE-2023-43788 and CVE-2023-43789

Includes hardening for CVE-2023-43786 and CVE-2023-43787.

Check X.Org Security Advisory [1] for more information.

[1] https://lists.x.org/archives/xorg-announce/2023-October/003424.html
Resolves: https://issues.redhat.com/browse/RHEL-12414
This commit is contained in:
José Expósito 2023-10-11 13:04:16 +02:00
parent 66ff8aa7cd
commit a3c0591d4a
5 changed files with 408 additions and 1 deletions

View File

@ -0,0 +1,284 @@
From 84fb14574c039f19ad7face87eb9acc31a50701c Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Wed, 6 Sep 2023 17:34:33 -0700
Subject: [PATCH] Avoid CVE-2023-43786: stack exhaustion in XPutImage()
This doesn't fix the CVE - that has to happen in libX11, this
just tries to avoid triggering it from libXpm, and saves time
in not pretending we can successfully create an X11 pixmap with
dimensions larger than the unsigned 16-bit integers used in the
X11 protocol for the dimensions.
Reported by Yair Mizrahi of the JFrog Vulnerability Research team
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
---
src/CrPFrBuf.c | 28 +++++++++++++++++++++++-----
src/CrPFrDat.c | 31 +++++++++++++++++++++++--------
src/CrPFrI.c | 10 +++++++++-
src/RdFToP.c | 28 +++++++++++++++++++++++-----
src/XpmI.h | 2 +-
src/create.c | 28 +++++++++++++++++++++++-----
6 files changed, 102 insertions(+), 25 deletions(-)
diff --git a/src/CrPFrBuf.c b/src/CrPFrBuf.c
index 2c28a41..e9e2243 100644
--- a/src/CrPFrBuf.c
+++ b/src/CrPFrBuf.c
@@ -46,7 +46,7 @@ XpmCreatePixmapFromBuffer(
Pixmap *shapemask_return,
XpmAttributes *attributes)
{
- XImage *ximage, *shapeimage;
+ XImage *ximage = NULL, *shapeimage = NULL;
int ErrorStatus;
/* initialize return values */
@@ -63,16 +63,34 @@ XpmCreatePixmapFromBuffer(
attributes);
if (ErrorStatus < 0) /* fatal error */
- return (ErrorStatus);
+ goto cleanup;
/* create the pixmaps and destroy images */
if (pixmap_return && ximage) {
- xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
- XDestroyImage(ximage);
+ ErrorStatus =
+ xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
+ if (ErrorStatus < 0) /* fatal error */
+ goto cleanup;
}
if (shapemask_return && shapeimage) {
- xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
+ ErrorStatus =
+ xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
+ }
+
+ cleanup:
+ if (ximage != NULL)
+ XDestroyImage(ximage);
+ if (shapeimage != NULL)
XDestroyImage(shapeimage);
+ if (ErrorStatus < 0) {
+ if (pixmap_return && *pixmap_return) {
+ XFreePixmap(display, *pixmap_return);
+ *pixmap_return = 0;
+ }
+ if (shapemask_return && *shapemask_return) {
+ XFreePixmap(display, *shapemask_return);
+ *shapemask_return = 0;
+ }
}
return (ErrorStatus);
}
diff --git a/src/CrPFrDat.c b/src/CrPFrDat.c
index b65771d..8622663 100644
--- a/src/CrPFrDat.c
+++ b/src/CrPFrDat.c
@@ -46,7 +46,7 @@ XpmCreatePixmapFromData(
Pixmap *shapemask_return,
XpmAttributes *attributes)
{
- XImage *ximage, *shapeimage;
+ XImage *ximage = NULL, *shapeimage = NULL;
int ErrorStatus;
/* initialize return values */
@@ -63,19 +63,34 @@ XpmCreatePixmapFromData(
attributes);
if (ErrorStatus != XpmSuccess)
- return (ErrorStatus);
-
- if (ErrorStatus < 0) /* fatal error */
- return (ErrorStatus);
+ goto cleanup;
/* create the pixmaps and destroy images */
if (pixmap_return && ximage) {
- xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
- XDestroyImage(ximage);
+ ErrorStatus =
+ xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
+ if (ErrorStatus < 0) /* fatal error */
+ goto cleanup;
}
if (shapemask_return && shapeimage) {
- xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
+ ErrorStatus =
+ xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
+ }
+
+ cleanup:
+ if (ximage != NULL)
+ XDestroyImage(ximage);
+ if (shapeimage != NULL)
XDestroyImage(shapeimage);
+ if (ErrorStatus < 0) {
+ if (pixmap_return && *pixmap_return) {
+ XFreePixmap(display, *pixmap_return);
+ *pixmap_return = 0;
+ }
+ if (shapemask_return && *shapemask_return) {
+ XFreePixmap(display, *shapemask_return);
+ *shapemask_return = 0;
+ }
}
return (ErrorStatus);
}
diff --git a/src/CrPFrI.c b/src/CrPFrI.c
index 8f6f4aa..f6688c5 100644
--- a/src/CrPFrI.c
+++ b/src/CrPFrI.c
@@ -36,8 +36,9 @@
#include <config.h>
#endif
#include "XpmI.h"
+#include <stdint.h>
-void
+int
xpmCreatePixmapFromImage(
Display *display,
Drawable d,
@@ -47,6 +48,11 @@ xpmCreatePixmapFromImage(
GC gc;
XGCValues values;
+ /* X Pixmaps are limited to unsigned 16-bit height/width */
+ if ((ximage->width > UINT16_MAX) || (ximage->height > UINT16_MAX)) {
+ return XpmNoMemory;
+ }
+
*pixmap_return = XCreatePixmap(display, d, ximage->width,
ximage->height, ximage->depth);
/* set fg and bg in case we have an XYBitmap */
@@ -59,4 +65,6 @@ xpmCreatePixmapFromImage(
ximage->width, ximage->height);
XFreeGC(display, gc);
+
+ return XpmSuccess;
}
diff --git a/src/RdFToP.c b/src/RdFToP.c
index f829757..2c3e7f9 100644
--- a/src/RdFToP.c
+++ b/src/RdFToP.c
@@ -46,7 +46,7 @@ XpmReadFileToPixmap(
Pixmap *shapemask_return,
XpmAttributes *attributes)
{
- XImage *ximage, *shapeimage;
+ XImage *ximage = NULL, *shapeimage = NULL;
int ErrorStatus;
/* initialize return values */
@@ -62,16 +62,34 @@ XpmReadFileToPixmap(
attributes);
if (ErrorStatus < 0) /* fatal error */
- return (ErrorStatus);
+ goto cleanup;
/* create the pixmaps and destroy images */
if (pixmap_return && ximage) {
- xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
- XDestroyImage(ximage);
+ ErrorStatus =
+ xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
+ if (ErrorStatus < 0) /* fatal error */
+ goto cleanup;
}
if (shapemask_return && shapeimage) {
- xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
+ ErrorStatus =
+ xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
+ }
+
+ cleanup:
+ if (ximage != NULL)
+ XDestroyImage(ximage);
+ if (shapeimage != NULL)
XDestroyImage(shapeimage);
+ if (ErrorStatus < 0) {
+ if (pixmap_return && *pixmap_return) {
+ XFreePixmap(display, *pixmap_return);
+ *pixmap_return = 0;
+ }
+ if (shapemask_return && *shapemask_return) {
+ XFreePixmap(display, *shapemask_return);
+ *shapemask_return = 0;
+ }
}
return (ErrorStatus);
}
diff --git a/src/XpmI.h b/src/XpmI.h
index ab7a680..6691693 100644
--- a/src/XpmI.h
+++ b/src/XpmI.h
@@ -195,7 +195,7 @@ FUNC(xpmSetAttributes, void, (XpmAttributes *attributes, XpmImage *image,
XpmInfo *info));
#if !defined(FOR_MSW) && !defined(AMIGA)
-FUNC(xpmCreatePixmapFromImage, void, (Display *display, Drawable d,
+FUNC(xpmCreatePixmapFromImage, int, (Display *display, Drawable d,
XImage *ximage, Pixmap *pixmap_return));
FUNC(xpmCreateImageFromPixmap, void, (Display *display, Pixmap pixmap,
diff --git a/src/create.c b/src/create.c
index 4921c7d..ec562b2 100644
--- a/src/create.c
+++ b/src/create.c
@@ -1652,7 +1652,7 @@ XpmCreatePixmapFromXpmImage(
Pixmap *shapemask_return,
XpmAttributes *attributes)
{
- XImage *ximage, *shapeimage;
+ XImage *ximage = NULL, *shapeimage = NULL;
int ErrorStatus;
/* initialize return values */
@@ -1668,16 +1668,34 @@ XpmCreatePixmapFromXpmImage(
&shapeimage : NULL),
attributes);
if (ErrorStatus < 0)
- return (ErrorStatus);
+ goto cleanup;
/* create the pixmaps and destroy images */
if (pixmap_return && ximage) {
- xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
- XDestroyImage(ximage);
+ ErrorStatus =
+ xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
+ if (ErrorStatus < 0) /* fatal error */
+ goto cleanup;
}
if (shapemask_return && shapeimage) {
- xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
+ ErrorStatus =
+ xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
+ }
+
+ cleanup:
+ if (ximage != NULL)
+ XDestroyImage(ximage);
+ if (shapeimage != NULL)
XDestroyImage(shapeimage);
+ if (ErrorStatus < 0) {
+ if (pixmap_return && *pixmap_return) {
+ XFreePixmap(display, *pixmap_return);
+ *pixmap_return = 0;
+ }
+ if (shapemask_return && *shapemask_return) {
+ XFreePixmap(display, *shapemask_return);
+ *shapemask_return = 0;
+ }
}
return (ErrorStatus);
}
--
2.41.0

View File

@ -0,0 +1,35 @@
From 91f887b41bf75648df725a4ed3be036da02e911e Mon Sep 17 00:00:00 2001
From: Yair Mizrahi <yairm@jfrog.com>
Date: Thu, 7 Sep 2023 16:59:07 -0700
Subject: [PATCH] Avoid CVE-2023-43787 (integer overflow in XCreateImage)
This doesn't fix the CVE - that has to happen in libX11, this
just tries to avoid triggering it from libXpm, and saves time
in not pretending we can successfully create an X Image for
which the width * depth would overflow the signed int used to
store the bytes_per_line value.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
---
src/create.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/create.c b/src/create.c
index ec562b2..b8c80d2 100644
--- a/src/create.c
+++ b/src/create.c
@@ -997,6 +997,11 @@ CreateXImage(
*image_return = NULL;
return XpmNoMemory;
}
+ if (width != 0 && (*image_return)->bits_per_pixel >= INT_MAX / width) {
+ XDestroyImage(*image_return);
+ *image_return = NULL;
+ return XpmNoMemory;
+ }
/* now that bytes_per_line must have been set properly alloc data */
if((*image_return)->bytes_per_line == 0 || height == 0) {
XDestroyImage(*image_return);
--
2.41.0

View File

@ -0,0 +1,32 @@
From 2fa554b01ef6079a9b35df9332bdc4f139ed67e0 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Sat, 29 Apr 2023 17:50:39 -0700
Subject: [PATCH] Fix CVE-2023-43788: Out of bounds read in
XpmCreateXpmImageFromBuffer
When the test case for CVE-2022-46285 was run with the Address Sanitizer
enabled, it found an out-of-bounds read in ParseComment() when reading
from a memory buffer instead of a file, as it continued to look for the
closing comment marker past the end of the buffer.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
---
src/data.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/data.c b/src/data.c
index 7524e65..0b0f1f3 100644
--- a/src/data.c
+++ b/src/data.c
@@ -108,7 +108,7 @@ ParseComment(xpmData *data)
n++;
s2++;
} while (c == *s2 && *s2 != '\0' && c);
- if (*s2 == '\0') {
+ if (*s2 == '\0' || c == '\0') {
/* this is the end of the comment */
notend = 0;
data->cptr--;
--
2.41.0

View File

@ -0,0 +1,36 @@
From 7e21cb63b9a1ca760a06cc4cd9b19bbc3fcd8f51 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Sat, 29 Apr 2023 18:30:34 -0700
Subject: [PATCH] Fix CVE-2023-43789: Out of bounds read on XPM with corrupted
colormap
Found with clang's libfuzzer
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
---
src/data.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/data.c b/src/data.c
index 0b0f1f3..6e87455 100644
--- a/src/data.c
+++ b/src/data.c
@@ -259,13 +259,13 @@ xpmNextWord(
int c;
if (!data->type || data->type == XPMBUFFER) {
- while (isspace(c = *data->cptr) && c != data->Eos)
+ while ((c = *data->cptr) && isspace(c) && (c != data->Eos))
data->cptr++;
do {
c = *data->cptr++;
*buf++ = c;
n++;
- } while (!isspace(c) && c != data->Eos && n < buflen);
+ } while (c && !isspace(c) && (c != data->Eos) && (n < buflen));
n--;
data->cptr--;
} else {
--
2.41.0

View File

@ -1,7 +1,7 @@
Summary: X.Org X11 libXpm runtime library
Name: libXpm
Version: 3.5.13
Release: 8%{?dist}
Release: 9%{?dist}
License: MIT
URL: http://www.x.org
@ -22,6 +22,14 @@ Patch0003: 0003-Prevent-a-double-free-in-the-error-code-path.patch
Patch0004: 0004-configure-add-disable-open-zfile-instead-of-requirin.patch
Patch0005: 0005-Fix-CVE-2022-4883-compression-commands-depend-on-PAT.patch
Patch0006: 0006-Use-gzip-d-instead-of-gunzip.patch
# CVE-2023-43788
Patch0007: 0001-Fix-CVE-2023-43788-Out-of-bounds-read-in-XpmCreateXp.patch
# CVE-2023-43789
Patch0008: 0001-Fix-CVE-2023-43789-Out-of-bounds-read-on-XPM-with-co.patch
# CVE-2023-43786
Patch0009: 0001-Avoid-CVE-2023-43786-stack-exhaustion-in-XPutImage.patch
# CVE-2023-43787
Patch0010: 0001-Avoid-CVE-2023-43787-integer-overflow-in-XCreateImag.patch
%description
X.Org X11 libXpm runtime library
@ -42,6 +50,10 @@ X.Org X11 libXpm development package
%patch0004 -p1
%patch0005 -p1
%patch0006 -p1
%patch0007 -p1
%patch0008 -p1
%patch0009 -p1
%patch0010 -p1
%build
autoreconf -v --install --force
@ -75,6 +87,14 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
#%{_mandir}/man1/*.1x*
%changelog
* Wed Oct 11 2023 José Expósito <jexposit@redhat.com> - 3.5.13-9
- CVE-2023-43786 libX11: stack exhaustion from infinite recursion
in PutSubImage()
- CVE-2023-43787 libX11: integer overflow in XCreateImage() leading to
a heap overflow
- CVE-2023-43788 libXpm: out of bounds read in XpmCreateXpmImageFromBuffer()
- CVE-2023-43789 libXpm: out of bounds read on XPM with corrupted colormap
* Mon Jan 16 2023 Peter Hutterer <peter.hutterer@redhat.com> - 3.5.13-8
- Fix CVE-2022-46285: infinite loop on unclosed comments (#2160230)
- Fix CVE-2022-44617: runaway loop with width of 0 (#2160232)