diff --git a/CVE-2018-16548-1.patch b/CVE-2018-16548-1.patch new file mode 100644 index 0000000..b4c6301 --- /dev/null +++ b/CVE-2018-16548-1.patch @@ -0,0 +1,76 @@ +From b6ce8a1ca9442f89fae3482921fadc928ecbbb05 Mon Sep 17 00:00:00 2001 +From: jmoellers +Date: Fri, 7 Sep 2018 11:32:04 +0200 +Subject: [PATCH 1/3] Avoid memory leak from __zzip_parse_root_directory(). + +(cherry picked from commit 9411bde3e4a70a81ff3ffd256b71927b2d90dcbb) +https://github.com/gdraheim/zziplib/commit/9411bde3e4a70a81ff3ffd256b71927b2d90dcbb +Signed-off-by: Yufa Fang +--- + zzip/zip.c | 36 ++++++++++++++++++++++++++++++++++-- + 1 files changed, 34 insertions(+), 2 deletions(-) + +diff --git a/zzip/zip.c b/zzip/zip.c +index 14e2e06..8318463 100644 +--- a/zzip/zip.c ++++ b/zzip/zip.c +@@ -472,9 +472,15 @@ __zzip_parse_root_directory(int fd, + } else + { + if (io->fd.seeks(fd, zz_rootseek + zz_offset, SEEK_SET) < 0) ++ { ++ free(hdr0); + return ZZIP_DIR_SEEK; ++ } + if (io->fd.read(fd, &dirent, sizeof(dirent)) < __sizeof(dirent)) ++ { ++ free(hdr0); + return ZZIP_DIR_READ; ++ } + d = &dirent; + } + +@@ -574,12 +580,38 @@ __zzip_parse_root_directory(int fd, + + if (hdr_return) + *hdr_return = hdr0; ++ else ++ { ++ /* If it is not assigned to *hdr_return, it will never be free()'d */ ++ free(hdr0); ++ /* Make sure we don't free it again in case of error */ ++ hdr0 = NULL; ++ } + } /* else zero (sane) entries */ + # ifndef ZZIP_ALLOW_MODULO_ENTRIES +- return (entries != zz_entries ? ZZIP_CORRUPTED : 0); ++ if (entries != zz_entries) ++ { ++ /* If it was assigned to *hdr_return, undo assignment */ ++ if (p_reclen && hdr_return) ++ *hdr_return = NULL; ++ /* Free it, if it was not already free()'d */ ++ if (hdr0 != NULL) ++ free(hdr0); ++ return ZZIP_CORRUPTED; ++ } + # else +- return ((entries & (unsigned)0xFFFF) != zz_entries ? ZZIP_CORRUPTED : 0); ++ if (((entries & (unsigned)0xFFFF) != zz_entries) ++ { ++ /* If it was assigned to *hdr_return, undo assignment */ ++ if (p_reclen && hdr_return) ++ *hdr_return = NULL; ++ /* Free it, if it was not already free()'d */ ++ if (hdr0 != NULL) ++ free(hdr0); ++ return ZZIP_CORRUPTED; ++ } + # endif ++ return 0; + } + + /* ------------------------- high-level interface ------------------------- */ +-- +2.19.1 + diff --git a/CVE-2018-16548-2.patch b/CVE-2018-16548-2.patch new file mode 100644 index 0000000..5cd75c3 --- /dev/null +++ b/CVE-2018-16548-2.patch @@ -0,0 +1,56 @@ +From e8d90fe7525c177f0c28f6843f2a25da2e6e5045 Mon Sep 17 00:00:00 2001 +From: jmoellers +Date: Fri, 7 Sep 2018 11:49:28 +0200 +Subject: [PATCH 2/3] Avoid memory leak from __zzip_parse_root_directory(). + +(cherry picked from commit d2e5d5c53212e54a97ad64b793a4389193fec687) +https://github.com/gdraheim/zziplib/commit/d2e5d5c53212e54a97ad64b793a4389193fec687 +Signed-off-by: Yufa Fang +--- + zzip/zip.c | 25 ++----------------------- + 1 file changed, 2 insertions(+), 23 deletions(-) + +diff --git a/zzip/zip.c b/zzip/zip.c +index 8318463..79fd9ad 100644 +--- a/zzip/zip.c ++++ b/zzip/zip.c +@@ -584,34 +584,13 @@ __zzip_parse_root_directory(int fd, + { + /* If it is not assigned to *hdr_return, it will never be free()'d */ + free(hdr0); +- /* Make sure we don't free it again in case of error */ +- hdr0 = NULL; + } + } /* else zero (sane) entries */ + # ifndef ZZIP_ALLOW_MODULO_ENTRIES +- if (entries != zz_entries) +- { +- /* If it was assigned to *hdr_return, undo assignment */ +- if (p_reclen && hdr_return) +- *hdr_return = NULL; +- /* Free it, if it was not already free()'d */ +- if (hdr0 != NULL) +- free(hdr0); +- return ZZIP_CORRUPTED; +- } ++ return (entries != zz_entries) ? ZZIP_CORRUPTED : 0; + # else +- if (((entries & (unsigned)0xFFFF) != zz_entries) +- { +- /* If it was assigned to *hdr_return, undo assignment */ +- if (p_reclen && hdr_return) +- *hdr_return = NULL; +- /* Free it, if it was not already free()'d */ +- if (hdr0 != NULL) +- free(hdr0); +- return ZZIP_CORRUPTED; +- } ++ return ((entries & (unsigned)0xFFFF) != zz_entries) ? ZZIP_CORRUPTED : 0; + # endif +- return 0; + } + + /* ------------------------- high-level interface ------------------------- */ +-- +2.19.1 + diff --git a/CVE-2018-16548-3.patch b/CVE-2018-16548-3.patch new file mode 100644 index 0000000..fa1508b --- /dev/null +++ b/CVE-2018-16548-3.patch @@ -0,0 +1,28 @@ +From a37ce0d441050356efc5fcaa48e1cdcf21a6b8e1 Mon Sep 17 00:00:00 2001 +From: jmoellers +Date: Fri, 7 Sep 2018 13:55:35 +0200 +Subject: [PATCH 3/3] One more free() to avoid memory leak. + +(cherry picked from commit 0e1dadb05c1473b9df2d7b8f298dab801778ef99) +https://github.com/gdraheim/zziplib/commit/0e1dadb05c1473b9df2d7b8f298dab801778ef99 +Signed-off-by: Yufa Fang +--- + zzip/zip.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/zzip/zip.c b/zzip/zip.c +index 79fd9ad..f97a40a 100644 +--- a/zzip/zip.c ++++ b/zzip/zip.c +@@ -586,6 +586,8 @@ __zzip_parse_root_directory(int fd, + free(hdr0); + } + } /* else zero (sane) entries */ ++ else ++ free(hdr0); + # ifndef ZZIP_ALLOW_MODULO_ENTRIES + return (entries != zz_entries) ? ZZIP_CORRUPTED : 0; + # else +-- +2.19.1 + diff --git a/CVE-2018-17828.patch b/CVE-2018-17828.patch new file mode 100644 index 0000000..ee7f4dd --- /dev/null +++ b/CVE-2018-17828.patch @@ -0,0 +1,345 @@ +From 81dfa6b3e08f6934885ba5c98939587d6850d08e Mon Sep 17 00:00:00 2001 +From: Josef Moellers +Date: Thu, 4 Oct 2018 14:21:48 +0200 +Subject: [PATCH] Fix issue #62: Remove any "../" components from pathnames of + extracted files. [CVE-2018-17828] + +https://github.com/gdraheim/zziplib/commit/f609ae8971f3c0ce64d38276b778001d0bbfc84b +--- + bins/unzzipcat-big.c | 57 +++++++++++++++++++++++++++++++++++++++++++- + bins/unzzipcat-mem.c | 57 +++++++++++++++++++++++++++++++++++++++++++- + bins/unzzipcat-mix.c | 57 +++++++++++++++++++++++++++++++++++++++++++- + bins/unzzipcat-zip.c | 57 +++++++++++++++++++++++++++++++++++++++++++- + 4 files changed, 224 insertions(+), 4 deletions(-) + +diff --git a/bins/unzzipcat-big.c b/bins/unzzipcat-big.c +index 982d262..88c4d65 100644 +--- a/bins/unzzipcat-big.c ++++ b/bins/unzzipcat-big.c +@@ -53,6 +53,48 @@ static void unzzip_cat_file(FILE* disk, char* name, FILE* out) + } + } + ++/* ++ * NAME: remove_dotdotslash ++ * PURPOSE: To remove any "../" components from the given pathname ++ * ARGUMENTS: path: path name with maybe "../" components ++ * RETURNS: Nothing, "path" is modified in-place ++ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it! ++ * Also, "path" is not used after creating it. ++ * So modifying "path" in-place is safe to do. ++ */ ++static inline void ++remove_dotdotslash(char *path) ++{ ++ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */ ++ char *dotdotslash; ++ int warned = 0; ++ ++ dotdotslash = path; ++ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL) ++ { ++ /* ++ * Remove only if at the beginning of the pathname ("../path/name") ++ * or when preceded by a slash ("path/../name"), ++ * otherwise not ("path../name..")! ++ */ ++ if (dotdotslash == path || dotdotslash[-1] == '/') ++ { ++ char *src, *dst; ++ if (!warned) ++ { ++ /* Note: the first time through the pathname is still intact */ ++ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path); ++ warned = 1; ++ } ++ /* We cannot use strcpy(), as there "The strings may not overlap" */ ++ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++) ++ ; ++ } ++ else ++ dotdotslash +=3; /* skip this instance to prevent infinite loop */ ++ } ++} ++ + static void makedirs(const char* name) + { + char* p = strrchr(name, '/'); +@@ -70,6 +112,16 @@ static void makedirs(const char* name) + + static FILE* create_fopen(char* name, char* mode, int subdirs) + { ++ char *name_stripped; ++ FILE *fp; ++ int mustfree = 0; ++ ++ if ((name_stripped = strdup(name)) != NULL) ++ { ++ remove_dotdotslash(name_stripped); ++ name = name_stripped; ++ mustfree = 1; ++ } + if (subdirs) + { + char* p = strrchr(name, '/'); +@@ -79,7 +131,10 @@ static FILE* create_fopen(char* name, char* mode, int subdirs) + free (dir_name); + } + } +- return fopen(name, mode); ++ fp = fopen(name, mode); ++ if (mustfree) ++ free(name_stripped); ++ return fp; + } + + +diff --git a/bins/unzzipcat-mem.c b/bins/unzzipcat-mem.c +index 9bc966b..793bde8 100644 +--- a/bins/unzzipcat-mem.c ++++ b/bins/unzzipcat-mem.c +@@ -58,6 +58,48 @@ static void unzzip_mem_disk_cat_file(ZZIP_MEM_DISK* disk, char* name, FILE* out) + } + } + ++/* ++ * NAME: remove_dotdotslash ++ * PURPOSE: To remove any "../" components from the given pathname ++ * ARGUMENTS: path: path name with maybe "../" components ++ * RETURNS: Nothing, "path" is modified in-place ++ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it! ++ * Also, "path" is not used after creating it. ++ * So modifying "path" in-place is safe to do. ++ */ ++static inline void ++remove_dotdotslash(char *path) ++{ ++ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */ ++ char *dotdotslash; ++ int warned = 0; ++ ++ dotdotslash = path; ++ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL) ++ { ++ /* ++ * Remove only if at the beginning of the pathname ("../path/name") ++ * or when preceded by a slash ("path/../name"), ++ * otherwise not ("path../name..")! ++ */ ++ if (dotdotslash == path || dotdotslash[-1] == '/') ++ { ++ char *src, *dst; ++ if (!warned) ++ { ++ /* Note: the first time through the pathname is still intact */ ++ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path); ++ warned = 1; ++ } ++ /* We cannot use strcpy(), as there "The strings may not overlap" */ ++ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++) ++ ; ++ } ++ else ++ dotdotslash +=3; /* skip this instance to prevent infinite loop */ ++ } ++} ++ + static void makedirs(const char* name) + { + char* p = strrchr(name, '/'); +@@ -75,6 +117,16 @@ static void makedirs(const char* name) + + static FILE* create_fopen(char* name, char* mode, int subdirs) + { ++ char *name_stripped; ++ FILE *fp; ++ int mustfree = 0; ++ ++ if ((name_stripped = strdup(name)) != NULL) ++ { ++ remove_dotdotslash(name_stripped); ++ name = name_stripped; ++ mustfree = 1; ++ } + if (subdirs) + { + char* p = strrchr(name, '/'); +@@ -84,7 +136,10 @@ static FILE* create_fopen(char* name, char* mode, int subdirs) + free (dir_name); + } + } +- return fopen(name, mode); ++ fp = fopen(name, mode); ++ if (mustfree) ++ free(name_stripped); ++ return fp; + } + + static int unzzip_cat (int argc, char ** argv, int extract) +diff --git a/bins/unzzipcat-mix.c b/bins/unzzipcat-mix.c +index 91c2f00..73b6ed6 100644 +--- a/bins/unzzipcat-mix.c ++++ b/bins/unzzipcat-mix.c +@@ -69,6 +69,48 @@ static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out) + } + } + ++/* ++ * NAME: remove_dotdotslash ++ * PURPOSE: To remove any "../" components from the given pathname ++ * ARGUMENTS: path: path name with maybe "../" components ++ * RETURNS: Nothing, "path" is modified in-place ++ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it! ++ * Also, "path" is not used after creating it. ++ * So modifying "path" in-place is safe to do. ++ */ ++static inline void ++remove_dotdotslash(char *path) ++{ ++ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */ ++ char *dotdotslash; ++ int warned = 0; ++ ++ dotdotslash = path; ++ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL) ++ { ++ /* ++ * Remove only if at the beginning of the pathname ("../path/name") ++ * or when preceded by a slash ("path/../name"), ++ * otherwise not ("path../name..")! ++ */ ++ if (dotdotslash == path || dotdotslash[-1] == '/') ++ { ++ char *src, *dst; ++ if (!warned) ++ { ++ /* Note: the first time through the pathname is still intact */ ++ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path); ++ warned = 1; ++ } ++ /* We cannot use strcpy(), as there "The strings may not overlap" */ ++ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++) ++ ; ++ } ++ else ++ dotdotslash +=3; /* skip this instance to prevent infinite loop */ ++ } ++} ++ + static void makedirs(const char* name) + { + char* p = strrchr(name, '/'); +@@ -86,6 +128,16 @@ static void makedirs(const char* name) + + static FILE* create_fopen(char* name, char* mode, int subdirs) + { ++ char *name_stripped; ++ FILE *fp; ++ int mustfree = 0; ++ ++ if ((name_stripped = strdup(name)) != NULL) ++ { ++ remove_dotdotslash(name_stripped); ++ name = name_stripped; ++ mustfree = 1; ++ } + if (subdirs) + { + char* p = strrchr(name, '/'); +@@ -95,7 +147,10 @@ static FILE* create_fopen(char* name, char* mode, int subdirs) + free (dir_name); + } + } +- return fopen(name, mode); ++ fp = fopen(name, mode); ++ if (mustfree) ++ free(name_stripped); ++ return fp; + } + + static int unzzip_cat (int argc, char ** argv, int extract) +diff --git a/bins/unzzipcat-zip.c b/bins/unzzipcat-zip.c +index 2810f85..7f7f3fa 100644 +--- a/bins/unzzipcat-zip.c ++++ b/bins/unzzipcat-zip.c +@@ -69,6 +69,48 @@ static void unzzip_cat_file(ZZIP_DIR* disk, char* name, FILE* out) + } + } + ++/* ++ * NAME: remove_dotdotslash ++ * PURPOSE: To remove any "../" components from the given pathname ++ * ARGUMENTS: path: path name with maybe "../" components ++ * RETURNS: Nothing, "path" is modified in-place ++ * NOTE: removing "../" from the path ALWAYS shortens the path, never adds to it! ++ * Also, "path" is not used after creating it. ++ * So modifying "path" in-place is safe to do. ++ */ ++static inline void ++remove_dotdotslash(char *path) ++{ ++ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */ ++ char *dotdotslash; ++ int warned = 0; ++ ++ dotdotslash = path; ++ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL) ++ { ++ /* ++ * Remove only if at the beginning of the pathname ("../path/name") ++ * or when preceded by a slash ("path/../name"), ++ * otherwise not ("path../name..")! ++ */ ++ if (dotdotslash == path || dotdotslash[-1] == '/') ++ { ++ char *src, *dst; ++ if (!warned) ++ { ++ /* Note: the first time through the pathname is still intact */ ++ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path); ++ warned = 1; ++ } ++ /* We cannot use strcpy(), as there "The strings may not overlap" */ ++ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++) ++ ; ++ } ++ else ++ dotdotslash +=3; /* skip this instance to prevent infinite loop */ ++ } ++} ++ + static void makedirs(const char* name) + { + char* p = strrchr(name, '/'); +@@ -86,6 +128,16 @@ static void makedirs(const char* name) + + static FILE* create_fopen(char* name, char* mode, int subdirs) + { ++ char *name_stripped; ++ FILE *fp; ++ int mustfree = 0; ++ ++ if ((name_stripped = strdup(name)) != NULL) ++ { ++ remove_dotdotslash(name_stripped); ++ name = name_stripped; ++ mustfree = 1; ++ } + if (subdirs) + { + char* p = strrchr(name, '/'); +@@ -95,7 +147,10 @@ static FILE* create_fopen(char* name, char* mode, int subdirs) + free (dir_name); + } + } +- return fopen(name, mode); ++ fp = fopen(name, mode); ++ if (mustfree) ++ free(name_stripped); ++ return fp; + } + + static int unzzip_cat (int argc, char ** argv, int extract) +-- +2.19.1 + diff --git a/zziplib.spec b/zziplib.spec index b3d473a..756c3c9 100644 --- a/zziplib.spec +++ b/zziplib.spec @@ -4,13 +4,17 @@ sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' */libtool Name: zziplib Version: 0.13.69 -Release: 2 +Release: 3 Summary: Lightweight library for zip compression License: LGPLv2+ or MPLv1.1 URL: http://zziplib.sourceforge.net Source0: https://github.com/gdraheim/zziplib/archive/v%{version}.tar.gz Patch0: zziplib-0.13.69-multilib.patch +Patch6000: CVE-2018-16548-1.patch +Patch6001: CVE-2018-16548-2.patch +Patch6002: CVE-2018-16548-3.patch +Patch6003: CVE-2018-17828.patch BuildRequires: perl-interpreter python2 python2-rpm-macros zip xmlto BuildRequires: zlib-devel SDL-devel pkgconfig autoconf automake @@ -44,6 +48,11 @@ This package includes help documentation and manuals related to zziplib. %prep %setup -q +%patch6000 -p1 +%patch6001 -p1 +%patch6002 -p1 +%patch6003 -p1 + find . -name '*.py' | xargs sed -i 's@#! /usr/bin/python@#! %__python2@g;s@#! /usr/bin/env python@#! %__python2@g' %build @@ -84,5 +93,8 @@ cd .. %{_mandir}/man3/* %changelog +* Sat Dec 21 2019 openEuler Buildteam - 0.13.36-3 +- Fix CVE-2018-16548 and CVE-2018-17828 + * Thu Sep 12 2019 dongjian 0.13.36-2 - Modification summary