Blame SOURCES/libtiff-CVE-2017-9935.patch

b03815
From e1cd2d7ab032e7fe80b4c13e07895194c8bac85e Mon Sep 17 00:00:00 2001
b03815
From: Brian May <brian@linuxpenguins.xyz>
b03815
Date: Thu, 7 Dec 2017 07:46:47 +1100
b03815
Subject: [PATCH 1/4] [PATCH] tiff2pdf: Fix CVE-2017-9935
b03815
b03815
Fix for http://bugzilla.maptools.org/show_bug.cgi?id=2704
b03815
b03815
This vulnerability - at least for the supplied test case - is because we
b03815
assume that a tiff will only have one transfer function that is the same
b03815
for all pages. This is not required by the TIFF standards.
b03815
b03815
We than read the transfer function for every page.  Depending on the
b03815
transfer function, we allocate either 2 or 4 bytes to the XREF buffer.
b03815
We allocate this memory after we read in the transfer function for the
b03815
page.
b03815
b03815
For the first exploit - POC1, this file has 3 pages. For the first page
b03815
we allocate 2 extra extra XREF entries. Then for the next page 2 more
b03815
entries. Then for the last page the transfer function changes and we
b03815
allocate 4 more entries.
b03815
b03815
When we read the file into memory, we assume we have 4 bytes extra for
b03815
each and every page (as per the last transfer function we read). Which
b03815
is not correct, we only have 2 bytes extra for the first 2 pages. As a
b03815
result, we end up writing past the end of the buffer.
b03815
b03815
There are also some related issues that this also fixes. For example,
b03815
TIFFGetField can return uninitalized pointer values, and the logic to
b03815
detect a N=3 vs N=1 transfer function seemed rather strange.
b03815
b03815
It is also strange that we declare the transfer functions to be of type
b03815
float, when the standard says they are unsigned 16 bit values. This is
b03815
fixed in another patch.
b03815
b03815
This patch will check to ensure that the N value for every transfer
b03815
function is the same for every page. If this changes, we abort with an
b03815
error. In theory, we should perhaps check that the transfer function
b03815
itself is identical for every page, however we don't do that due to the
b03815
confusion of the type of the data in the transfer function.
b03815
---
b03815
 libtiff/tif_dir.c |  3 +++
b03815
 tools/tiff2pdf.c  | 69 +++++++++++++++++++++++++++++++----------------
b03815
 2 files changed, 49 insertions(+), 23 deletions(-)
b03815
b03815
diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c
b03815
index f00f808..c36a5f3 100644
b03815
--- a/libtiff/tif_dir.c
b03815
+++ b/libtiff/tif_dir.c
b03815
@@ -1067,6 +1067,9 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
b03815
 			if (td->td_samplesperpixel - td->td_extrasamples > 1) {
b03815
 				*va_arg(ap, uint16**) = td->td_transferfunction[1];
b03815
 				*va_arg(ap, uint16**) = td->td_transferfunction[2];
b03815
+			} else {
b03815
+				*va_arg(ap, uint16**) = NULL;
b03815
+				*va_arg(ap, uint16**) = NULL;
b03815
 			}
b03815
 			break;
b03815
 		case TIFFTAG_REFERENCEBLACKWHITE:
