Author: branden Date: 2004-09-16 16:15:18 -0500 (Thu, 16 Sep 2004) New Revision: 1819
Added: branches/4.1.0/woody/debian/patches/076_SECURITY_libXpm_vulnerabilities.diff Modified: branches/4.1.0/woody/debian/changelog Log: Security update release. Resolves the following issues: + CAN-2004-0687: stack overflows in libXpm + CAN-2004-0688: integer overflows in libXpm Modified: branches/4.1.0/woody/debian/changelog =================================================================== --- branches/4.1.0/woody/debian/changelog 2004-09-15 11:56:07 UTC (rev 1818) +++ branches/4.1.0/woody/debian/changelog 2004-09-16 21:15:18 UTC (rev 1819) @@ -1,3 +1,11 @@ +xfree86 (4.1.0-16woody4) stable-security; urgency=high + + * Security update release. Resolves the following issues: + + CAN-2004-0687: stack overflows in libXpm + + CAN-2004-0688: integer overflows in libXpm + + -- Branden Robinson <[EMAIL PROTECTED]> Thu, 16 Sep 2004 16:13:56 -0500 + xfree86 (4.1.0-16woody3) stable-security; urgency=high * Security update release. Resolves the following issues: Added: branches/4.1.0/woody/debian/patches/076_SECURITY_libXpm_vulnerabilities.diff =================================================================== --- branches/4.1.0/woody/debian/patches/076_SECURITY_libXpm_vulnerabilities.diff 2004-09-15 11:56:07 UTC (rev 1818) +++ branches/4.1.0/woody/debian/patches/076_SECURITY_libXpm_vulnerabilities.diff 2004-09-16 21:15:18 UTC (rev 1819) @@ -0,0 +1,522 @@ +$Id$ + +Fix several security flaws in the Xpm library. Resolves CAN-2004-0687 (libXpm +stack overflows) and CAN-2004-0688 (libXpm integer overflows). + +The following text is by Chris Evans. + + libXpm multiple image parsing flaws + =================================== + + Programs affected: libXpm, and any programs which use libXpm to decode XPM + files. For example, the GIMP seems to use libXpm. + + Severity: Compromise of account used to browse malicious XPM file. + + This advisory lists code flaws discovered by inspection of the libXpm code. + The specific version of libXpm discussed is the release that comes with the + initial X.ORG X11 system source code release. However, these flaws seem to + exist in older versions. + + Flaw 1. Stack-based overflow in xpmParseColors (parse.c). + + Careless use of strcat() in both the XPMv1 and XPMv2/3 parsing code leads + to a stack based overflow that should be exploitable. There are minor + complications due to stack layout; the buffer being overflowed in fact + typically overflows into another buffer that is used to populate the + overflowed buffer. This should not prevent exploitation, however. + + Flaw 2. Integer overflow allocating colorTable in xpmParseColors (parse.c) + -- probably a crashable but not exploitable offence. Here: + + colorTable = (XpmColor *) XpmCalloc(ncolors, sizeof(XpmColor)); + + ncolors would seem to come from the (untrusted) XPM file. + + In fact, multiple integer overflow problems seem to exist. Some may well + be exploitable. Note that the following may not be an exhaustive list: + + a) XpmCreateImageFromXpmImage: multiple possible overflow, e.g.: + image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); + (ncolors is user-supplied) + + b) CreateXImage: + *image_return = XCreateImage(display, visual, depth, format, 0, 0, + width, height, bitmap_pad, 0); + (width and height are user-supplied, possibly other variables too) + + c) ParsePixels: + iptr2 = (unsigned int *) XpmMalloc(sizeof(unsigned int) * width * height); + (width and height are user-supplied) + + d) ParseAndPutPixels and ParsePixels: + cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1; + (possibly, char1 might be negative, and access the cidx array out of bounds) + + Flaw 3. Stack overflow reading pixel values in ParseAndPutPixels + (create.c) as well as ParsePixels (parse.c). Should be exploitable. + + A user-supplied number of bytes are stuffed into a fixed-size buffer (typically + 8192 bytes). The user gets to choose how many bytes to put into this + buffer via the "number of bytes per pixel" XPM value. + +This patch by Matthieu Herrb. + +diff -urN xc/extras/Xpm~/lib/Attrib.c xc/extras/Xpm/lib/Attrib.c +--- xc/extras/Xpm~/lib/Attrib.c 1999-01-11 08:23:09.000000000 -0500 ++++ xc/extras/Xpm/lib/Attrib.c 2004-09-15 16:30:40.000000000 -0500 +@@ -35,7 +35,7 @@ + #include "XpmI.h" + + /* 3.2 backward compatibility code */ +-LFUNC(CreateOldColorTable, int, (XpmColor *ct, int ncolors, ++LFUNC(CreateOldColorTable, int, (XpmColor *ct, unsigned int ncolors, + XpmColor ***oldct)); + + LFUNC(FreeOldColorTable, void, (XpmColor **colorTable, int ncolors)); +@@ -46,12 +46,15 @@ + static int + CreateOldColorTable(ct, ncolors, oldct) + XpmColor *ct; +- int ncolors; ++ unsigned int ncolors; + XpmColor ***oldct; + { + XpmColor **colorTable, **color; + int a; + ++ if (ncolors >= SIZE_MAX / sizeof(XpmColor *)) ++ return XpmNoMemory; ++ + colorTable = (XpmColor **) XpmMalloc(ncolors * sizeof(XpmColor *)); + if (!colorTable) { + *oldct = NULL; +diff -urN xc/extras/Xpm~/lib/CrDatFrI.c xc/extras/Xpm/lib/CrDatFrI.c +--- xc/extras/Xpm~/lib/CrDatFrI.c 1999-01-11 08:23:09.000000000 -0500 ++++ xc/extras/Xpm/lib/CrDatFrI.c 2004-09-15 16:30:40.000000000 -0500 +@@ -123,6 +123,8 @@ + */ + header_nlines = 1 + image->ncolors; + header_size = sizeof(char *) * header_nlines; ++ if (header_size >= SIZE_MAX / sizeof(char *)) ++ return (XpmNoMemory); + header = (char **) XpmCalloc(header_size, sizeof(char *)); + if (!header) + return (XpmNoMemory); +diff -urN xc/extras/Xpm~/lib/WrFFrI.c xc/extras/Xpm/lib/WrFFrI.c +--- xc/extras/Xpm~/lib/WrFFrI.c 1999-01-11 08:23:10.000000000 -0500 ++++ xc/extras/Xpm/lib/WrFFrI.c 2004-09-15 16:30:40.000000000 -0500 +@@ -247,6 +247,8 @@ + unsigned int x, y, h; + + h = height - 1; ++ if (cpp != 0 && width >= (SIZE_MAX - 3)/cpp) ++ return XpmNoMemory; + p = buf = (char *) XpmMalloc(width * cpp + 3); + if (!buf) + return (XpmNoMemory); +diff -urN xc/extras/Xpm~/lib/XpmI.h xc/extras/Xpm/lib/XpmI.h +--- xc/extras/Xpm~/lib/XpmI.h 2000-09-26 10:56:42.000000000 -0500 ++++ xc/extras/Xpm/lib/XpmI.h 2004-09-15 16:30:40.000000000 -0500 +@@ -116,6 +116,18 @@ + boundCheckingCalloc((long)(nelem),(long) (elsize)) + #endif + ++#if defined(SCO) || defined(__USLC__) ++#include <stdint.h> /* For SIZE_MAX */ ++#endif ++#include <limits.h> ++#ifndef SIZE_MAX ++# ifdef ULONG_MAX ++# define SIZE_MAX ULONG_MAX ++# else ++# define SIZE_MAX UINT_MAX ++# endif ++#endif ++ + #define XPMMAXCMTLEN BUFSIZ + typedef struct { + unsigned int type; +@@ -217,9 +229,9 @@ + } *xpmHashAtom; + + typedef struct { +- int size; +- int limit; +- int used; ++ unsigned int size; ++ unsigned int limit; ++ unsigned int used; + xpmHashAtom *atomTable; + } xpmHashTable; + +diff -urN xc/extras/Xpm~/lib/create.c xc/extras/Xpm/lib/create.c +--- xc/extras/Xpm~/lib/create.c 1999-01-11 08:23:10.000000000 -0500 ++++ xc/extras/Xpm/lib/create.c 2004-09-15 16:30:40.000000000 -0500 +@@ -1,3 +1,4 @@ ++/* $XdotOrg: pre-CVS proposed fix for CESA-2004-003 alanc 7/25/2004 $ */ + /* + * Copyright (C) 1989-95 GROUPE BULL + * +@@ -819,6 +820,9 @@ + + ErrorStatus = XpmSuccess; + ++ if (image->ncolors >= SIZE_MAX / sizeof(Pixel)) ++ return (XpmNoMemory); ++ + /* malloc pixels index tables */ + image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); + if (!image_pixels) +@@ -991,6 +995,8 @@ + return (XpmNoMemory); + + #if !defined(FOR_MSW) && !defined(AMIGA) ++ if (height != 0 && (*image_return)->bytes_per_line >= SIZE_MAX / height) ++ return XpmNoMemory; + /* now that bytes_per_line must have been set properly alloc data */ + (*image_return)->data = + (char *) XpmMalloc((*image_return)->bytes_per_line * height); +@@ -2063,6 +2069,9 @@ + xpmGetCmt(data, &colors_cmt); + + /* malloc pixels index tables */ ++ if (ncolors >= SIZE_MAX / sizeof(Pixel)) ++ return XpmNoMemory; ++ + image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); + if (!image_pixels) + RETURN(XpmNoMemory); +@@ -2317,7 +2326,8 @@ + } + obm = SelectObject(*dc, image->bitmap); + #endif +- ++ if (ncolors > 256) ++ return (XpmFileInvalid); + + bzero((char *)colidx, 256 * sizeof(short)); + for (a = 0; a < ncolors; a++) +@@ -2423,6 +2433,9 @@ + char *s; + char buf[BUFSIZ]; + ++ if (cpp >= sizeof(buf)) ++ return (XpmFileInvalid); ++ + buf[cpp] = '\0'; + if (USE_HASHTABLE) { + xpmHashAtom *slot; +diff -urN xc/extras/Xpm~/lib/data.c xc/extras/Xpm/lib/data.c +--- xc/extras/Xpm~/lib/data.c 2000-02-23 15:28:14.000000000 -0500 ++++ xc/extras/Xpm/lib/data.c 2004-09-15 16:30:40.000000000 -0500 +@@ -374,7 +374,7 @@ + { + if (!data->type) + *cmt = NULL; +- else if (data->CommentLength) { ++ else if (data->CommentLength != 0 && data->CommentLength < SIZE_MAX - 1) { + *cmt = (char *) XpmMalloc(data->CommentLength + 1); + strncpy(*cmt, data->Comment, data->CommentLength); + (*cmt)[data->CommentLength] = '\0'; +diff -urN xc/extras/Xpm~/lib/hashtab.c xc/extras/Xpm/lib/hashtab.c +--- xc/extras/Xpm~/lib/hashtab.c 1999-01-11 08:23:11.000000000 -0500 ++++ xc/extras/Xpm/lib/hashtab.c 2004-09-15 16:30:40.000000000 -0500 +@@ -135,7 +135,7 @@ + xpmHashTable *table; + { + xpmHashAtom *atomTable = table->atomTable; +- int size = table->size; ++ unsigned int size = table->size; + xpmHashAtom *t, *p; + int i; + int oldSize = size; +@@ -144,6 +144,8 @@ + HASH_TABLE_GROWS + table->size = size; + table->limit = size / 3; ++ if (size >= SIZE_MAX / sizeof(*atomTable)) ++ return (XpmNoMemory); + atomTable = (xpmHashAtom *) XpmMalloc(size * sizeof(*atomTable)); + if (!atomTable) + return (XpmNoMemory); +@@ -204,6 +206,8 @@ + table->size = INITIAL_HASH_SIZE; + table->limit = table->size / 3; + table->used = 0; ++ if (table->size >= SIZE_MAX / sizeof(*atomTable)) ++ return (XpmNoMemory); + atomTable = (xpmHashAtom *) XpmMalloc(table->size * sizeof(*atomTable)); + if (!atomTable) + return (XpmNoMemory); +diff -urN xc/extras/Xpm~/lib/parse.c xc/extras/Xpm/lib/parse.c +--- xc/extras/Xpm~/lib/parse.c 2000-09-26 10:56:43.000000000 -0500 ++++ xc/extras/Xpm/lib/parse.c 2004-09-16 15:31:32.000000000 -0500 +@@ -1,3 +1,4 @@ ++/* $XdotOrg: pre-CVS proposed fix for CESA-2004-003 alanc 7/25/2004 $ */ + /* + * Copyright (C) 1989-95 GROUPE BULL + * +@@ -43,6 +44,23 @@ + #include <ctype.h> + #include <string.h> + ++#ifdef HAS_STRLCAT ++# define STRLCAT(dst, src, dstsize) { \ ++ if (strlcat(dst, src, dstsize) >= (dstsize)) \ ++ return (XpmFileInvalid); } ++# define STRLCPY(dst, src, dstsize) { \ ++ if (strlcpy(dst, src, dstsize) >= (dstsize)) \ ++ return (XpmFileInvalid); } ++#else ++# define STRLCAT(dst, src, dstsize) { \ ++ if ((strlen(dst) + strlen(src)) < (dstsize)) \ ++ strcat(dst, src); \ ++ else return (XpmFileInvalid); } ++# define STRLCPY(dst, src, dstsize) { \ ++ if (strlen(src) < (dstsize)) \ ++ strcpy(dst, src); \ ++ else return (XpmFileInvalid); } ++ + LFUNC(ParsePixels, int, (xpmData *data, unsigned int width, + unsigned int height, unsigned int ncolors, + unsigned int cpp, XpmColor *colorTable, +@@ -65,7 +83,7 @@ + unsigned int *extensions; + { + unsigned int l; +- char buf[BUFSIZ]; ++ char buf[BUFSIZ + 1]; + + if (!data->format) { /* XPM 2 or 3 */ + +@@ -174,10 +192,10 @@ + XpmColor **colorTablePtr; + xpmHashTable *hashtable; + { +- unsigned int key, l, a, b; ++ unsigned int key = 0, l, a, b, len; + unsigned int curkey; /* current color key */ + unsigned int lastwaskey; /* key read */ +- char buf[BUFSIZ]; ++ char buf[BUFSIZ+1]; + char curbuf[BUFSIZ]; /* current buffer */ + char **sptr, *s; + XpmColor *color; +@@ -185,6 +203,8 @@ + char **defaults; + int ErrorStatus; + ++ if (ncolors >= SIZE_MAX / sizeof(XpmColor)) ++ return (XpmNoMemory); + colorTable = (XpmColor *) XpmCalloc(ncolors, sizeof(XpmColor)); + if (!colorTable) + return (XpmNoMemory); +@@ -196,6 +216,10 @@ + /* + * read pixel value + */ ++ if (cpp >= SIZE_MAX - 1) { ++ xpmFreeColorTable(colorTable, ncolors); ++ return (XpmNoMemory); ++ } + color->string = (char *) XpmMalloc(cpp + 1); + if (!color->string) { + xpmFreeColorTable(colorTable, ncolors); +@@ -233,13 +257,14 @@ + } + if (!lastwaskey && key < NKEYS) { /* open new key */ + if (curkey) { /* flush string */ +- s = (char *) XpmMalloc(strlen(curbuf) + 1); ++ len = strlen(curbuf) + 1; ++ s = (char *) XpmMalloc(len); + if (!s) { + xpmFreeColorTable(colorTable, ncolors); + return (XpmNoMemory); + } + defaults[curkey] = s; +- strcpy(s, curbuf); ++ memcpy(s, curbuf, len); + } + curkey = key + 1; /* set new key */ + *curbuf = '\0'; /* reset curbuf */ +@@ -250,9 +275,9 @@ + return (XpmFileInvalid); + } + if (!lastwaskey) +- strcat(curbuf, " "); /* append space */ ++ STRLCAT(curbuf, " ", sizeof(curbuf)); /* append space */ + buf[l] = '\0'; +- strcat(curbuf, buf);/* append buf */ ++ STRLCAT(curbuf, buf, sizeof(curbuf));/* append buf */ + lastwaskey = 0; + } + } +@@ -260,12 +285,13 @@ + xpmFreeColorTable(colorTable, ncolors); + return (XpmFileInvalid); + } +- s = defaults[curkey] = (char *) XpmMalloc(strlen(curbuf) + 1); ++ len = strlen(curbuf) + 1; ++ s = defaults[curkey] = (char *) XpmMalloc(len); + if (!s) { + xpmFreeColorTable(colorTable, ncolors); + return (XpmNoMemory); + } +- strcpy(s, curbuf); ++ memcpy(s, curbuf, len); + } + } else { /* XPM 1 */ + /* get to the beginning of the first string */ +@@ -278,6 +304,10 @@ + /* + * read pixel value + */ ++ if (cpp >= SIZE_MAX - 1) { ++ xpmFreeColorTable(colorTable, ncolors); ++ return (XpmNoMemory); ++ } + color->string = (char *) XpmMalloc(cpp + 1); + if (!color->string) { + xpmFreeColorTable(colorTable, ncolors); +@@ -306,16 +336,17 @@ + *curbuf = '\0'; /* init curbuf */ + while (l = xpmNextWord(data, buf, BUFSIZ)) { + if (*curbuf != '\0') +- strcat(curbuf, " ");/* append space */ ++ STRLCAT(curbuf, " ", sizeof(curbuf));/* append space */ + buf[l] = '\0'; +- strcat(curbuf, buf); /* append buf */ ++ STRLCAT(curbuf, buf, sizeof(curbuf)); /* append buf */ + } +- s = (char *) XpmMalloc(strlen(curbuf) + 1); ++ len = strlen(curbuf) + 1; ++ s = (char *) XpmMalloc(len); + if (!s) { + xpmFreeColorTable(colorTable, ncolors); + return (XpmNoMemory); + } +- strcpy(s, curbuf); ++ memcpy(s, curbuf, len); + color->c_color = s; + *curbuf = '\0'; /* reset curbuf */ + if (a < ncolors - 1) +@@ -340,6 +371,9 @@ + unsigned int *iptr, *iptr2; + unsigned int a, x, y; + ++ if ((height > 0 && width >= SIZE_MAX / height) || ++ width * height >= SIZE_MAX / sizeof(unsigned int)) ++ return XpmNoMemory; + #ifndef FOR_MSW + iptr2 = (unsigned int *) XpmMalloc(sizeof(unsigned int) * width * height); + #else +@@ -363,6 +397,9 @@ + { + unsigned short colidx[256]; + ++ if (ncolors > 256) ++ return (XpmFileInvalid); ++ + bzero((char *)colidx, 256 * sizeof(short)); + for (a = 0; a < ncolors; a++) + colidx[(unsigned char)colorTable[a].string[0]] = a + 1; +@@ -441,6 +478,9 @@ + char *s; + char buf[BUFSIZ]; + ++ if (cpp >= sizeof(buf)) ++ return (XpmFileInvalid); ++ + buf[cpp] = '\0'; + if (USE_HASHTABLE) { + xpmHashAtom *slot; +diff -urN xc/extras/Xpm~/lib/scan.c xc/extras/Xpm/lib/scan.c +--- xc/extras/Xpm~/lib/scan.c 1999-01-11 08:23:11.000000000 -0500 ++++ xc/extras/Xpm/lib/scan.c 2004-09-15 16:30:40.000000000 -0500 +@@ -103,7 +103,8 @@ + LFUNC(ScanTransparentColor, int, (XpmColor *color, unsigned int cpp, + XpmAttributes *attributes)); + +-LFUNC(ScanOtherColors, int, (Display *display, XpmColor *colors, int ncolors, ++LFUNC(ScanOtherColors, int, (Display *display, XpmColor *colors, ++ unsigned int ncolors, + Pixel *pixels, unsigned int mask, + unsigned int cpp, XpmAttributes *attributes)); + +@@ -228,11 +229,17 @@ + else + cpp = 0; + ++ if ((height > 0 && width >= SIZE_MAX / height) || ++ width * height >= SIZE_MAX / sizeof(unsigned int)) ++ RETURN(XpmNoMemory); + pmap.pixelindex = + (unsigned int *) XpmCalloc(width * height, sizeof(unsigned int)); + if (!pmap.pixelindex) + RETURN(XpmNoMemory); + ++ if (pmap.size >= SIZE_MAX / sizeof(Pixel)) ++ RETURN(XpmNoMemory); ++ + pmap.pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * pmap.size); + if (!pmap.pixels) + RETURN(XpmNoMemory); +@@ -297,7 +304,8 @@ + * get rgb values and a string of char, and possibly a name for each + * color + */ +- ++ if (pmap.ncolors >= SIZE_MAX / sizeof(XpmColor)) ++ RETURN(XpmNoMemory); + colorTable = (XpmColor *) XpmCalloc(pmap.ncolors, sizeof(XpmColor)); + if (!colorTable) + RETURN(XpmNoMemory); +@@ -356,6 +364,8 @@ + + /* first get a character string */ + a = 0; ++ if (cpp >= SIZE_MAX - 1) ++ return (XpmNoMemory); + if (!(s = color->string = (char *) XpmMalloc(cpp + 1))) + return (XpmNoMemory); + *s++ = printable[c = a % MAXPRINTABLE]; +@@ -403,7 +413,7 @@ + ScanOtherColors(display, colors, ncolors, pixels, mask, cpp, attributes) + Display *display; + XpmColor *colors; +- int ncolors; ++ unsigned int ncolors; + Pixel *pixels; + unsigned int mask; + unsigned int cpp; +@@ -447,6 +457,8 @@ + } + + /* first get character strings and rgb values */ ++ if (ncolors >= SIZE_MAX / sizeof(XColor) || cpp >= SIZE_MAX - 1) ++ return (XpmNoMemory); + xcolors = (XColor *) XpmMalloc(sizeof(XColor) * ncolors); + if (!xcolors) + return (XpmNoMemory); +diff -urN xc/lib/Xpm~/Imakefile xc/lib/Xpm/Imakefile +--- xc/lib/Xpm~/Imakefile 2000-09-19 07:46:06.000000000 -0500 ++++ xc/lib/Xpm/Imakefile 2004-09-15 16:30:40.000000000 -0500 +@@ -42,11 +42,16 @@ + SPRINTFDEF = -DVOID_SPRINTF + #endif + ++#if HasStrlcat ++STRLCATDEF = -DHAS_STRLCAT ++#endif ++ + #if defined(Win32Architecture) + ZPIPEDEF = -DNO_ZPIPE + #endif + +-DEFINES = $(STRDUPDEF) $(STRCASECMPDEF) $(SPRINTFDEF) $(ZPIPEDEF) $(ZFILEDEF) ++DEFINES = $(STRDUPDEF) $(STRCASECMPDEF) $(SPRINTFDEF) $(STRLCATDEF) \ ++ $(ZPIPEDEF) $(ZFILEDEF) + + HEADERS = xpm.h + Property changes on: branches/4.1.0/woody/debian/patches/076_SECURITY_libXpm_vulnerabilities.diff ___________________________________________________________________ Name: svn:keywords + Id