summary refs log tree commit diff
path: root/gnu/packages/patches/libtiff-CVE-2017-9935.patch
blob: 5685d81f6890d4c7dc07338f646507c3019eda4f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
Fix CVE-2017-9935

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9935
http://bugzilla.maptools.org/show_bug.cgi?id=2704

Patch copied from upstream source repository:

https://gitlab.com/libtiff/libtiff/commit/3dd8f6a357981a4090f126ab9025056c938b6940

From 3dd8f6a357981a4090f126ab9025056c938b6940 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.
---
 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 2ccaf448..cbf2b693 100644
--- a/libtiff/tif_dir.c
+++ b/libtiff/tif_dir.c
@@ -1065,6 +1065,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 d1a9b095..c3ec0746 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.16.1