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

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