Version in base suite: 0.98-1 Version in overlay suite: 0.98-1.1+0sarge1 Base version: exiftags_0.98-1 Target version: exiftags_0.98-1.1+0sarge1 Base file: /org/ftp.debian.org/ftp/pool/main/e/exiftags/exiftags_0.98-1.dsc Target file: /org/ftp.debian.org/ftp/pool/main/e/exiftags/exiftags_0.98-1.1+0sarge1.dsc diff -u exiftags-0.98/debian/changelog exiftags-0.98/debian/changelog --- exiftags-0.98/debian/changelog +++ exiftags-0.98/debian/changelog @@ -1,3 +1,14 @@ +exiftags (0.98-1.1+0sarge1) oldstable-security; urgency=high + + * Non-maintainer upload by the Security Team. + * Backport upstream fixes from v1.01: + - CVE-2007-6354, CVE-2007-6355: integer overflow and memory access + errors through inadequate EXIF data validation + - CVE-2007-6356: recursive IFD references in EXIF data would cause + a denial of service via infinite loop + + -- Devin Carraway Mon, 24 Mar 2008 00:58:02 -0700 + exiftags (0.98-1) unstable; urgency=low * New upstream release diff -u exiftags-0.98/debian/rules exiftags-0.98/debian/rules --- exiftags-0.98/debian/rules +++ exiftags-0.98/debian/rules @@ -29,6 +29,12 @@ build-stamp: configure-stamp dh_testdir + for p in `ls debian/patches/*.patch` ; do \ + if [ ! -e "$$p.applied" ] ; then \ + echo applying $$p ; \ + patch -p1 < $$p && touch $$p.applied ; \ + fi \ + done # Add here commands to compile the package. $(MAKE) @@ -44,6 +50,13 @@ # Add here commands to clean up after the build process. -$(MAKE) clean + for p in `ls -r debian/patches/*.patch` ; do \ + if [ -e "$$p.applied" ] ; then \ + echo reverse-applying $$p ; \ + patch -R -p1 < $$p && rm -f $$p.applied ; \ + fi \ + done + dh_clean install: build only in patch2: unchanged: --- exiftags-0.98.orig/debian/patches/CVE-2007-6354_CVE-2007-6355_CVE-2007-6356.patch +++ exiftags-0.98/debian/patches/CVE-2007-6354_CVE-2007-6355_CVE-2007-6356.patch @@ -0,0 +1,339 @@ +diff -aruN exiftags-0.98.orig/exif.c exiftags-0.98.fix/exif.c +--- exiftags-0.98.orig/exif.c 2003-08-15 20:34:21.000000000 -0700 ++++ exiftags-0.98.fix/exif.c 2008-03-24 00:40:28.000000000 -0700 +@@ -144,8 +144,13 @@ + /* Check the field count. */ + + if (prop->tagset[i].count && prop->tagset[i].count != +- prop->count) ++ prop->count) { + exifwarn2("field count mismatch", prop->name); ++ ++ /* Let's be forgiving with ASCII fields. */ ++ if (prop->type != TIFF_ASCII) ++ prop->lvl = ED_BAD; ++ } + } + + /* Debuggage. */ +@@ -216,6 +221,11 @@ + enum byteorder o = t->md.order; + struct exifprop *h = t->props; + ++ /* Skip bad properties. */ ++ ++ if (prop->lvl == ED_BAD) ++ return; ++ + /* + * Process tags from special IFDs. + * XXX Don't properly pass IFD byte order here. +@@ -426,6 +436,11 @@ + unsigned char *btiff = dir->md.btiff; + enum byteorder o = dir->md.order; + ++ /* If the tag's already marked as bad, no sense in continuing. */ ++ ++ if (prop->lvl == ED_BAD) ++ return; ++ + /* Set description if we have a lookup table. */ + + for (i = 0; prop->tagset[i].tag < EXIF_T_UNKNOWN && +@@ -523,9 +538,11 @@ + * the manufacturer tag first to figure out makerifd(). + */ + +- if (makers[t->mkrval].ifdfun) +- dir->next = makers[t->mkrval].ifdfun(prop->value, md); +- else ++ if (makers[t->mkrval].ifdfun) { ++ if (!offsanity(prop, 1, dir)) ++ dir->next = ++ makers[t->mkrval].ifdfun(prop->value, md); ++ } else + exifwarn("maker note not supported"); + + if (!dir->next) +@@ -538,6 +555,11 @@ + /* Lookup functions for maker note. */ + + case EXIF_T_EQUIPMAKE: ++ ++ /* Sanity check the offset. */ ++ if (offsanity(prop, 1, dir)) ++ return; ++ + strncpy(buf, (const char *)(btiff + prop->value), sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for (c = buf; *c; c++) *c = tolower(*c); +@@ -571,8 +593,14 @@ + /* FALLTHROUGH */ + + case EXIF_T_USERCOMMENT: +- if (prop->count < 8) +- break; ++ if (prop->count < 8) { ++ exifwarn("invalid user comment length"); ++ prop->lvl = ED_BAD; ++ return; ++ } ++ ++ if (offsanity(prop, 1, dir)) ++ return; + + /* Ignore the 'comments' WinXP creates when rotating. */ + #ifdef WINXP_BUGS +@@ -623,12 +651,21 @@ + * (InteroperabilityOffset has an odd ASCII value.) + */ + +- if (prop->type == TIFF_ASCII && +- (prop->value + prop->count <= +- (u_int32_t)(dir->md.etiff - btiff))) { +- exifstralloc(&prop->str, prop->count + 1); +- strncpy(prop->str, (const char *)(btiff + prop->value), +- prop->count); ++ if (prop->type == TIFF_ASCII) { ++ /* Should fit in the value field. */ ++ if (prop->count < 5) { ++ exifstralloc(&prop->str, 5); ++ byte4exif(prop->value, (unsigned char *)prop->str, o); ++ return; ++ } ++ ++ /* Sanity check the offset. */ ++ if (!offsanity(prop, 1, dir)) { ++ exifstralloc(&prop->str, prop->count + 1); ++ strncpy(prop->str, (const char *)(btiff + prop->value), ++ prop->count); ++ return; ++ } + return; + } + +@@ -638,8 +675,7 @@ + */ + + if ((prop->type == TIFF_RTNL || prop->type == TIFF_SRTNL) && +- (prop->value + prop->count * 8 <= +- (u_int32_t)(dir->md.etiff - btiff))) { ++ !offsanity(prop, 8, dir)) { + + exifstralloc(&prop->str, 32); + +@@ -665,8 +701,7 @@ + */ + + if ((prop->type == TIFF_SHORT || prop->type == TIFF_SSHORT) && +- prop->count > 1 && (prop->value + prop->count * 2 <= +- (u_int32_t)(dir->md.etiff - btiff))) { ++ prop->count > 2 && !offsanity(prop, 2, dir)) { + + if (prop->count > 8) + return; +@@ -699,6 +734,7 @@ + exiffree(struct exiftags *t) + { + struct exifprop *tmpprop; ++ struct ifdoff *tmpoff; + + if (!t) return; + +@@ -707,6 +743,10 @@ + t->props = t->props->next; + free(tmpprop); + } ++ while ((tmpoff = (struct ifdoff *)(t->md.ifdoffs))) { ++ t->md.ifdoffs = (void *)tmpoff->next; ++ free(tmpoff); ++ } + free(t); + } + +diff -aruN exiftags-0.98.orig/exif.h exiftags-0.98.fix/exif.h +--- exiftags-0.98.orig/exif.h 2003-08-05 19:26:42.000000000 -0700 ++++ exiftags-0.98.fix/exif.h 2008-03-24 01:18:32.000000000 -0700 +@@ -216,6 +216,7 @@ + enum byteorder order; /* Endianness of IFD. */ + unsigned char *btiff; /* Beginning of TIFF (offset base). */ + unsigned char *etiff; /* End of TIFF. */ ++ void *ifdoffs; /* List of IFD offsets (internal only). */ + }; + + +diff -aruN exiftags-0.98.orig/exifutil.c exiftags-0.98.fix/exifutil.c +--- exiftags-0.98.orig/exifutil.c 2003-08-08 15:31:32.000000000 -0700 ++++ exiftags-0.98.fix/exifutil.c 2008-03-23 15:54:45.000000000 -0700 +@@ -79,6 +79,59 @@ + fprintf(stderr, "%s: %s (%s)\n", progname, msg1, msg2); + } + ++ /* ++ * Sanity check a tag's count & value when used as an offset within ++ * the TIFF. Checks for overflows. Returns 0 if OK; !0 if not OK. ++ */ ++int ++offsanity(struct exifprop *prop, u_int16_t size, struct ifd *dir) ++{ ++ u_int32_t tifflen; ++ const char *name; ++ ++ /* XXX Hrm. Should be OK with 64-bit addresses. */ ++ tifflen = dir->md.etiff - dir->md.btiff; ++ if (prop->name) ++ name = prop->name; ++ else ++ name = "Unknown"; ++ ++ if (!prop->count) { ++ if (prop->value > tifflen) { ++ exifwarn2("invalid field offset", name); ++ prop->lvl = ED_BAD; ++ return (1); ++ } ++ return (0); ++ } ++ ++ /* Does count * size overflow? */ ++ ++ if (size > (u_int32_t)(-1) / prop->count) { ++ exifwarn2("invalid field count", name); ++ prop->lvl = ED_BAD; ++ return (1); ++ } ++ ++ /* Does count * size + value overflow? */ ++ ++ if ((u_int32_t)(-1) - prop->value < prop->count * size) { ++ exifwarn2("invalid field offset", name); ++ prop->lvl = ED_BAD; ++ return (1); ++ } ++ ++ /* Is the offset valid? */ ++ ++ if (prop->value + prop->count * size > tifflen) { ++ exifwarn2("invalid field offset", name); ++ prop->lvl = ED_BAD; ++ return (1); ++ } ++ ++ return (0); ++} ++ + + /* + * Read an unsigned 2-byte int from the buffer. +@@ -177,8 +230,8 @@ + findprop(struct exifprop *prop, struct exiftag *tagset, u_int16_t tag) + { + +- for (; prop && (prop->tagset != tagset || prop->tag != tag); +- prop = prop->next); ++ for (; prop && (prop->tagset != tagset || prop->tag != tag || ++ prop->lvl == ED_BAD); prop = prop->next); + return (prop); + } + +@@ -298,10 +351,45 @@ + readifd(u_int32_t offset, struct ifd **dir, struct exiftag *tagset, + struct tiffmeta *md) + { +- u_int32_t ifdsize; ++ u_int32_t ifdsize, tifflen; + unsigned char *b; ++ struct ifdoff *ifdoffs, *lastoff; + ++ tifflen = md->etiff - md->btiff; + b = md->btiff; ++ ifdoffs = (struct ifdoff *)(md->ifdoffs); ++ lastoff = NULL; ++ *dir = NULL; ++ ++ /* ++ * Check to see if we've already visited this offset. Otherwise ++ * we could loop. (Need to add in TIFF start for Nikon makernotes.) ++ */ ++ ++ while (ifdoffs && ifdoffs->offset != b + offset) { ++ lastoff = ifdoffs; ++ ifdoffs = ifdoffs->next; ++ } ++ if (ifdoffs) { ++ /* We'll only complain if debugging. */ ++ if (debug) exifwarn("loop in IFD reference"); ++ return (0); ++ } ++ ++ ifdoffs = (struct ifdoff *)malloc(sizeof(struct ifdoff)); ++ if (!ifdoffs) { ++ exifwarn2("can't allocate IFD offset record", ++ (const char *)strerror(errno)); ++ return (0); ++ } ++ ifdoffs->offset = offset + b; ++ ifdoffs->next = NULL; ++ ++ /* The 0th (first) IFD establishes our list on the master tiffmeta. */ ++ if (lastoff) ++ lastoff->next = ifdoffs; ++ else ++ md->ifdoffs = (void *)ifdoffs; + + /* + * Verify that we have a valid offset. Some maker note IFDs prepend +@@ -309,10 +397,8 @@ + * (Number of directory entries is in the first 2 bytes.) + */ + +- if (b + offset + 2 > md->etiff) { +- *dir = NULL; ++ if ((u_int32_t)(-1) - offset < 2 || offset + 2 > tifflen) + return (0); +- } + + *dir = (struct ifd *)malloc(sizeof(struct ifd)); + if (!*dir) +@@ -324,12 +410,22 @@ + (*dir)->md = *md; + (*dir)->next = NULL; + ++ /* Make sure ifdsize doesn't overflow. */ ++ ++ if ((*dir)->num && ++ sizeof(struct field) > (u_int32_t)(-1) / (*dir)->num) { ++ free(*dir); ++ *dir = NULL; ++ return (0); ++ } ++ + ifdsize = (*dir)->num * sizeof(struct field); + b += offset + 2; + +- /* Sanity check our sizes. */ ++ /* Sanity check our size (and check for overflows). */ + +- if (b + ifdsize > md->etiff) { ++ if ((u_int32_t)(-1) - (offset + 2) < ifdsize || ++ offset + 2 + ifdsize > tifflen) { + free(*dir); + *dir = NULL; + return (0); +diff -aruN exiftags-0.98.orig/exifint.h exiftags-0.98.fix/exifint.h +--- exiftags-0.98.orig/exifint.h 2003-08-05 19:26:42.000000000 -0700 ++++ exiftags-0.98.fix/exifint.h 2008-03-24 01:24:21.000000000 -0700 +@@ -87,6 +87,13 @@ + struct ifd *next; + }; + ++/* List of IFD offsets, to detect loops. */ ++ ++struct ifdoff { ++ unsigned char *offset; /* Offset to IFD. */ ++ struct ifdoff *next; /* Next IFD in list. */ ++}; ++ + + /* Macro for making sense of a fraction. */ +