Backport an upstream patch to fix erroneous "zip bomb" detection
ok naddy
This commit is contained in:
parent
248f18c28d
commit
68f39bf9dd
@ -1,4 +1,4 @@
|
||||
# $OpenBSD: Makefile,v 1.65 2020/03/11 21:57:31 naddy Exp $
|
||||
# $OpenBSD: Makefile,v 1.66 2020/11/14 17:45:17 jcs Exp $
|
||||
|
||||
PORTROACH = skipv:551,552
|
||||
|
||||
@ -7,7 +7,7 @@ COMMENT = extract, list & test files in a ZIP archive
|
||||
VERSION = 6.0
|
||||
DISTNAME = unzip${VERSION:S/.//}
|
||||
PKGNAME = unzip-${VERSION}
|
||||
REVISION = 13
|
||||
REVISION = 14
|
||||
CATEGORIES = archivers
|
||||
MASTER_SITES = ${MASTER_SITE_SOURCEFORGE:=infozip/} \
|
||||
ftp://ftp.info-zip.org/pub/infozip/src/
|
||||
|
@ -1,4 +1,4 @@
|
||||
$OpenBSD: patch-extract_c,v 1.3 2020/03/11 21:57:32 naddy Exp $
|
||||
$OpenBSD: patch-extract_c,v 1.4 2020/11/14 17:45:17 jcs Exp $
|
||||
|
||||
Fix CVE-2015-7696: prevent unsigned overflow on invalid input
|
||||
https://bugzilla.redhat.com/attachment.cgi?id=1075942
|
||||
@ -14,6 +14,7 @@ Fix CVE-2015-7697: infinite loop when extracting empty bzip2 data
|
||||
https://bugzilla.redhat.com/attachment.cgi?id=1073339
|
||||
Fix CVE-2019-13232: a zip bomb using overlapped entries
|
||||
https://github.com/madler/unzip/commit/47b3ceae397d21bf822bc2ac73052a4b1daf8e1c
|
||||
https://github.com/madler/unzip/commit/6d351831be705cc26d897db44f878a978f4138fc
|
||||
|
||||
Index: extract.c
|
||||
--- extract.c.orig
|
||||
@ -165,12 +166,15 @@ Index: extract.c
|
||||
/**************************************/
|
||||
/* Function extract_or_test_files() */
|
||||
/**************************************/
|
||||
@@ -374,6 +495,29 @@ int extract_or_test_files(__G) /* return PK-type er
|
||||
@@ -374,6 +495,42 @@ int extract_or_test_files(__G) /* return PK-type er
|
||||
}
|
||||
#endif /* !SFX || SFX_EXDIR */
|
||||
|
||||
+ /* One more: initialize cover structure for bomb detection. Start with a
|
||||
+ span that covers the central directory though the end of the file. */
|
||||
+ /* One more: initialize cover structure for bomb detection. Start with
|
||||
+ spans that cover any extra bytes at the start, the central directory,
|
||||
+ the end of central directory record (including the Zip64 end of central
|
||||
+ directory locator, if present), and the Zip64 end of central directory
|
||||
+ record, if present. */
|
||||
+ if (G.cover == NULL) {
|
||||
+ G.cover = malloc(sizeof(cover_t));
|
||||
+ if (G.cover == NULL) {
|
||||
@ -182,20 +186,30 @@ Index: extract.c
|
||||
+ ((cover_t *)G.cover)->max = 0;
|
||||
+ }
|
||||
+ ((cover_t *)G.cover)->num = 0;
|
||||
+ if ((G.extra_bytes != 0 &&
|
||||
+ cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
|
||||
+ cover_add((cover_t *)G.cover,
|
||||
+ if (cover_add((cover_t *)G.cover,
|
||||
+ G.extra_bytes + G.ecrec.offset_start_central_directory,
|
||||
+ G.ziplen) != 0) {
|
||||
+ G.extra_bytes + G.ecrec.offset_start_central_directory +
|
||||
+ G.ecrec.size_central_directory) != 0) {
|
||||
+ Info(slide, 0x401, ((char *)slide,
|
||||
+ LoadFarString(NotEnoughMemCover)));
|
||||
+ return PK_MEM;
|
||||
+ }
|
||||
+ if ((G.extra_bytes != 0 &&
|
||||
+ cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
|
||||
+ (G.ecrec.have_ecr64 &&
|
||||
+ cover_add((cover_t *)G.cover, G.ecrec.ec64_start,
|
||||
+ G.ecrec.ec64_end) != 0) ||
|
||||
+ cover_add((cover_t *)G.cover, G.ecrec.ec_start,
|
||||
+ G.ecrec.ec_end) != 0) {
|
||||
+ Info(slide, 0x401, ((char *)slide,
|
||||
+ LoadFarString(OverlappedComponents)));
|
||||
+ return PK_BOMB;
|
||||
+ }
|
||||
+
|
||||
/*---------------------------------------------------------------------------
|
||||
The basic idea of this function is as follows. Since the central di-
|
||||
rectory lies at the end of the zipfile and the member files lie at the
|
||||
@@ -591,7 +735,8 @@ int extract_or_test_files(__G) /* return PK-type er
|
||||
@@ -591,7 +748,8 @@ int extract_or_test_files(__G) /* return PK-type er
|
||||
if (error > error_in_archive)
|
||||
error_in_archive = error;
|
||||
/* ...and keep going (unless disk full or user break) */
|
||||
@ -205,7 +219,7 @@ Index: extract.c
|
||||
/* clear reached_end to signal premature stop ... */
|
||||
reached_end = FALSE;
|
||||
/* ... and cancel scanning the central directory */
|
||||
@@ -1060,6 +1205,11 @@ static int extract_or_test_entrylist(__G__ numchunk,
|
||||
@@ -1060,6 +1218,11 @@ static int extract_or_test_entrylist(__G__ numchunk,
|
||||
|
||||
/* seek_zipf(__G__ pInfo->offset); */
|
||||
request = G.pInfo->offset + G.extra_bytes;
|
||||
@ -217,7 +231,7 @@ Index: extract.c
|
||||
inbuf_offset = request % INBUFSIZ;
|
||||
bufstart = request - inbuf_offset;
|
||||
|
||||
@@ -1255,8 +1405,17 @@ static int extract_or_test_entrylist(__G__ numchunk,
|
||||
@@ -1255,8 +1418,17 @@ static int extract_or_test_entrylist(__G__ numchunk,
|
||||
if (G.lrec.compression_method == STORED) {
|
||||
zusz_t csiz_decrypted = G.lrec.csize;
|
||||
|
||||
@ -236,7 +250,7 @@ Index: extract.c
|
||||
if (G.lrec.ucsize != csiz_decrypted) {
|
||||
Info(slide, 0x401, ((char *)slide,
|
||||
LoadFarStringSmall2(WrnStorUCSizCSizDiff),
|
||||
@@ -1591,6 +1750,18 @@ reprompt:
|
||||
@@ -1591,6 +1763,18 @@ reprompt:
|
||||
return IZ_CTRLC; /* cancel operation by user request */
|
||||
}
|
||||
#endif
|
||||
@ -255,7 +269,7 @@ Index: extract.c
|
||||
#ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
|
||||
UserStop();
|
||||
#endif
|
||||
@@ -1992,6 +2163,34 @@ static int extract_or_test_member(__G) /* return PK
|
||||
@@ -1992,6 +2176,34 @@ static int extract_or_test_member(__G) /* return PK
|
||||
}
|
||||
|
||||
undefer_input(__G);
|
||||
@ -290,7 +304,7 @@ Index: extract.c
|
||||
return error;
|
||||
|
||||
} /* end function extract_or_test_member() */
|
||||
@@ -2023,7 +2222,8 @@ static int TestExtraField(__G__ ef, ef_len)
|
||||
@@ -2023,7 +2235,8 @@ static int TestExtraField(__G__ ef, ef_len)
|
||||
ebID = makeword(ef);
|
||||
ebLen = (unsigned)makeword(ef+EB_LEN);
|
||||
|
||||
@ -300,7 +314,7 @@ Index: extract.c
|
||||
/* Discovered some extra field inconsistency! */
|
||||
if (uO.qflag)
|
||||
Info(slide, 1, ((char *)slide, "%-22s ",
|
||||
@@ -2158,11 +2358,19 @@ static int TestExtraField(__G__ ef, ef_len)
|
||||
@@ -2158,11 +2371,19 @@ static int TestExtraField(__G__ ef, ef_len)
|
||||
}
|
||||
break;
|
||||
case EF_PKVMS:
|
||||
@ -321,7 +335,7 @@ Index: extract.c
|
||||
break;
|
||||
case EF_PKW32:
|
||||
case EF_PKUNIX:
|
||||
@@ -2217,15 +2425,32 @@ static int test_compr_eb(__G__ eb, eb_size, compr_offs
|
||||
@@ -2217,15 +2438,32 @@ static int test_compr_eb(__G__ eb, eb_size, compr_offs
|
||||
ulg eb_ucsize;
|
||||
uch *eb_ucptr;
|
||||
int r;
|
||||
@ -357,7 +371,7 @@ Index: extract.c
|
||||
if (
|
||||
#ifdef INT_16BIT
|
||||
(((ulg)(extent)eb_ucsize) != eb_ucsize) ||
|
||||
@@ -2700,6 +2925,12 @@ __GDEF
|
||||
@@ -2700,6 +2938,12 @@ __GDEF
|
||||
int err=BZ_OK;
|
||||
int repeated_buf_err;
|
||||
bz_stream bstrm;
|
||||
|
@ -1,4 +1,4 @@
|
||||
$OpenBSD: patch-process_c,v 1.4 2020/03/11 21:57:32 naddy Exp $
|
||||
$OpenBSD: patch-process_c,v 1.5 2020/11/14 17:45:17 jcs Exp $
|
||||
|
||||
Fix: handle the PKWare verification bit of internal attributes
|
||||
https://bugs.debian.org/630078
|
||||
@ -10,6 +10,7 @@ Fix: restore uid and gid information when requested
|
||||
https://bugs.debian.org/689212
|
||||
Fix CVE-2019-13232: a zip bomb using overlapped entries
|
||||
https://github.com/madler/unzip/commit/47b3ceae397d21bf822bc2ac73052a4b1daf8e1c
|
||||
https://github.com/madler/unzip/commit/6d351831be705cc26d897db44f878a978f4138fc
|
||||
|
||||
Index: process.c
|
||||
--- process.c.orig
|
||||
@ -35,7 +36,27 @@ Index: process.c
|
||||
} /* end function free_G_buffers() */
|
||||
|
||||
|
||||
@@ -1729,6 +1736,13 @@ int process_cdir_file_hdr(__G) /* return PK-type er
|
||||
@@ -1401,6 +1408,10 @@ static int find_ecrec64(__G__ searchlen) /* re
|
||||
|
||||
/* Now, we are (almost) sure that we have a Zip64 archive. */
|
||||
G.ecrec.have_ecr64 = 1;
|
||||
+ G.ecrec.ec_start -= ECLOC64_SIZE+4;
|
||||
+ G.ecrec.ec64_start = ecrec64_start_offset;
|
||||
+ G.ecrec.ec64_end = ecrec64_start_offset +
|
||||
+ 12 + makeint64(&byterec[ECREC64_LENGTH]);
|
||||
|
||||
/* Update the "end-of-central-dir offset" for later checks. */
|
||||
G.real_ecrec_offset = ecrec64_start_offset;
|
||||
@@ -1535,6 +1546,8 @@ static int find_ecrec(__G__ searchlen) /* ret
|
||||
makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
|
||||
G.ecrec.zipfile_comment_length =
|
||||
makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
|
||||
+ G.ecrec.ec_start = G.real_ecrec_offset;
|
||||
+ G.ecrec.ec_end = G.ecrec.ec_start + 22 + G.ecrec.zipfile_comment_length;
|
||||
|
||||
/* Now, we have to read the archive comment, BEFORE the file pointer
|
||||
is moved away backwards to seek for a Zip64 ECLOC64 structure.
|
||||
@@ -1729,6 +1742,13 @@ int process_cdir_file_hdr(__G) /* return PK-type er
|
||||
else if (uO.L_flag > 1) /* let -LL force lower case for all names */
|
||||
G.pInfo->lcflag = 1;
|
||||
|
||||
@ -49,7 +70,7 @@ Index: process.c
|
||||
/* do Amigas (AMIGA_) also have volume labels? */
|
||||
if (IS_VOLID(G.crec.external_file_attributes) &&
|
||||
(G.pInfo->hostnum == FS_FAT_ || G.pInfo->hostnum == FS_HPFS_ ||
|
||||
@@ -1751,6 +1765,12 @@ int process_cdir_file_hdr(__G) /* return PK-type er
|
||||
@@ -1751,6 +1771,12 @@ int process_cdir_file_hdr(__G) /* return PK-type er
|
||||
= (G.crec.general_purpose_bit_flag & (1 << 11)) == (1 << 11);
|
||||
#endif
|
||||
|
||||
@ -62,7 +83,7 @@ Index: process.c
|
||||
return PK_COOL;
|
||||
|
||||
} /* end function process_cdir_file_hdr() */
|
||||
@@ -1888,48 +1908,84 @@ int getZip64Data(__G__ ef_buf, ef_len)
|
||||
@@ -1888,48 +1914,84 @@ int getZip64Data(__G__ ef_buf, ef_len)
|
||||
and a 4-byte version of disk start number.
|
||||
Sets both local header and central header fields. Not terribly clever,
|
||||
but it means that this procedure is only called in one place.
|
||||
@ -163,7 +184,7 @@ Index: process.c
|
||||
ef_buf += (eb_len + EB_HEADSIZE);
|
||||
ef_len -= (eb_len + EB_HEADSIZE);
|
||||
}
|
||||
@@ -2037,6 +2093,8 @@ int getUnicodeData(__G__ ef_buf, ef_len)
|
||||
@@ -2037,6 +2099,8 @@ int getUnicodeData(__G__ ef_buf, ef_len)
|
||||
(ZCONST char *)(offset + ef_buf), ULen);
|
||||
G.unipath_filename[ULen] = '\0';
|
||||
}
|
||||
@ -172,7 +193,7 @@ Index: process.c
|
||||
}
|
||||
|
||||
/* Skip this extra field block */
|
||||
@@ -2867,10 +2925,13 @@ unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos
|
||||
@@ -2867,10 +2931,13 @@ unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos
|
||||
break;
|
||||
|
||||
case EF_IZUNIX2:
|
||||
@ -188,7 +209,7 @@ Index: process.c
|
||||
#ifdef IZ_HAVE_UXUIDGID
|
||||
if (have_new_type_eb > 1)
|
||||
break; /* IZUNIX3 overrides IZUNIX2 e.f. block ! */
|
||||
@@ -2886,6 +2947,8 @@ unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos
|
||||
@@ -2886,6 +2953,8 @@ unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos
|
||||
/* new 3rd generation Unix ef */
|
||||
have_new_type_eb = 2;
|
||||
|
||||
@ -197,7 +218,7 @@ Index: process.c
|
||||
/*
|
||||
Version 1 byte version of this extra field, currently 1
|
||||
UIDSize 1 byte Size of UID field
|
||||
@@ -2897,7 +2960,7 @@ unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos
|
||||
@@ -2897,7 +2966,7 @@ unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos
|
||||
#ifdef IZ_HAVE_UXUIDGID
|
||||
if (eb_len >= EB_UX3_MINLEN
|
||||
&& z_uidgid != NULL
|
||||
@ -206,7 +227,7 @@ Index: process.c
|
||||
/* only know about version 1 */
|
||||
{
|
||||
uch uid_size;
|
||||
@@ -2906,13 +2969,11 @@ unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos
|
||||
@@ -2906,13 +2975,11 @@ unsigned ef_scan_for_izux(ef_buf, ef_len, ef_is_c, dos
|
||||
uid_size = *((EB_HEADSIZE + 1) + ef_buf);
|
||||
gid_size = *((EB_HEADSIZE + uid_size + 2) + ef_buf);
|
||||
|
||||
|
@ -1,13 +1,22 @@
|
||||
$OpenBSD: patch-unzip_c,v 1.2 2015/10/20 13:13:52 ajacoutot Exp $
|
||||
--- unzip.c.orig Wed Oct 7 12:11:04 2015
|
||||
+++ unzip.c Wed Oct 7 12:12:09 2015
|
||||
@@ -717,6 +717,9 @@ int MAIN(argc, argv) /* return PK-type error code (e
|
||||
$OpenBSD: patch-unzip_c,v 1.3 2020/11/14 17:45:17 jcs Exp $
|
||||
Index: unzip.c
|
||||
--- unzip.c.orig
|
||||
+++ unzip.c
|
||||
@@ -65,6 +65,7 @@
|
||||
|
||||
#define __UNZIP_C /* identifies this source module */
|
||||
#define UNZIP_INTERNAL
|
||||
+#include <err.h>
|
||||
#include "unzip.h" /* includes, typedefs, macros, prototypes, etc. */
|
||||
#include "crypt.h"
|
||||
#include "unzvers.h"
|
||||
@@ -716,6 +717,9 @@ int MAIN(argc, argv) /* return PK-type error code (e
|
||||
char *argv[];
|
||||
{
|
||||
int r;
|
||||
|
||||
+
|
||||
+ if (pledge("stdio rpath wpath cpath fattr tty", NULL) == -1)
|
||||
+ err(1, "pledge");
|
||||
+
|
||||
|
||||
CONSTRUCTGLOBALS();
|
||||
r = unzip(__G__ argc, argv);
|
||||
DESTROYGLOBALS();
|
||||
|
25
archivers/unzip/patches/patch-unzpriv_h
Normal file
25
archivers/unzip/patches/patch-unzpriv_h
Normal file
@ -0,0 +1,25 @@
|
||||
$OpenBSD: patch-unzpriv_h,v 1.1 2020/11/14 17:45:17 jcs Exp $
|
||||
|
||||
Fix CVE-2019-13232: a zip bomb using overlapped entries
|
||||
https://github.com/madler/unzip/commit/6d351831be705cc26d897db44f878a978f4138fc
|
||||
|
||||
Index: unzpriv.h
|
||||
--- unzpriv.h.orig
|
||||
+++ unzpriv.h
|
||||
@@ -2185,6 +2185,16 @@ typedef struct VMStimbuf {
|
||||
int have_ecr64; /* valid Zip64 ecdir-record exists */
|
||||
int is_zip64_archive; /* Zip64 ecdir-record is mandatory */
|
||||
ush zipfile_comment_length;
|
||||
+ zusz_t ec_start, ec_end; /* offsets of start and end of the
|
||||
+ end of central directory record,
|
||||
+ including if present the Zip64
|
||||
+ end of central directory locator,
|
||||
+ which immediately precedes the
|
||||
+ end of central directory record */
|
||||
+ zusz_t ec64_start, ec64_end; /* if have_ecr64 is true, then these
|
||||
+ are the offsets of the start and
|
||||
+ end of the Zip64 end of central
|
||||
+ directory record */
|
||||
} ecdir_rec;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user