Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 86894 - media-gfx/xv: new issues
Summary: media-gfx/xv: new issues
Status: RESOLVED DUPLICATE of bug 88742
Alias: None
Product: Gentoo Security
Classification: Unclassified
Component: Vulnerabilities (show other bugs)
Hardware: All All
: High normal (vote)
Assignee: Gentoo Security
URL:
Whiteboard: B2 [upstream] CLASSIFIED
Keywords:
Depends on:
Blocks:
 
Reported: 2005-03-27 13:20 UTC by Sune Kloppenborg Jeppesen (RETIRED)
Modified: 2008-11-05 08:51 UTC (History)
0 users

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sune Kloppenborg Jeppesen (RETIRED) gentoo-dev 2005-03-27 13:20:03 UTC
The vulnerability in question is the XV input-validation one from
last August or so; Gentoo, SuSE, OpenBSD, and undoubtedly other
vendors all put together various patches addressing the problem to
varying extents.  The vulnerability (or the set of them, really) was
brought to light in a BugTraq posting that included a (supposedly)
working exploit for one of them:

        http://www.securityfocus.com/archive/1/372345

The problem is that the additional checks considered only single-factor
or two-factor overflows--that is, are height and width reasonable?  Is
their product positive?  For example, the SuSE/Gentoo patch includes
this fragment (from http://bugs.gentoo.org/show_bug.cgi?id=61619):

--- xvpcx.c
+++ xvpcx.c     Tue Aug 24 13:12:15 2004
@@ -222,7 +222,14 @@
   byte *image;
   
   /* note:  overallocation to make life easier... */
-  image = (byte *) malloc((size_t) (pinfo->h + 1) * pinfo->w + 16);
+  int count = (pinfo->h + 1) * pinfo->w + 16;
+
+  if (count <= 0 || pinfo->h <= 0 || pinfo->w <= 0) {
+    pcxError(fname, "Bogus PCX file!!");
+    return (0);
+  }
+
+  image = (byte *) malloc((size_t) count);
   if (!image) FatalError("Can't alloc 'image' in pcxLoadImage8()");
   
   xvbzero((char *) image, (size_t) ((pinfo->h+1) * pinfo->w + 16));

(This is in the 8-bit code.)  Because of the additive factors, count
can be as large as 4295032848 == 65552 on machines with 32-bit integers;
obviously that's positive.  Setting the height to 65536 and the width
to 65535 requires only 15 bytes of "fill" before the heap-overflowing
exploit code can begin.

The more general case is in the 24-bit code; this is the one that
is most likely to affect all other 24-bit formats, too:

@@ -250,17 +257,25 @@
 {
   byte *pix, *pic24, scale[256];
   int   c, i, j, w, h, maxv, cnt, planes, bperlin, nbytes;
+  int count;
   
   w = pinfo->w;  h = pinfo->h;
   
   planes = (int) hdr[PCX_PLANES];
   bperlin = hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8);
   
+  count = w*h*planes;
+
+  if (count <= 0 || planes <= 0 || w <= 0 || h <= 0) {
+    pcxError(fname, "Bogus PCX file!!");
+    return (0);
+  }
+
   /* allocate 24-bit image */
-  pic24 = (byte *) malloc((size_t) w*h*planes);
+  pic24 = (byte *) malloc((size_t) count);
   if (!pic24) FatalError("couldn't malloc 'pic24'");
   
-  xvbzero((char *) pic24, (size_t) w*h*planes);
+  xvbzero((char *) pic24, (size_t) count);
   
   maxv = 0;
   pix = pinfo->pic = pic24;

In principle, "planes" can be as large as 255, but this function isn't
reached unless it's exactly equal to 3.  That's more than enough when
w and h can each be as large as 65536, however.

My PCX demo images, which contain enough information to allow a clueful
attacker to spread the joy to other image formats, have unfortunately
been attached to this KDE bug:

        http://bugs.kde.org/show_bug.cgi?id=102328

(I moved the images on my site before anyone else downloaded them--
at least, assuming my ISP's web logs can be trusted--so those links
are now broken.  But the attachment, id 10321, is officially Out There,
and I have no control over it.)

Note that, despite the implication in the KDE bug report, this is not
limited to the PCX format--in XV, it also affects at least xvpm.c and
xvpng.c, and almost certainly xvjpeg.c and xvtiff.c as well.  Nor is it
necessarily limited to corrupted images; one could create a perfectly
valid 4 GB PCX image whose pixel data just happened to be interpretable
as executable code, though it's unlikely to be an effective trojan.

It is also not limited solely to XV and gwenview.  Bruno reported that
ImageMagick's convert suffers some sort of memory over-allocation problem
(a DoS, at least), and IrfanView (Win32) crashes.  He found Imlib-based
decoders seem to be immune, as does the GIMP (not sure if it's based on
Imlib).  In general, any 24-bit image decoder that allocates a single
buffer to hold the entire image may be vulnerable.

Here's my patch for xvpcx.c and xvpm.c (against the original XV 3.10a
sources).  I haven't yet had time to make similar fixes for the PNG
decoder or any others, and the patch includes some extra whitespace
fluff since it's extracted from my jumbo-bugfix patch.  (Sorry.)  A
couple of the comments may differ slightly from what I sent to CERT.

