summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKhem Raj <raj.khem@gmail.com>2019-07-20 11:26:45 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2019-07-23 22:26:28 +0100
commitc46f497dbbf4c73259127e596983b0235498eb41 (patch)
tree0f2abc55a85eb5a3f6c85b528d852c1768359ce6
parent0bebaa64c62e5cb1d4bbe561cfbbfc18e0edfdbc (diff)
downloadpoky-c46f497dbbf4c73259127e596983b0235498eb41.tar.gz
Revert "unzip: fix CVE-2019-13232"
See [1] This reverts commit 4df4de2ac8bc0e80446e1ad0ce67eb244e2d2a32. [1] http://lists.openembedded.org/pipermail/openembedded-core/2019-July/284859.html (From OE-Core rev: 14655b3a54d086cbbd702adf9446fabf57ce51b0) Signed-off-by: Khem Raj <raj.khem@gmail.com> Cc: Anuj Mittal <anuj.mittal@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/recipes-extended/unzip/unzip/CVE-2019-13232.patch339
-rw-r--r--meta/recipes-extended/unzip/unzip_6.0.bb1
2 files changed, 0 insertions, 340 deletions
diff --git a/meta/recipes-extended/unzip/unzip/CVE-2019-13232.patch b/meta/recipes-extended/unzip/unzip/CVE-2019-13232.patch
deleted file mode 100644
index c808f3d36a..0000000000
--- a/meta/recipes-extended/unzip/unzip/CVE-2019-13232.patch
+++ /dev/null
@@ -1,339 +0,0 @@
1From: Mark Adler <madler@alumni.caltech.edu>
2Subject: Detect and reject a zip bomb using overlapped entries.
3Origin: https://github.com/madler/unzip/commit/47b3ceae397d21bf822bc2ac73052a4b1daf8e1c
4Bug-Debian: https://bugs.debian.org/931433
5X-Debian-version: 6.0-24
6
7 Detect and reject a zip bomb using overlapped entries.
8
9 This detects an invalid zip file that has at least one entry that
10 overlaps with another entry or with the central directory to the
11 end of the file. A Fifield zip bomb uses overlapped local entries
12 to vastly increase the potential inflation ratio. Such an invalid
13 zip file is rejected.
14
15 See https://www.bamsoftware.com/hacks/zipbomb/ for David Fifield's
16 analysis, construction, and examples of such zip bombs.
17
18 The detection maintains a list of covered spans of the zip files
19 so far, where the central directory to the end of the file and any
20 bytes preceding the first entry at zip file offset zero are
21 considered covered initially. Then as each entry is decompressed
22 or tested, it is considered covered. When a new entry is about to
23 be processed, its initial offset is checked to see if it is
24 contained by a covered span. If so, the zip file is rejected as
25 invalid.
26
27 This commit depends on a preceding commit: "Fix bug in
28 undefer_input() that misplaced the input state."
29
30Upstream-Status: Pending [Patch taken from debian]
31CVE: CVE-2019-13232
32Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
33
34--- a/extract.c
35+++ b/extract.c
36@@ -321,6 +321,125 @@
37 "\nerror: unsupported extra-field compression type (%u)--skipping\n";
38 static ZCONST char Far BadExtraFieldCRC[] =
39 "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n";
40+static ZCONST char Far NotEnoughMemCover[] =
41+ "error: not enough memory for bomb detection\n";
42+static ZCONST char Far OverlappedComponents[] =
43+ "error: invalid zip file with overlapped components (possible zip bomb)\n";
44+
45+
46+
47+
48+
49+/* A growable list of spans. */
50+typedef zoff_t bound_t;
51+typedef struct {
52+ bound_t beg; /* start of the span */
53+ bound_t end; /* one past the end of the span */
54+} span_t;
55+typedef struct {
56+ span_t *span; /* allocated, distinct, and sorted list of spans */
57+ size_t num; /* number of spans in the list */
58+ size_t max; /* allocated number of spans (num <= max) */
59+} cover_t;
60+
61+/*
62+ * Return the index of the first span in cover whose beg is greater than val.
63+ * If there is no such span, then cover->num is returned.
64+ */
65+static size_t cover_find(cover, val)
66+ cover_t *cover;
67+ bound_t val;
68+{
69+ size_t lo = 0, hi = cover->num;
70+ while (lo < hi) {
71+ size_t mid = (lo + hi) >> 1;
72+ if (val < cover->span[mid].beg)
73+ hi = mid;
74+ else
75+ lo = mid + 1;
76+ }
77+ return hi;
78+}
79+
80+/* Return true if val lies within any one of the spans in cover. */
81+static int cover_within(cover, val)
82+ cover_t *cover;
83+ bound_t val;
84+{
85+ size_t pos = cover_find(cover, val);
86+ return pos > 0 && val < cover->span[pos - 1].end;
87+}
88+
89+/*
90+ * Add a new span to the list, but only if the new span does not overlap any
91+ * spans already in the list. The new span covers the values beg..end-1. beg
92+ * must be less than end.
93+ *
94+ * Keep the list sorted and merge adjacent spans. Grow the allocated space for
95+ * the list as needed. On success, 0 is returned. If the new span overlaps any
96+ * existing spans, then 1 is returned and the new span is not added to the
97+ * list. If the new span is invalid because beg is greater than or equal to
98+ * end, then -1 is returned. If the list needs to be grown but the memory
99+ * allocation fails, then -2 is returned.
100+ */
101+static int cover_add(cover, beg, end)
102+ cover_t *cover;
103+ bound_t beg;
104+ bound_t end;
105+{
106+ size_t pos;
107+ int prec, foll;
108+
109+ if (beg >= end)
110+ /* The new span is invalid. */
111+ return -1;
112+
113+ /* Find where the new span should go, and make sure that it does not
114+ overlap with any existing spans. */
115+ pos = cover_find(cover, beg);
116+ if ((pos > 0 && beg < cover->span[pos - 1].end) ||
117+ (pos < cover->num && end > cover->span[pos].beg))
118+ return 1;
119+
120+ /* Check for adjacencies. */
121+ prec = pos > 0 && beg == cover->span[pos - 1].end;
122+ foll = pos < cover->num && end == cover->span[pos].beg;
123+ if (prec && foll) {
124+ /* The new span connects the preceding and following spans. Merge the
125+ following span into the preceding span, and delete the following
126+ span. */
127+ cover->span[pos - 1].end = cover->span[pos].end;
128+ cover->num--;
129+ memmove(cover->span + pos, cover->span + pos + 1,
130+ (cover->num - pos) * sizeof(span_t));
131+ }
132+ else if (prec)
133+ /* The new span is adjacent only to the preceding span. Extend the end
134+ of the preceding span. */
135+ cover->span[pos - 1].end = end;
136+ else if (foll)
137+ /* The new span is adjacent only to the following span. Extend the
138+ beginning of the following span. */
139+ cover->span[pos].beg = beg;
140+ else {
141+ /* The new span has gaps between both the preceding and the following
142+ spans. Assure that there is room and insert the span. */
143+ if (cover->num == cover->max) {
144+ size_t max = cover->max == 0 ? 16 : cover->max << 1;
145+ span_t *span = realloc(cover->span, max * sizeof(span_t));
146+ if (span == NULL)
147+ return -2;
148+ cover->span = span;
149+ cover->max = max;
150+ }
151+ memmove(cover->span + pos + 1, cover->span + pos,
152+ (cover->num - pos) * sizeof(span_t));
153+ cover->num++;
154+ cover->span[pos].beg = beg;
155+ cover->span[pos].end = end;
156+ }
157+ return 0;
158+}
159
160
161
162@@ -376,6 +495,29 @@
163 }
164 #endif /* !SFX || SFX_EXDIR */
165
166+ /* One more: initialize cover structure for bomb detection. Start with a
167+ span that covers the central directory though the end of the file. */
168+ if (G.cover == NULL) {
169+ G.cover = malloc(sizeof(cover_t));
170+ if (G.cover == NULL) {
171+ Info(slide, 0x401, ((char *)slide,
172+ LoadFarString(NotEnoughMemCover)));
173+ return PK_MEM;
174+ }
175+ ((cover_t *)G.cover)->span = NULL;
176+ ((cover_t *)G.cover)->max = 0;
177+ }
178+ ((cover_t *)G.cover)->num = 0;
179+ if ((G.extra_bytes != 0 &&
180+ cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
181+ cover_add((cover_t *)G.cover,
182+ G.extra_bytes + G.ecrec.offset_start_central_directory,
183+ G.ziplen) != 0) {
184+ Info(slide, 0x401, ((char *)slide,
185+ LoadFarString(NotEnoughMemCover)));
186+ return PK_MEM;
187+ }
188+
189 /*---------------------------------------------------------------------------
190 The basic idea of this function is as follows. Since the central di-
191 rectory lies at the end of the zipfile and the member files lie at the
192@@ -593,7 +735,8 @@
193 if (error > error_in_archive)
194 error_in_archive = error;
195 /* ...and keep going (unless disk full or user break) */
196- if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
197+ if (G.disk_full > 1 || error_in_archive == IZ_CTRLC ||
198+ error == PK_BOMB) {
199 /* clear reached_end to signal premature stop ... */
200 reached_end = FALSE;
201 /* ... and cancel scanning the central directory */
202@@ -1062,6 +1205,11 @@
203
204 /* seek_zipf(__G__ pInfo->offset); */
205 request = G.pInfo->offset + G.extra_bytes;
206+ if (cover_within((cover_t *)G.cover, request)) {
207+ Info(slide, 0x401, ((char *)slide,
208+ LoadFarString(OverlappedComponents)));
209+ return PK_BOMB;
210+ }
211 inbuf_offset = request % INBUFSIZ;
212 bufstart = request - inbuf_offset;
213
214@@ -1602,6 +1750,18 @@
215 return IZ_CTRLC; /* cancel operation by user request */
216 }
217 #endif
218+ error = cover_add((cover_t *)G.cover, request,
219+ G.cur_zipfile_bufstart + (G.inptr - G.inbuf));
220+ if (error < 0) {
221+ Info(slide, 0x401, ((char *)slide,
222+ LoadFarString(NotEnoughMemCover)));
223+ return PK_MEM;
224+ }
225+ if (error != 0) {
226+ Info(slide, 0x401, ((char *)slide,
227+ LoadFarString(OverlappedComponents)));
228+ return PK_BOMB;
229+ }
230 #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
231 UserStop();
232 #endif
233@@ -2003,6 +2163,34 @@
234 }
235
236 undefer_input(__G);
237+
238+ if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
239+ /* skip over data descriptor (harder than it sounds, due to signature
240+ * ambiguity)
241+ */
242+# define SIG 0x08074b50
243+# define LOW 0xffffffff
244+ uch buf[12];
245+ unsigned shy = 12 - readbuf((char *)buf, 12);
246+ ulg crc = shy ? 0 : makelong(buf);
247+ ulg clen = shy ? 0 : makelong(buf + 4);
248+ ulg ulen = shy ? 0 : makelong(buf + 8); /* or high clen if ZIP64 */
249+ if (crc == SIG && /* if not SIG, no signature */
250+ (G.lrec.crc32 != SIG || /* if not SIG, have signature */
251+ (clen == SIG && /* if not SIG, no signature */
252+ ((G.lrec.csize & LOW) != SIG || /* if not SIG, have signature */
253+ (ulen == SIG && /* if not SIG, no signature */
254+ (G.zip64 ? G.lrec.csize >> 32 : G.lrec.ucsize) != SIG
255+ /* if not SIG, have signature */
256+ )))))
257+ /* skip four more bytes to account for signature */
258+ shy += 4 - readbuf((char *)buf, 4);
259+ if (G.zip64)
260+ shy += 8 - readbuf((char *)buf, 8); /* skip eight more for ZIP64 */
261+ if (shy)
262+ error = PK_ERR;
263+ }
264+
265 return error;
266
267 } /* end function extract_or_test_member() */
268--- a/globals.c
269+++ b/globals.c
270@@ -181,6 +181,7 @@
271 # if (!defined(NO_TIMESTAMPS))
272 uO.D_flag=1; /* default to '-D', no restoration of dir timestamps */
273 # endif
274+ G.cover = NULL; /* not allocated yet */
275 #endif
276
277 uO.lflag=(-1);
278--- a/globals.h
279+++ b/globals.h
280@@ -260,12 +260,15 @@
281 ecdir_rec ecrec; /* used in unzip.c, extract.c */
282 z_stat statbuf; /* used by main, mapname, check_for_newer */
283
284+ int zip64; /* true if Zip64 info in extra field */
285+
286 int mem_mode;
287 uch *outbufptr; /* extract.c static */
288 ulg outsize; /* extract.c static */
289 int reported_backslash; /* extract.c static */
290 int disk_full;
291 int newfile;
292+ void **cover; /* used in extract.c for bomb detection */
293
294 int didCRlast; /* fileio static */
295 ulg numlines; /* fileio static: number of lines printed */
296--- a/process.c
297+++ b/process.c
298@@ -637,6 +637,13 @@
299 }
300 #endif
301
302+ /* Free the cover span list and the cover structure. */
303+ if (G.cover != NULL) {
304+ free(*(G.cover));
305+ free(G.cover);
306+ G.cover = NULL;
307+ }
308+
309 } /* end function free_G_buffers() */
310
311
312@@ -1913,6 +1920,8 @@
313 #define Z64FLGS 0xffff
314 #define Z64FLGL 0xffffffff
315
316+ G.zip64 = FALSE;
317+
318 if (ef_len == 0 || ef_buf == NULL)
319 return PK_COOL;
320
321@@ -2084,6 +2093,8 @@
322 (ZCONST char *)(offset + ef_buf), ULen);
323 G.unipath_filename[ULen] = '\0';
324 }
325+
326+ G.zip64 = TRUE;
327 }
328
329 /* Skip this extra field block */
330--- a/unzip.h
331+++ b/unzip.h
332@@ -645,6 +645,7 @@
333 #define PK_NOZIP 9 /* zipfile not found */
334 #define PK_PARAM 10 /* bad or illegal parameters specified */
335 #define PK_FIND 11 /* no files found */
336+#define PK_BOMB 12 /* likely zip bomb */
337 #define PK_DISK 50 /* disk full */
338 #define PK_EOF 51 /* unexpected EOF */
339
diff --git a/meta/recipes-extended/unzip/unzip_6.0.bb b/meta/recipes-extended/unzip/unzip_6.0.bb
index 1d18526ce2..daba722722 100644
--- a/meta/recipes-extended/unzip/unzip_6.0.bb
+++ b/meta/recipes-extended/unzip/unzip_6.0.bb
@@ -22,7 +22,6 @@ SRC_URI = "${SOURCEFORGE_MIRROR}/infozip/UnZip%206.x%20%28latest%29/UnZip%206.0/
22 file://symlink.patch \ 22 file://symlink.patch \
23 file://0001-unzip-fix-CVE-2018-1000035.patch \ 23 file://0001-unzip-fix-CVE-2018-1000035.patch \
24 file://CVE-2018-18384.patch \ 24 file://CVE-2018-18384.patch \
25 file://CVE-2019-13232.patch \
26" 25"
27UPSTREAM_VERSION_UNKNOWN = "1" 26UPSTREAM_VERSION_UNKNOWN = "1"
28 27