diff --git a/gnu/local.mk b/gnu/local.mk index dade7367be..60dbb7faf3 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -588,6 +588,7 @@ dist_patch_DATA = \ %D%/packages/patches/libmad-frame-length.patch \ %D%/packages/patches/libmad-mips-newgcc.patch \ %D%/packages/patches/libssh-0.6.5-CVE-2016-0739.patch \ + %D%/packages/patches/libtar-CVE-2013-4420.patch \ %D%/packages/patches/libtheora-config-guess.patch \ %D%/packages/patches/libtiff-CVE-2015-8665+CVE-2015-8683.patch \ %D%/packages/patches/libtiff-oob-accesses-in-decode.patch \ diff --git a/gnu/packages/compression.scm b/gnu/packages/compression.scm index 8148ecb070..5746ca3e03 100644 --- a/gnu/packages/compression.scm +++ b/gnu/packages/compression.scm @@ -34,6 +34,7 @@ #:use-module (guix git-download) #:use-module (guix build-system gnu) #:use-module (guix build-system perl) + #:use-module (gnu packages) #:use-module (gnu packages autotools) #:use-module (gnu packages backup) #:use-module (gnu packages base) @@ -122,7 +123,8 @@ utility. Instead of being written in Java, FastJar is written in C.") version ".orig.tar.gz"))) (sha256 (base32 - "02cihzl77ia0dcz7z2cga2412vyhhs5pa2355q4wpwbyga2lrwjh")))) + "02cihzl77ia0dcz7z2cga2412vyhhs5pa2355q4wpwbyga2lrwjh")) + (patches (search-patches "libtar-CVE-2013-4420.patch")))) (build-system gnu-build-system) (arguments `(#:tests? #f ;no "check" target diff --git a/gnu/packages/patches/libtar-CVE-2013-4420.patch b/gnu/packages/patches/libtar-CVE-2013-4420.patch new file mode 100644 index 0000000000..cc64711ae9 --- /dev/null +++ b/gnu/packages/patches/libtar-CVE-2013-4420.patch @@ -0,0 +1,118 @@ +Author: Raphael Geissert +Bug-Debian: https://bugs.debian.org/731860 +Description: Avoid directory traversal when extracting archives + by skipping over leading slashes and any prefix containing ".." components. +Forwarded: yes + +--- a/lib/decode.c ++++ b/lib/decode.c +@@ -22,6 +22,36 @@ + #endif + + ++char * ++safer_name_suffix (char const *file_name) ++{ ++ char const *p, *t; ++ p = t = file_name; ++ while (*p == '/') t = ++p; ++ while (*p) ++ { ++ while (p[0] == '.' && p[0] == p[1] && p[2] == '/') ++ { ++ p += 3; ++ t = p; ++ } ++ /* advance pointer past the next slash */ ++ while (*p && (p++)[0] != '/'); ++ } ++ ++ if (!*t) ++ { ++ t = "."; ++ } ++ ++ if (t != file_name) ++ { ++ /* TODO: warn somehow that the path was modified */ ++ } ++ return (char*)t; ++} ++ ++ + /* determine full path name */ + char * + th_get_pathname(TAR *t) +@@ -29,17 +59,17 @@ th_get_pathname(TAR *t) + static char filename[MAXPATHLEN]; + + if (t->th_buf.gnu_longname) +- return t->th_buf.gnu_longname; ++ return safer_name_suffix(t->th_buf.gnu_longname); + + if (t->th_buf.prefix[0] != '\0') + { + snprintf(filename, sizeof(filename), "%.155s/%.100s", + t->th_buf.prefix, t->th_buf.name); +- return filename; ++ return safer_name_suffix(filename); + } + + snprintf(filename, sizeof(filename), "%.100s", t->th_buf.name); +- return filename; ++ return safer_name_suffix(filename); + } + + +--- a/lib/extract.c ++++ b/lib/extract.c +@@ -298,14 +298,14 @@ tar_extract_hardlink(TAR * t, char *real + if (mkdirhier(dirname(filename)) == -1) + return -1; + libtar_hashptr_reset(&hp); +- if (libtar_hash_getkey(t->h, &hp, th_get_linkname(t), ++ if (libtar_hash_getkey(t->h, &hp, safer_name_suffix(th_get_linkname(t)), + (libtar_matchfunc_t)libtar_str_match) != 0) + { + lnp = (char *)libtar_hashptr_data(&hp); + linktgt = &lnp[strlen(lnp) + 1]; + } + else +- linktgt = th_get_linkname(t); ++ linktgt = safer_name_suffix(th_get_linkname(t)); + + #ifdef DEBUG + printf(" ==> extracting: %s (link to %s)\n", filename, linktgt); +@@ -343,9 +343,9 @@ tar_extract_symlink(TAR *t, char *realna + + #ifdef DEBUG + printf(" ==> extracting: %s (symlink to %s)\n", +- filename, th_get_linkname(t)); ++ filename, safer_name_suffix(th_get_linkname(t))); + #endif +- if (symlink(th_get_linkname(t), filename) == -1) ++ if (symlink(safer_name_suffix(th_get_linkname(t)), filename) == -1) + { + #ifdef DEBUG + perror("symlink()"); +--- a/lib/internal.h ++++ b/lib/internal.h +@@ -15,3 +15,4 @@ + + #include + ++char* safer_name_suffix(char const*); +--- a/lib/output.c ++++ b/lib/output.c +@@ -123,9 +123,9 @@ th_print_long_ls(TAR *t) + else + printf(" link to "); + if ((t->options & TAR_GNU) && t->th_buf.gnu_longlink != NULL) +- printf("%s", t->th_buf.gnu_longlink); ++ printf("%s", safer_name_suffix(t->th_buf.gnu_longlink)); + else +- printf("%.100s", t->th_buf.linkname); ++ printf("%.100s", safer_name_suffix(t->th_buf.linkname)); + } + + putchar('\n');