diff -ru xv-3.10a/xvpcx.c xv-3.10a-bugfixes/xvpcx.c
--- xv-3.10a/xvpcx.c    1995-01-10 15:06:37.000000000 -0800
+++ xv-3.10a-bugfixes/xvpcx.c   2005-03-20 20:45:00.000000000 -0800
@@ -218,15 +218,21 @@
      byte    *hdr;
 {
   /* load an image with at most 8 bits per pixel */
-  
+
   byte *image;
-  
+  int count;
+
   /* note:  overallocation to make life easier... */
-  image = (byte *) malloc((size_t) (pinfo->h + 1) * pinfo->w + 16);
+  count = (pinfo->h + 1) * pinfo->w + 16; /* 4295032848 max == 65552 (wrap) */
+  if (pinfo->w <= 0 || pinfo->h <= 0 || count/pinfo->w < pinfo->h) {
+    pcxError(fname, "Bogus PCX file!!");
+    return (0);
+  }
+  image = (byte *) malloc((size_t) count);
   if (!image) FatalError("Can't alloc 'image' in pcxLoadImage8()");
-  
-  xvbzero((char *) image, (size_t) ((pinfo->h+1) * pinfo->w + 16));
-  
+
+  xvbzero((char *) image, (size_t) count);
+
   switch (hdr[PCX_BPP]) {
   case 1:   pcxLoadRaster(fp, image, 1, hdr, pinfo->w, pinfo->h);   break;
   case 8:   pcxLoadRaster(fp, image, 8, hdr, pinfo->w, pinfo->h);   break;
@@ -249,25 +255,33 @@
      byte *hdr;
 {
   byte *pix, *pic24, scale[256];
-  int   c, i, j, w, h, maxv, cnt, planes, bperlin, nbytes;
-  
+  int   c, i, j, w, h, maxv, cnt, planes, bperlin, nbytes, count;
+
   w = pinfo->w;  h = pinfo->h;
-  
-  planes = (int) hdr[PCX_PLANES];
-  bperlin = hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8);
-  
+
+  planes = (int) hdr[PCX_PLANES];  /* 255 max */
+  bperlin = hdr[PCX_BPRL] + ((int) hdr[PCX_BPRH]<<8);  /* 65535 max */
+
+  j = h*planes;          /* w and h are limited to 65536, planes to 3 */
+  count = w*j;           /* ...so this could wrap up to 3 times */
+  nbytes = bperlin*j;    /* ...and this almost 3 times */
+  if (w <= 0 || h <= 0 || planes <= 0 || bperlin <= 0 ||
+      j/h < planes || count/w < j || nbytes/bperlin < j) {
+    pcxError(fname, "Bogus PCX file!!");
+    return (0);
+  }
+
   /* allocate 24-bit image */
-  pic24 = (byte *) malloc((size_t) w*h*planes);
-  if (!pic24) FatalError("couldn't malloc 'pic24'");
-  
-  xvbzero((char *) pic24, (size_t) w*h*planes);
-  
+  pic24 = (byte *) malloc((size_t) count);
+  if (!pic24) FatalError("Can't malloc 'pic24' in pcxLoadImage24()");
+
+  xvbzero((char *) pic24, (size_t) count);
+
   maxv = 0;
   pix = pinfo->pic = pic24;
   i = 0;      /* planes, in this while loop */
   j = 0;      /* bytes per line, in this while loop */
-  nbytes = bperlin*h*planes;
- 
+
   while (nbytes > 0 && (c = getc(fp)) != EOF) {
     if ((c & 0xC0) == 0xC0) {   /* have a rep. count */
       cnt = c & 0x3F;

diff -ru xv-3.10a/xvpm.c xv-3.10a-bugfixes/xvpm.c
--- xv-3.10a/xvpm.c     1994-12-22 14:34:40.000000000 -0800
+++ xv-3.10a-bugfixes/xvpm.c    2005-03-20 22:16:52.000000000 -0800
@@ -60,7 +60,7 @@
 
   FILE  *fp;
   byte  *pic8;
-  int    isize,i,flipit,w,h;
+  int    isize,i,flipit,w,h,numbytes;
   char  *bname;
 
   bname = BaseName(fname);
@@ -114,20 +115,27 @@
     fprintf(stderr,"(ie, 1-plane PM_I, or 1-, 3-, or 4-plane PM_C)\n");
 
     return pmError(bname, "PM file in unsupported format");
-  }    
+  }
 
 
   isize = pm_isize(&thePic);
+  i = w*h;
+  numbytes = i*3;
+
+  /* make sure image is more-or-less valid (and no overflows) */
+  if (isize <= 0 || w <= 0 || h <= 0 || i/w < h || numbytes/i < 3 ||
+      thePic.pm_cmtsize < 0)
+    return pmError(bname, "Bogus PM file!!");
 
-  if (DEBUG) 
+  if (DEBUG)
     fprintf(stderr,"%s: LoadPM() - loading a %dx%d %s pic, %d planes\n",
-           cmd, w, h, (thePic.pm_form==PM_I) ? "PM_I" : "PM_C", 
+           cmd, w, h, (thePic.pm_form==PM_I) ? "PM_I" : "PM_C",
            thePic.pm_np);
 
-             
+
   /* allocate memory for picture and read it in */
   thePic.pm_image = (char *) malloc((size_t) isize);
-  if (thePic.pm_image == NULL) 
+  if (thePic.pm_image == NULL)
     return( pmError(bname, "unable to malloc PM picture") );
 
   if (fread(thePic.pm_image, (size_t) isize, (size_t) 1, fp) != 1)   {
Comment 1 Sune Kloppenborg Jeppesen (RETIRED) gentoo-dev 2005-03-27 13:22:43 UTC
Follow up comment by reporter on Vendor-Sec:

I think we can consider this vulnerability to be "effectively exploited"
in the sense that an exploit for an earlier version of the same problem
in XV's BMP decoder was posted to BugTraq last August
(http://www.securityfocus.com/archive/1/372345), and demonstration images
for the new variant are publicly available from the KDE Bugzilla site
(http://bugs.kde.org/show_bug.cgi?id=102328).  I'm pretty sure the former
can be trivially adapted to the latter, though I have not attempted to do
so myself.

Ergo, I still plan to release an updated set of XV jumbo patches tonight
or tomorrow morning (US/Pacific) and to make an announcement to BugTraq
within the next day or two.  I realize this is a holiday weekend for many,
and that makes things awkward, but unfortunately it doesn't alter anything
I said in the previous paragraph.

In the meantime, here are some updated test images:

    http://pobox.com/~newt/test/286572/overflow-examples.zip  (189695 bytes)
    http://pobox.com/~newt/test/286572/normal-examples.zip    (189638 bytes)

(I trust no one will post the new links on publicly visible bug pages
just yet! :-/ )  The archives contain the same 8-bit PCX image as in
the KDE bug attachment, plus 24-bit BMP, JPEG, PCX (slightly "improved"),
PNG, PPM, and TIFF versions.  All but the PNG trigger segfaults in XV:

    % foreach j ( overflow-[28]* )
    foreach? echo $j
    foreach? /usr/X11R6/bin/xv $j
    foreach? end
    overflow-24.bmp
    Segmentation fault
    overflow-24.jpg
    Segmentation fault
    overflow-24.pcx
    Segmentation fault
    overflow-24.png
    overflow-24.ppm
    Segmentation fault
    overflow-24.tif
    Segmentation fault
    overflow-8.pcx
    Segmentation fault

(The PNG decoder is saved by internal libpng checks that apparently go
all the way back to 1.0.8, maybe even earlier.  On the other hand, a
different but related libpng vulnerability was fixed just last August,
so don't assume a PNG crack is entirely out of the question.)

Note that I'm limiting my attention solely to XV, simply because it's
the image viewer I know and love^Wuse.  Hopefully most modern ones are
a bit more secure.
Comment 2 Sune Kloppenborg Jeppesen (RETIRED) gentoo-dev 2005-03-28 00:13:59 UTC
Another followup:

Unfortunately (or fortunately, depending on your perspective), I still
have another 200 memory-allocations to inspect and potentially fix in
XV, which means I'm not ready with my own patch and probably won't be
before next weekend sometime.  In particular, I won't be announcing
anything for at least that long; I'd like the fix to be completely
ready first.
Comment 3 Thierry Carrez (RETIRED) gentoo-dev 2005-04-11 09:15:01 UTC
Closed, public followup in bug 88742

*** This bug has been marked as a duplicate of 88742 ***