b03815
diff --git a/tools/tiff2pdf.c b/tools/tiff2pdf.c
b03815
index bdb9126..bd23c9e 100644
b03815
--- a/tools/tiff2pdf.c
b03815
+++ b/tools/tiff2pdf.c
b03815
@@ -239,7 +239,7 @@ typedef struct {
b03815
 	float tiff_whitechromaticities[2];
b03815
 	float tiff_primarychromaticities[6];
b03815
 	float tiff_referenceblackwhite[2];
b03815
-	float* tiff_transferfunction[3];
b03815
+	uint16* tiff_transferfunction[3];
b03815
 	int pdf_image_interpolate;	/* 0 (default) : do not interpolate,
b03815
 					   1 : interpolate */
b03815
 	uint16 tiff_transferfunctioncount;
b03815
@@ -1049,6 +1049,8 @@ void t2p_read_tiff_init(T2P* t2p, TIFF* input){
b03815
 	uint16 pagen=0;
b03815
 	uint16 paged=0;
b03815
 	uint16 xuint16=0;
b03815
+	uint16 tiff_transferfunctioncount=0;
b03815
+	uint16* tiff_transferfunction[3];
b03815
 
b03815
 	directorycount=TIFFNumberOfDirectories(input);
b03815
 	if(directorycount > TIFF_DIR_MAX) {
b03815
@@ -1157,26 +1159,48 @@ void t2p_read_tiff_init(T2P* t2p, TIFF* input){
b03815
                 }
b03815
 #endif
b03815
 		if (TIFFGetField(input, TIFFTAG_TRANSFERFUNCTION,
b03815
-                                 &(t2p->tiff_transferfunction[0]),
b03815
-                                 &(t2p->tiff_transferfunction[1]),
b03815
-                                 &(t2p->tiff_transferfunction[2]))) {
b03815
-			if((t2p->tiff_transferfunction[1] != (float*) NULL) &&
b03815
-                           (t2p->tiff_transferfunction[2] != (float*) NULL) &&
b03815
-                           (t2p->tiff_transferfunction[1] !=
b03815
-                            t2p->tiff_transferfunction[0])) {
b03815
-				t2p->tiff_transferfunctioncount = 3;
b03815
-				t2p->tiff_pages[i].page_extra += 4;
b03815
-				t2p->pdf_xrefcount += 4;
b03815
-			} else {
b03815
-				t2p->tiff_transferfunctioncount = 1;
b03815
-				t2p->tiff_pages[i].page_extra += 2;
b03815
-				t2p->pdf_xrefcount += 2;
b03815
-			}
b03815
-			if(t2p->pdf_minorversion < 2)
b03815
-				t2p->pdf_minorversion = 2;
b03815
+                                 &(tiff_transferfunction[0]),
b03815
+                                 &(tiff_transferfunction[1]),
b03815
+                                 &(tiff_transferfunction[2]))) {
b03815
+
b03815
+                        if((tiff_transferfunction[1] != (uint16*) NULL) &&
b03815
+                           (tiff_transferfunction[2] != (uint16*) NULL)
b03815
+                          ) {
b03815
+                            tiff_transferfunctioncount=3;
b03815
+                        } else {
b03815
+                            tiff_transferfunctioncount=1;
b03815
+                        }
b03815
                 } else {
b03815
-			t2p->tiff_transferfunctioncount=0;
b03815
+			tiff_transferfunctioncount=0;
b03815
 		}
b03815
+
b03815
+                if (i > 0){
b03815
+                    if (tiff_transferfunctioncount != t2p->tiff_transferfunctioncount){
b03815
+                        TIFFError(
b03815
+                            TIFF2PDF_MODULE,
b03815
+                            "Different transfer function on page %d",
b03815
+                            i);
b03815
+                        t2p->t2p_error = T2P_ERR_ERROR;
b03815
+                        return;
b03815
+                    }
b03815
+                }
b03815
+
b03815
+                t2p->tiff_transferfunctioncount = tiff_transferfunctioncount;
b03815
+                t2p->tiff_transferfunction[0] = tiff_transferfunction[0];
b03815
+                t2p->tiff_transferfunction[1] = tiff_transferfunction[1];
b03815
+                t2p->tiff_transferfunction[2] = tiff_transferfunction[2];
b03815
+                if(tiff_transferfunctioncount == 3){
b03815
+                        t2p->tiff_pages[i].page_extra += 4;
b03815
+                        t2p->pdf_xrefcount += 4;
b03815
+                        if(t2p->pdf_minorversion < 2)
b03815
+                                t2p->pdf_minorversion = 2;
b03815
+                } else if (tiff_transferfunctioncount == 1){
b03815
+                        t2p->tiff_pages[i].page_extra += 2;
b03815
+                        t2p->pdf_xrefcount += 2;
b03815
+                        if(t2p->pdf_minorversion < 2)
b03815
+                                t2p->pdf_minorversion = 2;
b03815
+                }
b03815
+
b03815
 		if( TIFFGetField(
b03815
 			input, 
b03815
 			TIFFTAG_ICCPROFILE, 
b03815
@@ -1837,10 +1861,9 @@ void t2p_read_tiff_data(T2P* t2p, TIFF* input){
b03815
 			 &(t2p->tiff_transferfunction[0]),
b03815
 			 &(t2p->tiff_transferfunction[1]),
b03815
 			 &(t2p->tiff_transferfunction[2]))) {
b03815
-		if((t2p->tiff_transferfunction[1] != (float*) NULL) &&
b03815
-                   (t2p->tiff_transferfunction[2] != (float*) NULL) &&
b03815
-                   (t2p->tiff_transferfunction[1] !=
b03815
-                    t2p->tiff_transferfunction[0])) {
b03815
+		if((t2p->tiff_transferfunction[1] != (uint16*) NULL) &&
b03815
+                   (t2p->tiff_transferfunction[2] != (uint16*) NULL)
b03815
+                  ) {
b03815
 			t2p->tiff_transferfunctioncount=3;
b03815
 		} else {
b03815
 			t2p->tiff_transferfunctioncount=1;
b03815
-- 
b03815
2.17.0
b03815