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