debian/0000775000000000000000000000000012350670310007165 5ustar debian/docs0000664000000000000000000000003411543727543010053 0ustar README TODO ChangeLog-1.0.x debian/libtar0.install0000664000000000000000000000002211710331324012102 0ustar usr/lib/lib*.so.* debian/copyright0000664000000000000000000000404411771171776011144 0ustar This package was debianized by Glenn McGrath on Sat, 5 Jan 2002 13:24:37 +1100. It was downloaded from http://repo.or.cz/w/libtar.git; previously from http://www.feep.net/libtar/ Upstream Authors: Mark D. Roth and Chris Frey Copyright: Copyright (c) 1998-2003 University of Illinois Board of Trustees Copyright (c) 1998-2003 Mark D. Roth All rights reserved. Developed by: Campus Information Technologies and Educational Services, University of Illinois at Urbana-Champaign Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of Campus Information Technologies and Educational Services, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. debian/libtar-dev.manpages0000664000000000000000000000100311543727543012743 0ustar debian/tmp/usr/share/man/man3/libtar_hash_new.3 debian/tmp/usr/share/man/man3/libtar_list_new.3 debian/tmp/usr/share/man/man3/tar_append_file.3 debian/tmp/usr/share/man/man3/tar_block_read.3 debian/tmp/usr/share/man/man3/tar_extract_all.3 debian/tmp/usr/share/man/man3/tar_extract_file.3 debian/tmp/usr/share/man/man3/tar_open.3 debian/tmp/usr/share/man/man3/th_get_pathname.3 debian/tmp/usr/share/man/man3/th_print_long_ls.3 debian/tmp/usr/share/man/man3/th_read.3 debian/tmp/usr/share/man/man3/th_set_from_stat.3 debian/source/0000775000000000000000000000000012331233764010474 5ustar debian/source/format0000664000000000000000000000001411710331221011665 0ustar 3.0 (quilt) debian/changelog0000664000000000000000000001720312350670273011052 0ustar libtar (1.2.20-3ubuntu0.1) trusty-proposed; urgency=high [ Magnus Holmgren ] * no_maxpathlen.patch: Half of the part of the patch modifying compat/dirname.c was missing, causing libtar's dirname to always return NULL (except in special circumstances). Actually make it work (Closes: #745352). (The reason that libtar doesn't use libc's dirname() and basename() on some or most platforms is that the code doesn't work with destructive versions of these functions). (LP: #1315742) -- Brian Murray Thu, 19 Jun 2014 11:44:33 -0700 libtar (1.2.20-3) unstable; urgency=low * no_maxpathlen.patch: Fix two grave bugs in the patch. First, th_get_pathname would only allocate as much memory as was needed for the first filename encountered, causing heap corruption when/if encountering longer filenames later. Second, two variables were mixed up in tar_append_tree(). Also, fix a potential memory leak and trim the patch a bit. * [SECURITY] CVE-2013-4420.patch: When the prefix field is in use, the safer_name_suffix() function should certainly be applied to the combination of it and the name field, not just on the name field. * th_get_size-unsigned-int.patch: Make the th_get_size() macro cast the result from oct_to_int() to unsigned int. This is the right fix for bug #725938 on 64-bit systems, where a specially crafted tar file would not cause an integer overflow, but a memory allocation of almost 16 exbibytes, which would certainly fail outright without harm. -- Magnus Holmgren Sat, 15 Feb 2014 23:51:51 +0100 libtar (1.2.20-2) unstable; urgency=low * no_static_buffers.patch: avoid using a static buffer in th_get_pathname(). Taken from upstream. Needed for no_maxpathlen.patch. * no_maxpathlen.patch: Fix FTBFS on Hurd by dynamically allocating path names (Closes: #657116). Thanks to Svante Signell and Petter Reinholdtsen. * [SECURITY] CVE-2013-4420.patch: Strip out leading slashes and any pathname prefix containing ".." components (Closes: #731860). This is done in th_get_pathname() (as well as to symlink targets when extracting symlinks), not merely when extracting files, which means applications calling that function will not see the stored filename. There is no way to disable this behaviour, but it can be expected that one will be provided when the issue is solved upstream. * Bump Standards-Version to 3.9.5. -- Magnus Holmgren Sat, 15 Feb 2014 21:49:37 +0100 libtar (1.2.20-1) unstable; urgency=high * [SECURITY] New upstream release. Fixes CVE-2013-4397: Integer overflow (Closes: #725938). * Bump Standards-Version to 3.9.4. -- Magnus Holmgren Thu, 10 Oct 2013 19:20:49 +0200 libtar (1.2.19-1) unstable; urgency=low * New upstream release. -- Magnus Holmgren Sun, 05 May 2013 17:59:29 +0200 libtar (1.2.16-1) unstable; urgency=low * New upstream: Chris Frey has stepped up with the consent of the original author, Mark Roth, and published an "official unofficial" git repo at http://repo.or.cz/w/libtar.git, which I will use for the time being. * Updated debian/watch to look for tags and corresponding snapshot tarballs at above URL. * All patches have been incorporated or (in the case of autoreconf.patch) made obsolete upstream. * debian/rules: Add build-indep and build-arch targets. * Updated debian/copyright. * Use dpkg-buildflags to set CFLAGS et al. * debian/control: Add VCS fields; bump Standards-Version to 3.9.3. -- Magnus Holmgren Sat, 23 Jun 2012 01:03:41 +0200 libtar (1.2.11-8) unstable; urgency=low * libtool.patch: Set SHELL to the configured shell in those Makefile.in where libtool is used; otherwise libtool fails when /bin/sh is dash but bash is expected (Closes: #621935). * man_hyphen_minus.patch (new): Escape hyphens that should be minus signs in man pages. * Rename libtar as libtar0 to follow policy. -- Magnus Holmgren Sun, 24 Apr 2011 21:11:52 +0200 libtar (1.2.11-7) unstable; urgency=low * New maintainer (Closes: #526618). * Change source format to 3.0 (quilt), clean up Debian diff and split into several patches: * libtool.patch: Using libtool to build dynamic library; * autoreconf.patch: Changes needed to call autoreconf (bug 511741); * memleak.patch: Fix memory leaks; * bad_ptrtoint.patch: Document stupidity of tartype_t in libtar.c (bug 309945). * Increase Debhelper compat level to 7. * Use dh_autoreconf to avoid having to keep track of files to clean. * memleak2.patch (new): Applied instead of memleak.patch. Fix memory leak by making th_get_pathname() return a pointer to a static buffer instead of a pointer to a copy of a local buffer (LP: #41804). * Add homepage field and watch file (in case there is ever a new upstream release). * Upgrade to Standards-Version 3.9.1. -- Magnus Holmgren Sat, 26 Mar 2011 23:10:25 +0100 libtar (1.2.11-6) unstable; urgency=low * Fix autotools usage (Closes: #511741) -- Julien Danjou Sat, 02 May 2009 11:33:06 +0200 libtar (1.2.11-5) unstable; urgency=low * New maintainer (Closes: #465889) * Add missing binary-indep target in debian/rules (Closes: #395714) * Use ${binary:Version} instead of Source-Version * Bump standard version * Switch to debhelper 5 -- Julien Danjou Wed, 02 Apr 2008 07:06:55 +0200 libtar (1.2.11-4) unstable; urgency=low * Always include the newest libtool.m4. (Closes: #313612) -- James Morrison Sun, 28 Aug 2005 09:41:47 -0700 libtar (1.2.11-3) unstable; urgency=low * Document stupidity of tartype_t in libtar.c. (Closes: #309945) -- James Morrison Sat, 11 Jun 2005 18:23:15 -0400 libtar (1.2.11-2) unstable; urgency=low * Move libtar-dev to libdevel. (Closes: #188207) * Fix potential memory leak. -- James Morrison Sun, 25 Jul 2004 12:59:08 -0700 libtar (1.2.11-1) unstable; urgency=low * New Upstream release. -- James Morrison Sat, 5 Apr 2003 14:03:19 -0500 libtar (1.2.10-1) unstable; urgency=low * New Upstream release. (Closes: #166602) New upstream uses autoconf 2.5x * Remove dependency on automake. Hopefully upstream will except this use of libtool. * Remove all -static and -shared targets from debian/rules. * Use dh_install instead of dh_movefiles. * - -- James Morrison Sat, 5 Apr 2003 14:03:16 -0500 libtar (1.2.5-4) unstable; urgency=low * New maintainer. (Closes: #154597) * WSG_ENCAP is now defined. (Closes: #147764) * libtar-dev depends on libc-dev instead of libc6-dev. -- James Morrison Wed, 14 Aug 2002 23:44:16 -0400 libtar (1.2.5-3) unstable; urgency=low * Modify build commands to acomadate change in autoconf (Closes #147764) -- Glenn McGrath Thu, 23 May 2002 01:06:16 +1000 libtar (1.2.5-2) unstable; urgency=low * Fix build problem (Closes #135360) -- Glenn McGrath Sun, 24 Feb 2002 06:29:31 +1100 libtar (1.2.5-1) unstable; urgency=low * New upstream version * Change section of libtar-dev to devel and libtar to libs -- Glenn McGrath Fri, 22 Feb 2002 04:23:15 +1100 libtar (1.2.4-2) unstable; urgency=low * Change section from devel to libs -- Glenn McGrath Sat, 2 Feb 2002 12:12:32 +1100 libtar (1.2.4-1) unstable; urgency=low * Initial Release. (closes #128042) -- Glenn McGrath Sat, 5 Jan 2002 13:24:37 +1100 debian/libtar-dev.examples0000664000000000000000000000004011710331221012742 0ustar libtar/libtar.c libtar/Makefile debian/watch0000664000000000000000000000033411771171745010234 0ustar version=3 #ftp://ftp.feep.net/pub/software/libtar/libtar-(.*).tar.gz opts=downloadurlmangle=s/tag/snapshot/,filenamemangle=s/.*\/v([\d\.]+)$/libtar-$1.tar.gz/ \ http://repo.or.cz/w/libtar.git/shortlog ^.*/v([\d\.]+) debian/compat0000664000000000000000000000000211710331221010355 0ustar 7 debian/libtar-dev.install0000664000000000000000000000012111543727543012616 0ustar usr/include/libtar.h usr/include/libtar_listhash.h usr/lib/lib*.a usr/lib/lib*so debian/control0000664000000000000000000000201112350627673010600 0ustar Source: libtar Section: libs Priority: optional Maintainer: Ubuntu Developers XSBC-Original-Maintainer: Magnus Holmgren Build-Depends: dpkg-dev (>= 1.15.7), debhelper (>= 7), dh-autoreconf, autoconf, libtool Standards-Version: 3.9.5 Homepage: http://www.feep.net/libtar/ Vcs-Browser: http://svn.kibibyte.se/libtar Vcs-Svn: svn://svn.kibibyte.se/libtar/trunk Package: libtar-dev Architecture: any Section: libdevel Depends: libtar0 (= ${binary:Version}), ${misc:Depends} Description: C library for manipulating tar archives (development files) Contains static library, headers, example code and development manpages for libtar Package: libtar0 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: libtar Breaks: libtar Provides: libtar Description: C library for manipulating tar archives libtar allows programs to create, extract and test tar archives. It supports both the strict POSIX tar format and many of the commonly-used GNU extensions. debian/patches/0000775000000000000000000000000012331233764010623 5ustar debian/patches/no_maxpathlen.patch0000664000000000000000000002605012331233732014477 0ustar Author: Svante Signell Author: Petter Reinholdtsen Author: Magnus Holmgren Bug-Debian: http://bugs.debian.org/657116 Description: Fix FTBFS on Hurd by dynamically allocating path names. Depends on no_static_buffers.patch, which introduced the th_pathname field. --- a/compat/basename.c +++ b/compat/basename.c @@ -34,13 +34,25 @@ static char rcsid[] = "$OpenBSD: basenam #include #include #include +#include char * openbsd_basename(path) const char *path; { - static char bname[MAXPATHLEN]; + static char *bname = NULL; + static size_t allocated = 0; register const char *endp, *startp; + int len = 0; + + if (!allocated) { + allocated = 64; + bname = malloc(allocated); + if (!bname) { + allocated = 0; + return NULL; + } + } /* Empty or NULL string gets treated as "." */ if (path == NULL || *path == '\0') { @@ -64,11 +76,19 @@ openbsd_basename(path) while (startp > path && *(startp - 1) != '/') startp--; - if (endp - startp + 1 > sizeof(bname)) { - errno = ENAMETOOLONG; - return(NULL); + len = endp - startp + 1; + + if (len + 1 > allocated) { + size_t new_allocated = 2*(len+1); + void *new_bname = malloc(new_allocated); + if (!new_bname) + return NULL; + allocated = new_allocated; + free(bname); + bname = new_bname; } - (void)strncpy(bname, startp, endp - startp + 1); - bname[endp - startp + 1] = '\0'; + + (void)strncpy(bname, startp, len); + bname[len] = '\0'; return(bname); } --- a/compat/dirname.c +++ b/compat/dirname.c @@ -34,13 +34,25 @@ static char rcsid[] = "$OpenBSD: dirname #include #include #include +#include char * openbsd_dirname(path) const char *path; { - static char bname[MAXPATHLEN]; + static char *bname = NULL; + static size_t allocated = 0; register const char *endp; + int len; + + if (!allocated) { + allocated = 64; + bname = malloc(allocated); + if (!bname) { + allocated = 0; + return NULL; + } + } /* Empty or NULL string gets treated as "." */ if (path == NULL || *path == '\0') { @@ -67,11 +79,19 @@ openbsd_dirname(path) } while (endp > path && *endp == '/'); } - if (endp - path + 1 > sizeof(bname)) { - errno = ENAMETOOLONG; - return(NULL); + len = endp - path + 1; + + if (len + 1 > allocated) { + size_t new_allocated = 2*(len+1); + void *new_bname = malloc(new_allocated); + if (!new_bname) + return NULL; + allocated = new_allocated; + free(bname); + bname = new_bname; } - (void)strncpy(bname, path, endp - path + 1); - bname[endp - path + 1] = '\0'; + + (void)strncpy(bname, path, len); + bname[len] = '\0'; return(bname); } --- a/lib/append.c +++ b/lib/append.c @@ -38,7 +38,7 @@ typedef struct tar_dev tar_dev_t; struct tar_ino { ino_t ti_ino; - char ti_name[MAXPATHLEN]; + char ti_name[]; }; typedef struct tar_ino tar_ino_t; @@ -61,7 +61,7 @@ tar_append_file(TAR *t, const char *real libtar_hashptr_t hp; tar_dev_t *td = NULL; tar_ino_t *ti = NULL; - char path[MAXPATHLEN]; + char *path = NULL; #ifdef DEBUG printf("==> tar_append_file(TAR=0x%lx (\"%s\"), realname=\"%s\", " @@ -126,34 +126,39 @@ tar_append_file(TAR *t, const char *real } else { + const char *name; #ifdef DEBUG printf("+++ adding entry: device (0x%lx,0x%lx), inode %ld " "(\"%s\")...\n", major(s.st_dev), minor(s.st_dev), s.st_ino, realname); #endif - ti = (tar_ino_t *)calloc(1, sizeof(tar_ino_t)); + name = savename ? savename : realname; + ti = (tar_ino_t *)calloc(1, sizeof(tar_ino_t) + strlen(name) + 1); if (ti == NULL) return -1; ti->ti_ino = s.st_ino; - snprintf(ti->ti_name, sizeof(ti->ti_name), "%s", - savename ? savename : realname); + snprintf(ti->ti_name, strlen(name) + 1, "%s", name); libtar_hash_add(td->td_h, ti); } /* check if it's a symlink */ if (TH_ISSYM(t)) { - i = readlink(realname, path, sizeof(path)); + if ((path = malloc(s.st_size + 1)) == NULL) + return -1; + i = readlink(realname, path, s.st_size); if (i == -1) + { + free(path); return -1; - if (i >= MAXPATHLEN) - i = MAXPATHLEN - 1; + } path[i] = '\0'; #ifdef DEBUG printf(" tar_append_file(): encoding symlink \"%s\" -> " "\"%s\"...\n", realname, path); #endif th_set_link(t, path); + free(path); } /* print file info */ --- a/lib/decode.c +++ b/lib/decode.c @@ -33,7 +33,8 @@ th_get_pathname(TAR *t) /* allocate the th_pathname buffer if not already */ if (t->th_pathname == NULL) { - t->th_pathname = malloc(MAXPATHLEN * sizeof(char)); + /* Allocate the maximum length of prefix + '/' + name + '\0' */ + t->th_pathname = malloc(155 + 1 + 100 + 1); if (t->th_pathname == NULL) /* out of memory */ return NULL; @@ -41,11 +42,11 @@ th_get_pathname(TAR *t) if (t->th_buf.prefix[0] == '\0') { - snprintf(t->th_pathname, MAXPATHLEN, "%.100s", t->th_buf.name); + sprintf(t->th_pathname, "%.100s", t->th_buf.name); } else { - snprintf(t->th_pathname, MAXPATHLEN, "%.155s/%.100s", + sprintf(t->th_pathname, "%.155s/%.100s", t->th_buf.prefix, t->th_buf.name); } --- a/lib/util.c +++ b/lib/util.c @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef STDC_HEADERS # include @@ -25,13 +26,15 @@ int path_hashfunc(char *key, int numbuckets) { - char buf[MAXPATHLEN]; + char *buf; char *p; + int i; - strcpy(buf, key); + buf = strdup(key); p = basename(buf); - - return (((unsigned int)p[0]) % numbuckets); + i = ((unsigned int)p[0]) % numbuckets; + free(buf); + return (i); } @@ -77,15 +80,26 @@ ino_hash(ino_t *inode) int mkdirhier(char *path) { - char src[MAXPATHLEN], dst[MAXPATHLEN] = ""; - char *dirp, *nextp = src; - int retval = 1; + char *src, *dst = NULL; + char *dirp, *nextp = NULL; + int retval = 1, len; + + len = strlen(path); + if ((src = strdup(path)) == NULL) + { + errno = ENOMEM; + return -1; + } + nextp = src; - if (strlcpy(src, path, sizeof(src)) > sizeof(src)) + /* Make room for // with absolute paths */ + if ((dst = malloc(len + 2)) == NULL) { - errno = ENAMETOOLONG; + free(src); + errno = ENOMEM; return -1; } + dst[0] = '\0'; if (path[0] == '/') strcpy(dst, "/"); @@ -102,12 +116,18 @@ mkdirhier(char *path) if (mkdir(dst, 0777) == -1) { if (errno != EEXIST) + { + free(src); + free(dst); return -1; + } } else retval = 0; } + free(src); + free(dst); return retval; } --- a/lib/wrapper.c +++ b/lib/wrapper.c @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef STDC_HEADERS # include @@ -26,8 +27,8 @@ int tar_extract_glob(TAR *t, char *globname, char *prefix) { char *filename; - char buf[MAXPATHLEN]; - int i; + char *buf = NULL; + int i, len; while ((i = th_read(t)) == 0) { @@ -41,11 +42,25 @@ tar_extract_glob(TAR *t, char *globname, if (t->options & TAR_VERBOSE) th_print_long_ls(t); if (prefix != NULL) - snprintf(buf, sizeof(buf), "%s/%s", prefix, filename); + { + len = strlen(prefix) + 1 + strlen(filename); + if ((buf = malloc(len + 1)) == NULL) + return -1; + sprintf(buf, "%s/%s", prefix, filename); + } else - strlcpy(buf, filename, sizeof(buf)); + { + len = strlen(filename); + if ((buf = malloc(len + 1)) == NULL) + return -1; + strcpy(buf, filename); + } if (tar_extract_file(t, buf) != 0) + { + free(buf); return -1; + } + free(buf); } return (i == 1 ? 0 : -1); @@ -56,8 +71,9 @@ int tar_extract_all(TAR *t, char *prefix) { char *filename; - char buf[MAXPATHLEN]; - int i; + char *buf = NULL; + size_t bufsize = 0; + int i, len; #ifdef DEBUG printf("==> tar_extract_all(TAR *t, \"%s\")\n", @@ -73,15 +89,29 @@ tar_extract_all(TAR *t, char *prefix) if (t->options & TAR_VERBOSE) th_print_long_ls(t); if (prefix != NULL) - snprintf(buf, sizeof(buf), "%s/%s", prefix, filename); + { + len = strlen(prefix) + 1 + strlen(filename); + if ((buf = malloc(len + 1)) == NULL) + return -1; + sprintf(buf, "%s/%s", prefix, filename); + } else - strlcpy(buf, filename, sizeof(buf)); + { + len = strlen(filename); + if ((buf = malloc(len + 1)) == NULL) + return -1; + strcpy(buf, filename); + } #ifdef DEBUG printf(" tar_extract_all(): calling tar_extract_file(t, " "\"%s\")\n", buf); #endif if (tar_extract_file(t, buf) != 0) + { + free(buf); return -1; + } + free(buf); } return (i == 1 ? 0 : -1); @@ -91,11 +121,14 @@ tar_extract_all(TAR *t, char *prefix) int tar_append_tree(TAR *t, char *realdir, char *savedir) { - char realpath[MAXPATHLEN]; - char savepath[MAXPATHLEN]; + char *realpath = NULL; + size_t realpathsize = 0; + char *savepath = NULL; + size_t savepathsize = 0; struct dirent *dent; DIR *dp; struct stat s; + int len; #ifdef DEBUG printf("==> tar_append_tree(0x%lx, \"%s\", \"%s\")\n", @@ -122,11 +155,21 @@ tar_append_tree(TAR *t, char *realdir, c strcmp(dent->d_name, "..") == 0) continue; - snprintf(realpath, MAXPATHLEN, "%s/%s", realdir, + len = strlen(realdir) + 1 + strlen(dent->d_name); + if ((realpath = malloc(len + 1)) == NULL) + return -1; + snprintf(realpath, len + 1, "%s/%s", realdir, dent->d_name); if (savedir) - snprintf(savepath, MAXPATHLEN, "%s/%s", savedir, + { + len = strlen(savedir) + 1 + strlen(dent->d_name); + if ((savepath = malloc(len + 1)) == NULL) { + free(realpath); + return -1; + } + snprintf(savepath, len + 1, "%s/%s", savedir, dent->d_name); + } if (lstat(realpath, &s) != 0) return -1; @@ -135,13 +178,23 @@ tar_append_tree(TAR *t, char *realdir, c { if (tar_append_tree(t, realpath, (savedir ? savepath : NULL)) != 0) + { + free(realpath); + free(savepath); return -1; + } continue; } if (tar_append_file(t, realpath, (savedir ? savepath : NULL)) != 0) + { + free(realpath); + free(savepath); return -1; + } + free(realpath); + free(savepath); } closedir(dp); --- a/libtar/libtar.c +++ b/libtar/libtar.c @@ -111,8 +111,9 @@ create(char *tarfile, char *rootdir, lib { TAR *t; char *pathname; - char buf[MAXPATHLEN]; + char *buf = NULL; libtar_listptr_t lp; + int len; if (tar_open(&t, tarfile, #ifdef HAVE_LIBZ @@ -133,17 +134,29 @@ create(char *tarfile, char *rootdir, lib { pathname = (char *)libtar_listptr_data(&lp); if (pathname[0] != '/' && rootdir != NULL) - snprintf(buf, sizeof(buf), "%s/%s", rootdir, pathname); + { + len = strlen(rootdir) + 1 + strlen(pathname); + if ((buf = malloc(len + 1)) == NULL) + return -1; + snprintf(buf, len + 1, "%s/%s", rootdir, pathname); + } else - strlcpy(buf, pathname, sizeof(buf)); + { + len = strlen(pathname); + if ((buf = malloc(len + 1)) == NULL) + return -1; + strlcpy(buf, pathname, len + 1); + } if (tar_append_tree(t, buf, pathname) != 0) { fprintf(stderr, "tar_append_tree(\"%s\", \"%s\"): %s\n", buf, pathname, strerror(errno)); tar_close(t); + free(buf); return -1; } + free(buf); } if (tar_append_eof(t) != 0) debian/patches/no_static_buffers.patch0000664000000000000000000000371112277765602015357 0ustar From: Kamil Dudka Date: Wed, 23 Oct 2013 13:04:22 +0000 (+0200) Origin: http://repo.or.cz/w/libtar.git/commitdiff/ec613af2e9371d7a3e1f7c7a6822164a4255b4d1 Subject: decode: avoid using a static buffer in th_get_pathname() decode: avoid using a static buffer in th_get_pathname() A solution suggested by Chris Frey: https://lists.feep.net:8080/pipermail/libtar/2013-October/000377.html Note this can break programs that expect sizeof(TAR) to be fixed. --- a/lib/decode.c +++ b/lib/decode.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -26,20 +27,30 @@ char * th_get_pathname(TAR *t) { - static TLS_THREAD char filename[MAXPATHLEN]; - if (t->th_buf.gnu_longname) return t->th_buf.gnu_longname; - if (t->th_buf.prefix[0] != '\0') + /* allocate the th_pathname buffer if not already */ + if (t->th_pathname == NULL) + { + t->th_pathname = malloc(MAXPATHLEN * sizeof(char)); + if (t->th_pathname == NULL) + /* out of memory */ + return NULL; + } + + if (t->th_buf.prefix[0] == '\0') + { + snprintf(t->th_pathname, MAXPATHLEN, "%.100s", t->th_buf.name); + } + else { - snprintf(filename, sizeof(filename), "%.155s/%.100s", + snprintf(t->th_pathname, MAXPATHLEN, "%.155s/%.100s", t->th_buf.prefix, t->th_buf.name); - return filename; } - snprintf(filename, sizeof(filename), "%.100s", t->th_buf.name); - return filename; + /* will be deallocated in tar_close() */ + return t->th_pathname; } --- a/lib/handle.c +++ b/lib/handle.c @@ -121,6 +121,7 @@ tar_close(TAR *t) libtar_hash_free(t->h, ((t->oflags & O_ACCMODE) == O_RDONLY ? free : (libtar_freefunc_t)tar_dev_free)); + free(t->th_pathname); free(t); return i; --- a/lib/libtar.h +++ b/lib/libtar.h @@ -85,6 +85,9 @@ typedef struct int options; struct tar_header th_buf; libtar_hash_t *h; + + /* introduced in libtar 1.2.21 */ + char *th_pathname; } TAR; debian/patches/th_get_size-unsigned-int.patch0000664000000000000000000000417412277767643016601 0ustar Origin: http://repo.or.cz/w/libtar.git/commitdiff/e4c1f2974258d6a325622cfd712873d49b5e7a73 From: Chris Frey Date: Thu, 24 Oct 2013 18:52:44 -0400 Subject: [PATCH] Change th_get_size() macro to return unsigned int On systems where size_t is larger than an int (and larger than unsigned int), then in various places in the library, where stuff like this happens: size_t sz = th_get_size(t); then the int value returned from th_get_size() is sign extended to some unwieldy amount. On 64bit systems, this can yield extremely large values. By fixing this problem in the header, and only for th_get_size(), we avoid breaking the API of the function call oct_to_int() (which arguably should return an unsigned int, since the sscanf() it uses expects to yield an unsigned int). We also fix the library, which uses th_get_size() internally to assign sizes to size_t. The drawback is that not all client code that uses th_get_size() will be fixed, until they recompile, but they will automatically take advantage of the bugs fixed *inside* the library. The remaining th_get_*() functions operate on modes and CRC values and the like, and should be fine, remaining as ints. Thanks very much to Magnus Holmgren for catching this behaviour. https://lists.feep.net:8080/pipermail/libtar/2013-October/000365.html --- lib/libtar.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/libtar.h b/lib/libtar.h index 2fefee0..13bb82d 100644 --- a/lib/libtar.h +++ b/lib/libtar.h @@ -185,7 +185,11 @@ int th_write(TAR *t); /* decode tar header info */ #define th_get_crc(t) oct_to_int((t)->th_buf.chksum) -#define th_get_size(t) oct_to_int((t)->th_buf.size) +/* We cast from int (what oct_to_int() returns) to + unsigned int, to avoid unwieldy sign extensions + from occurring on systems where size_t is bigger than int, + since th_get_size() is often stored into a size_t. */ +#define th_get_size(t) ((unsigned int)oct_to_int((t)->th_buf.size)) #define th_get_mtime(t) oct_to_int((t)->th_buf.mtime) #define th_get_devmajor(t) oct_to_int((t)->th_buf.devmajor) #define th_get_devminor(t) oct_to_int((t)->th_buf.devminor) debian/patches/series0000664000000000000000000000013712277767643012062 0ustar no_static_buffers.patch no_maxpathlen.patch CVE-2013-4420.patch th_get_size-unsigned-int.patch debian/patches/CVE-2013-4420.patch0000664000000000000000000000540112277765602013245 0ustar 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,13 +22,42 @@ # include #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) { if (t->th_buf.gnu_longname) - return t->th_buf.gnu_longname; + return safer_name_suffix(t->th_buf.gnu_longname); /* allocate the th_pathname buffer if not already */ if (t->th_pathname == NULL) @@ -51,7 +80,7 @@ th_get_pathname(TAR *t) } /* will be deallocated in tar_close() */ - return t->th_pathname; + return safer_name_suffix(t->th_pathname); } --- 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 @@ -21,3 +21,4 @@ #define TLS_THREAD #endif +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'); debian/rules0000775000000000000000000000214311771173345010261 0ustar #!/usr/bin/make -f export LIBTOOLIZE = libtoolize --install configure: configure-stamp configure-stamp: dh_testdir [ -f debian/autoreconf.before ] || dh_autoreconf ./configure \ --prefix=/usr \ --mandir=\$${prefix}/share/man \ $(shell dpkg-buildflags --export=configure) touch configure-stamp build-arch: build build-indep: build: build-stamp build-stamp: configure-stamp dh_testdir $(MAKE) touch build-stamp clean: dh_testdir dh_testroot # Stale build files [ ! -f Makefile ] || $(MAKE) distclean -rm -f build-stamp configure-stamp dh_autoreconf_clean dh_clean libtool configure install: build-stamp dh_testdir dh_testroot dh_prep $(MAKE) install DESTDIR=$(CURDIR)/debian/tmp binary-indep: binary-arch: install dh_testdir dh_testroot dh_install --sourcedir=debian/tmp dh_installdocs dh_installexamples dh_installman dh_installchangelogs ChangeLog dh_link dh_strip dh_compress dh_fixperms dh_makeshlibs dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install configure