[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: possible regressing in tiff4/libtiff3 update (deb7u1)



On Thu, 26 Jan 2017, Raphael Hertzog wrote:
> This code thus assumes that the list ok known tags only contains a single
> tag per unique fip->field_bit and this is no no longer the case with
> the patches we added:
> - CVE-2014-8128-5-fixed.patch
> - CVE-2016-5318_CVE-2015-7554.patch
> 
> I guess we have no other choice than to drop all CODEC-specific tags
> from the global list of tags... and thus reopen the above CVE, at
> least in part.

In fact, I opted to add logic that filters out the non-relevant tags.

Matthias, can you try
https://people.debian.org/~hertzog/packages/libtiff4_3.9.6-11+deb7u3_amd64.deb
and report back if it works for you ? Please check that there are no other
regressions as well.

The full upload is available:
$ dget https://people.debian.org/~hertzog/packages/tiff3_3.9.6-11+deb7u3_amd64.changes

The debdiff is attached for review by other contributors.

If we are satisfied by this fix, then we should do something similar on
source package tiff 4.x (which provides libtiff5 4.x).

Cheers,
-- 
Raphaël Hertzog ◈ Debian Developer

Support Debian LTS: https://www.freexian.com/services/debian-lts.html
Learn to master Debian: https://debian-handbook.info/get/
diff -Nru tiff3-3.9.6/debian/changelog tiff3-3.9.6/debian/changelog
--- tiff3-3.9.6/debian/changelog	2016-11-02 12:27:15.000000000 +0100
+++ tiff3-3.9.6/debian/changelog	2017-01-26 14:27:21.000000000 +0100
@@ -1,3 +1,12 @@
+tiff3 (3.9.6-11+deb7u3) wheezy-security; urgency=low
+
+  * When writing out a TIFF file, skip codec-specific tags that are not
+    relevant for the current codec (compression scheme). Closes: #852610
+    This fixes a regression introduced by CVE-2014-8128-5-fixed.patch and
+    CVE-2016-5318_CVE-2015-7554.patch.
+
+ -- Raphaël Hertzog <hertzog@debian.org>  Thu, 26 Jan 2017 13:27:21 +0000
+
 tiff3 (3.9.6-11+deb7u2) wheezy-security; urgency=high
 
   * Non-maintainer upload by the LTS Team.
diff -Nru tiff3-3.9.6/debian/patches/handle-codec-specific-tags.patch tiff3-3.9.6/debian/patches/handle-codec-specific-tags.patch
--- tiff3-3.9.6/debian/patches/handle-codec-specific-tags.patch	1970-01-01 01:00:00.000000000 +0100
+++ tiff3-3.9.6/debian/patches/handle-codec-specific-tags.patch	2017-01-26 14:27:21.000000000 +0100
@@ -0,0 +1,256 @@
+Description: Fix regression introduced with former updates
+ The codec specific fields share the same "field_bit" value
+ (FIELD_CODEC+x). When a TIFF file is written, the list of tags
+ is browsed looking for matching "field_bit" assuming that only
+ the tags of the current codec are loaded. This is no longer the
+ case, since we have added all tags to the main table in a former
+ security update. The net result is that the wrong tag number is
+ used because the first match is usually not the correct one.
+ .
+ So we add supplementary code to skip tags that are not relevant
+ for the current compression scheme (codec).
+ .
+ We also harmonize "field_bit" values of tags that are shared across
+ multiple codecs otherwise we might end up using the same field_bit
+ for multiple tags and we thus miss tags. This concerns only
+ TIFFTAG_FAXRECVPARAMS TIFFTAG_FAXSUBADDRESS TIFFTAG_FAXRECVTIME and
+ TIFFTAG_FAXDCS.
+Author: Raphaël Hertzog <hertzog@debian.org>
+Origin: vendor
+Bug: http://bugzilla.maptools.org/show_bug.cgi?id=2580
+Bug-Debian: http://bugs.debian.org/852610
+Last-Update: 2017-01-27
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/libtiff/tif_dirinfo.c
++++ b/libtiff/tif_dirinfo.c
+@@ -230,14 +230,20 @@ tiffFieldInfo[] = {
+     /* MISSING: TIFFTAG_OPIPROXY */
+     { TIFFTAG_JPEGPROC,          1, 1,  TIFF_SHORT,     FIELD_CODEC+5,
+       0,        0,      "JpegProc" },
+-    /* MISSING: TIFFTAG_JPEGIFOFFSET and TIFFTAG_JPEGIFBYTECOUNT,
+-     * no TIFF_LONG8 supported in this version */
++    { TIFFTAG_JPEGIFOFFSET,      1, 1,  TIFF_LONG,      FIELD_CODEC+0,
++      1,        0,      "JpegInterchangeFormat" },
++    { TIFFTAG_JPEGIFBYTECOUNT,   1, 1,  TIFF_LONG,      FIELD_CODEC+1,
++      1,        0,      "JpegInterchangeFormatLength" },
+     { TIFFTAG_JPEGRESTARTINTERVAL,1,1,  TIFF_SHORT,     FIELD_CODEC+6,
+       0,        0,      "JpegRestartInterval" },
+     /* MISSING: TIFFTAG_JPEGLOSSLESSPREDICTORS */
+     /* MISSING: TIFFTAG_JPEGPOINTTRANSFORM */
+-    /* MISSING: TIFFTAG_JPEGQTABLES, TIFFTAG_JPEGDCTABLES,
+-     * TIFFTAG_JPEGACTABLES, no TIFF_LONG8 supported in this version */
++    { TIFFTAG_JPEGQTABLES,      -1,-1,  TIFF_LONG,      FIELD_CODEC+2,
++      0,        1,      "JpegQTables" },
++    { TIFFTAG_JPEGDCTABLES,     -1,-1,  TIFF_LONG,      FIELD_CODEC+3,
++      0,        1,      "JpegDcTables" },
++    { TIFFTAG_JPEGACTABLES,     -1,-1,  TIFF_LONG,      FIELD_CODEC+4,
++      0,        1,      "JpegAcTables" },
+     { TIFFTAG_YCBCRCOEFFICIENTS, 3, 3,	TIFF_RATIONAL,	FIELD_CUSTOM,
+       0,	0,	"YCbCrCoefficients" },
+     { TIFFTAG_YCBCRSUBSAMPLING,	 2, 2,	TIFF_SHORT,	FIELD_YCBCRSUBSAMPLING,
+@@ -304,13 +310,13 @@ tiffFieldInfo[] = {
+     /* MISSING: TIFFTAG_JBIGOPTIONS */
+     { TIFFTAG_GPSIFD,		1, 1,	TIFF_LONG,	FIELD_CUSTOM,
+       0,	0,	"GPSIFDOffset" },
+-    { TIFFTAG_FAXRECVPARAMS,    1, 1,   TIFF_LONG,      FIELD_CUSTOM,
++    { TIFFTAG_FAXRECVPARAMS,    1, 1,   TIFF_LONG,      FIELD_CODEC+3,
+       1,        0,      "FaxRecvParams" },
+-    { TIFFTAG_FAXSUBADDRESS,   -1,-1,   TIFF_ASCII,     FIELD_CUSTOM,
++    { TIFFTAG_FAXSUBADDRESS,   -1,-1,   TIFF_ASCII,     FIELD_CODEC+4,
+       1,        0,      "FaxSubAddress" },
+-    { TIFFTAG_FAXRECVTIME,      1, 1,   TIFF_LONG,      FIELD_CUSTOM,
++    { TIFFTAG_FAXRECVTIME,      1, 1,   TIFF_LONG,      FIELD_CODEC+5,
+       1,        0,      "FaxRecvTime" },
+-    { TIFFTAG_FAXDCS,          -1,-1,   TIFF_ASCII,     FIELD_CUSTOM,
++    { TIFFTAG_FAXDCS,          -1,-1,   TIFF_ASCII,     FIELD_CODEC+6,
+       1,        0,      "FaxDcs" },
+     { TIFFTAG_STONITS,		 1, 1,	TIFF_DOUBLE,	FIELD_CUSTOM,
+       0,	0,	"StoNits" },
+@@ -922,6 +928,125 @@ _TIFFCreateAnonFieldInfo(TIFF *tif, ttag
+ 	return fld;    
+ }
+ 
++const int
++_TIFFCheckFieldIsValidForCodec(TIFF *tif, ttag_t tag)
++{
++	/* Filter out non-codec specific tags */
++	switch (tag) {
++	    /* Shared tags */
++	    case TIFFTAG_PREDICTOR:
++	    case TIFFTAG_FAXRECVPARAMS:
++	    case TIFFTAG_FAXSUBADDRESS:
++	    case TIFFTAG_FAXRECVTIME:
++	    case TIFFTAG_FAXDCS:
++	    /* JPEG tags */
++	    case TIFFTAG_JPEGTABLES:
++	    /* OJPEG tags */
++	    case TIFFTAG_JPEGIFOFFSET:
++	    case TIFFTAG_JPEGIFBYTECOUNT:
++	    case TIFFTAG_JPEGQTABLES:
++	    case TIFFTAG_JPEGDCTABLES:
++	    case TIFFTAG_JPEGACTABLES:
++	    case TIFFTAG_JPEGPROC:
++	    case TIFFTAG_JPEGRESTARTINTERVAL:
++	    /* CCITT* */
++	    case TIFFTAG_BADFAXLINES:
++	    case TIFFTAG_CLEANFAXDATA:
++	    case TIFFTAG_CONSECUTIVEBADFAXLINES:
++	    case TIFFTAG_GROUP3OPTIONS:
++	    case TIFFTAG_GROUP4OPTIONS:
++	    /* JBIG shares 4 tags with CCITT* */
++		break;
++	    default:
++		return 1;
++	}
++	/* Check if codec specific tags are allowed for the current
++	 * compression scheme (codec) */
++	switch (tif->tif_dir.td_compression) {
++	    case COMPRESSION_LZW:
++		if (tag == TIFFTAG_PREDICTOR)
++		    return 1;
++		break;
++	    case COMPRESSION_PACKBITS:
++		/* No codec-specific tags */
++		break;
++	    case COMPRESSION_THUNDERSCAN:
++		/* No codec-specific tags */
++		break;
++	    case COMPRESSION_NEXT:
++		/* No codec-specific tags */
++		break;
++	    case COMPRESSION_JPEG:
++		switch (tag) {
++		    case TIFFTAG_JPEGTABLES:
++		    case TIFFTAG_FAXRECVPARAMS:
++		    case TIFFTAG_FAXSUBADDRESS:
++		    case TIFFTAG_FAXRECVTIME:
++		    case TIFFTAG_FAXDCS:
++			return 1;
++		}
++		break;
++	    case COMPRESSION_OJPEG:
++		switch (tag) {
++		    case TIFFTAG_JPEGIFOFFSET:
++		    case TIFFTAG_JPEGIFBYTECOUNT:
++		    case TIFFTAG_JPEGQTABLES:
++		    case TIFFTAG_JPEGDCTABLES:
++		    case TIFFTAG_JPEGACTABLES:
++		    case TIFFTAG_JPEGPROC:
++		    case TIFFTAG_JPEGRESTARTINTERVAL:
++			return 1;
++		}
++		break;
++	    case COMPRESSION_CCITTRLE:
++	    case COMPRESSION_CCITTRLEW:
++	    case COMPRESSION_CCITTFAX3:
++	    case COMPRESSION_CCITTFAX4:
++		switch (tag) {
++		    case TIFFTAG_BADFAXLINES:
++		    case TIFFTAG_CLEANFAXDATA:
++		    case TIFFTAG_CONSECUTIVEBADFAXLINES:
++		    case TIFFTAG_FAXRECVPARAMS:
++		    case TIFFTAG_FAXSUBADDRESS:
++		    case TIFFTAG_FAXRECVTIME:
++		    case TIFFTAG_FAXDCS:
++			return 1;
++		    case TIFFTAG_GROUP3OPTIONS:
++			if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX3)
++			    return 1;
++			break;
++		    case TIFFTAG_GROUP4OPTIONS:
++			if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4)
++			    return 1;
++			break;
++		}
++		break;
++	    case COMPRESSION_JBIG:
++		switch (tag) {
++		    case TIFFTAG_FAXRECVPARAMS:
++		    case TIFFTAG_FAXSUBADDRESS:
++		    case TIFFTAG_FAXRECVTIME:
++		    case TIFFTAG_FAXDCS:
++			return 1;
++		}
++		break;
++	    case COMPRESSION_DEFLATE:
++	    case COMPRESSION_ADOBE_DEFLATE:
++		if (tag == TIFFTAG_PREDICTOR)
++		    return 1;
++		break;
++	   case COMPRESSION_PIXARLOG:
++		if (tag == TIFFTAG_PREDICTOR)
++		    return 1;
++		break;
++	    case COMPRESSION_SGILOG:
++	    case COMPRESSION_SGILOG24:
++		/* No codec-specific tags */
++		break;
++	}
++	return 0;
++}
++
+ /* vim: set ts=8 sts=8 sw=8 noet: */
+ /*
+  * Local Variables:
+--- a/libtiff/tif_dir.h
++++ b/libtiff/tif_dir.h
+@@ -190,6 +190,7 @@ extern  const TIFFFieldInfo* _TIFFFindOr
+ 							   TIFFDataType dt );
+ extern  TIFFFieldInfo* _TIFFCreateAnonFieldInfo( TIFF *tif, ttag_t tag,
+                                                  TIFFDataType dt );
++extern const int _TIFFCheckFieldIsValidForCodec(TIFF *tif, ttag_t tag);
+ 
+ #define _TIFFFindFieldInfo	    TIFFFindFieldInfo
+ #define _TIFFFindFieldInfoByName    TIFFFindFieldInfoByName
+--- a/libtiff/tif_dirwrite.c
++++ b/libtiff/tif_dirwrite.c
+@@ -194,9 +194,12 @@ _TIFFWriteDirectory(TIFF* tif, int done)
+ 
+ 			if( !is_set )
+ 				continue;
++		} else {
++			if (!FieldSet(fields, fip->field_bit))
++				continue;
++			if (!_TIFFCheckFieldIsValidForCodec(tif, fip->field_tag))
++				continue;
+ 		}
+-		else if (!FieldSet(fields, fip->field_bit))
+-			continue;
+ 
+ 		/*
+ 		 * Handle other fields.
+--- a/libtiff/tif_jbig.c
++++ b/libtiff/tif_jbig.c
+@@ -50,10 +50,10 @@ typedef struct
+ 
+ #define GetJBIGState(tif) ((JBIGState*)(tif)->tif_data)
+ 
+-#define FIELD_RECVPARAMS        (FIELD_CODEC+0)
+-#define FIELD_SUBADDRESS        (FIELD_CODEC+1)
+-#define FIELD_RECVTIME          (FIELD_CODEC+2)
+-#define FIELD_FAXDCS            (FIELD_CODEC+3)
++#define FIELD_RECVPARAMS        (FIELD_CODEC+3)
++#define FIELD_SUBADDRESS        (FIELD_CODEC+4)
++#define FIELD_RECVTIME          (FIELD_CODEC+5)
++#define FIELD_FAXDCS            (FIELD_CODEC+6)
+ 
+ static const TIFFFieldInfo jbigFieldInfo[] = 
+ {
+--- a/libtiff/tif_jpeg.c
++++ b/libtiff/tif_jpeg.c
+@@ -179,10 +179,10 @@ static  int JPEGInitializeLibJPEG( TIFF
+ 								   int force_encode, int force_decode );
+ 
+ #define	FIELD_JPEGTABLES	(FIELD_CODEC+0)
+-#define	FIELD_RECVPARAMS	(FIELD_CODEC+1)
+-#define	FIELD_SUBADDRESS	(FIELD_CODEC+2)
+-#define	FIELD_RECVTIME		(FIELD_CODEC+3)
+-#define	FIELD_FAXDCS		(FIELD_CODEC+4)
++#define	FIELD_RECVPARAMS	(FIELD_CODEC+3)
++#define	FIELD_SUBADDRESS	(FIELD_CODEC+4)
++#define	FIELD_RECVTIME		(FIELD_CODEC+5)
++#define	FIELD_FAXDCS		(FIELD_CODEC+6)
+ 
+ static const TIFFFieldInfo jpegFieldInfo[] = {
+     { TIFFTAG_JPEGTABLES,	 -3,-3,	TIFF_UNDEFINED,	FIELD_JPEGTABLES,
diff -Nru tiff3-3.9.6/debian/patches/series tiff3-3.9.6/debian/patches/series
--- tiff3-3.9.6/debian/patches/series	2016-10-28 15:02:15.000000000 +0200
+++ tiff3-3.9.6/debian/patches/series	2017-01-26 14:27:21.000000000 +0100
@@ -26,3 +26,4 @@
 CVE-2013-1961.patch
 CVE-2010-2596.patch
 CVE-2016-5318_CVE-2015-7554.patch
+handle-codec-specific-tags.patch

Reply to: