From: Michael Olbrich <m.olbrich@pengutronix.de>
To: ptxdist@pengutronix.de
Subject: Re: [ptxdist] [PATCH] libtar: add as new package
Date: Thu, 6 Mar 2014 19:14:08 +0100 [thread overview]
Message-ID: <20140306181408.GS32080@pengutronix.de> (raw)
In-Reply-To: <1393160492-30990-1-git-send-email-post@lespocky.de>
On Sun, Feb 23, 2014 at 02:01:32PM +0100, Alexander Dahl wrote:
> libtar is a C library for manipulating POSIX tar files. It handles
> adding and extracting files to/from a tar archive. I reviewed the
> current Debian patches for usefulness and added all of them. Since the
> "official unofficial" way (maintainer's words) to get new releases is
> Git only I used the ptxdist mechanism for creating a tarball from a git
> clone in get stage.
>
> Signed-off-by: Alexander Dahl <post@lespocky.de>
Thanks, applied.
Michael
> ---
> ...d-using-a-static-buffer-in-th_get_pathnam.patch | 92 ++++
> patches/libtar-1.2.20/0002-no_maxpathlen.patch | 487 ++++++++++++++++++++
> patches/libtar-1.2.20/0003-CVE-2013-4420.patch | 126 +++++
> ...-th_get_size-macro-to-return-unsigned-int.patch | 51 ++
> patches/libtar-1.2.20/autogen.sh | 1 +
> patches/libtar-1.2.20/series | 7 +
> rules/libtar.in | 11 +
> rules/libtar.make | 62 +++
> 8 files changed, 837 insertions(+)
> create mode 100644 patches/libtar-1.2.20/0001-decode-avoid-using-a-static-buffer-in-th_get_pathnam.patch
> create mode 100644 patches/libtar-1.2.20/0002-no_maxpathlen.patch
> create mode 100644 patches/libtar-1.2.20/0003-CVE-2013-4420.patch
> create mode 100644 patches/libtar-1.2.20/0004-Change-th_get_size-macro-to-return-unsigned-int.patch
> create mode 120000 patches/libtar-1.2.20/autogen.sh
> create mode 100644 patches/libtar-1.2.20/series
> create mode 100644 rules/libtar.in
> create mode 100644 rules/libtar.make
>
> diff --git a/patches/libtar-1.2.20/0001-decode-avoid-using-a-static-buffer-in-th_get_pathnam.patch b/patches/libtar-1.2.20/0001-decode-avoid-using-a-static-buffer-in-th_get_pathnam.patch
> new file mode 100644
> index 0000000..7664f1d
> --- /dev/null
> +++ b/patches/libtar-1.2.20/0001-decode-avoid-using-a-static-buffer-in-th_get_pathnam.patch
> @@ -0,0 +1,92 @@
> +From: Kamil Dudka <kdudka@redhat.com>
> +Date: Wed, 23 Oct 2013 13:04:22 +0200
> +Subject: [PATCH] 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.
> +---
> + lib/decode.c | 25 ++++++++++++++++++-------
> + lib/handle.c | 1 +
> + lib/libtar.h | 3 +++
> + 3 files changed, 22 insertions(+), 7 deletions(-)
> +
> +diff --git a/lib/decode.c b/lib/decode.c
> +index c16ea2d..35312be 100644
> +--- a/lib/decode.c
> ++++ b/lib/decode.c
> +@@ -13,6 +13,7 @@
> + #include <internal.h>
> +
> + #include <stdio.h>
> ++#include <stdlib.h>
> + #include <sys/param.h>
> + #include <pwd.h>
> + #include <grp.h>
> +@@ -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;
> + }
> +
> +
> +diff --git a/lib/handle.c b/lib/handle.c
> +index 33a262c..9faf2ed 100644
> +--- 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;
> +diff --git a/lib/libtar.h b/lib/libtar.h
> +index 55f509a..5993cd2 100644
> +--- 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;
> +
> diff --git a/patches/libtar-1.2.20/0002-no_maxpathlen.patch b/patches/libtar-1.2.20/0002-no_maxpathlen.patch
> new file mode 100644
> index 0000000..90a95fb
> --- /dev/null
> +++ b/patches/libtar-1.2.20/0002-no_maxpathlen.patch
> @@ -0,0 +1,487 @@
> +From: unknown author <unknown.author@example.com>
> +Date: Thu, 20 Feb 2014 13:49:38 +0100
> +Subject: [PATCH] no_maxpathlen
> +
> +---
> + compat/basename.c | 32 +++++++++++++++++-----
> + compat/dirname.c | 14 +++++++++-
> + lib/append.c | 21 +++++++++------
> + lib/decode.c | 7 ++---
> + lib/util.c | 38 +++++++++++++++++++-------
> + lib/wrapper.c | 77 ++++++++++++++++++++++++++++++++++++++++++++---------
> + libtar/libtar.c | 19 ++++++++++---
> + 7 files changed, 166 insertions(+), 42 deletions(-)
> +
> +diff --git a/compat/basename.c b/compat/basename.c
> +index 2ac1e13..93c75e6 100644
> +--- a/compat/basename.c
> ++++ b/compat/basename.c
> +@@ -34,13 +34,25 @@ static char rcsid[] = "$OpenBSD: basename.c,v 1.4 1999/05/30 17:10:30 espie Exp
> + #include <errno.h>
> + #include <string.h>
> + #include <sys/param.h>
> ++#include <stdlib.h>
> +
> + 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);
> + }
> +diff --git a/compat/dirname.c b/compat/dirname.c
> +index 986db4a..987b46e 100644
> +--- a/compat/dirname.c
> ++++ b/compat/dirname.c
> +@@ -34,13 +34,25 @@ static char rcsid[] = "$OpenBSD: dirname.c,v 1.4 1999/05/30 17:10:30 espie Exp $
> + #include <errno.h>
> + #include <string.h>
> + #include <sys/param.h>
> ++#include <stdlib.h>
> +
> + 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') {
> +diff --git a/lib/append.c b/lib/append.c
> +index 13e1ace..3628d87 100644
> +--- 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 *realname, const char *savename)
> + 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 *realname, const char *savename)
> + }
> + 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 */
> +diff --git a/lib/decode.c b/lib/decode.c
> +index 35312be..df62bec 100644
> +--- 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);
> + }
> +
> +diff --git a/lib/util.c b/lib/util.c
> +index 31e8315..2c9b0fa 100644
> +--- a/lib/util.c
> ++++ b/lib/util.c
> +@@ -15,6 +15,7 @@
> + #include <stdio.h>
> + #include <sys/param.h>
> + #include <errno.h>
> ++#include <stdlib.h>
> +
> + #ifdef STDC_HEADERS
> + # include <string.h>
> +@@ -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;
> + }
> +
> +diff --git a/lib/wrapper.c b/lib/wrapper.c
> +index 4cd0652..897ee44 100644
> +--- a/lib/wrapper.c
> ++++ b/lib/wrapper.c
> +@@ -16,6 +16,7 @@
> + #include <sys/param.h>
> + #include <dirent.h>
> + #include <errno.h>
> ++#include <stdlib.h>
> +
> + #ifdef STDC_HEADERS
> + # include <string.h>
> +@@ -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, 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);
> ++ }
> + 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, char *savedir)
> + 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, char *savedir)
> + {
> + 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);
> +diff --git a/libtar/libtar.c b/libtar/libtar.c
> +index 9fa92b2..f4967e8 100644
> +--- a/libtar/libtar.c
> ++++ b/libtar/libtar.c
> +@@ -111,8 +111,9 @@ create(char *tarfile, char *rootdir, libtar_list_t *l)
> + {
> + 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, libtar_list_t *l)
> + {
> + 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)
> diff --git a/patches/libtar-1.2.20/0003-CVE-2013-4420.patch b/patches/libtar-1.2.20/0003-CVE-2013-4420.patch
> new file mode 100644
> index 0000000..7adbaed
> --- /dev/null
> +++ b/patches/libtar-1.2.20/0003-CVE-2013-4420.patch
> @@ -0,0 +1,126 @@
> +From: unknown author <unknown.author@example.com>
> +Date: Thu, 20 Feb 2014 13:49:38 +0100
> +Subject: [PATCH] CVE-2013-4420
> +
> +---
> + lib/decode.c | 33 +++++++++++++++++++++++++++++++--
> + lib/extract.c | 8 ++++----
> + lib/internal.h | 1 +
> + lib/output.c | 4 ++--
> + 4 files changed, 38 insertions(+), 8 deletions(-)
> +
> +diff --git a/lib/decode.c b/lib/decode.c
> +index df62bec..0b75be1 100644
> +--- a/lib/decode.c
> ++++ b/lib/decode.c
> +@@ -22,13 +22,42 @@
> + # include <string.h>
> + #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);
> + }
> +
> +
> +diff --git a/lib/extract.c b/lib/extract.c
> +index 36357e7..627e05f 100644
> +--- a/lib/extract.c
> ++++ b/lib/extract.c
> +@@ -298,14 +298,14 @@ tar_extract_hardlink(TAR * t, char *realname)
> + 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 *realname)
> +
> + #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()");
> +diff --git a/lib/internal.h b/lib/internal.h
> +index da7be7f..f05ca4f 100644
> +--- a/lib/internal.h
> ++++ b/lib/internal.h
> +@@ -21,3 +21,4 @@
> + #define TLS_THREAD
> + #endif
> +
> ++char* safer_name_suffix(char const*);
> +diff --git a/lib/output.c b/lib/output.c
> +index a2db929..99421bd 100644
> +--- 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');
> diff --git a/patches/libtar-1.2.20/0004-Change-th_get_size-macro-to-return-unsigned-int.patch b/patches/libtar-1.2.20/0004-Change-th_get_size-macro-to-return-unsigned-int.patch
> new file mode 100644
> index 0000000..8cc3a41
> --- /dev/null
> +++ b/patches/libtar-1.2.20/0004-Change-th_get_size-macro-to-return-unsigned-int.patch
> @@ -0,0 +1,51 @@
> +From: Chris Frey <cdfrey@foursquare.net>
> +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 5993cd2..b3281f7 100644
> +--- a/lib/libtar.h
> ++++ b/lib/libtar.h
> +@@ -183,7 +183,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)
> diff --git a/patches/libtar-1.2.20/autogen.sh b/patches/libtar-1.2.20/autogen.sh
> new file mode 120000
> index 0000000..9f8a4cb
> --- /dev/null
> +++ b/patches/libtar-1.2.20/autogen.sh
> @@ -0,0 +1 @@
> +../autogen.sh
> \ No newline at end of file
> diff --git a/patches/libtar-1.2.20/series b/patches/libtar-1.2.20/series
> new file mode 100644
> index 0000000..2af0ad9
> --- /dev/null
> +++ b/patches/libtar-1.2.20/series
> @@ -0,0 +1,7 @@
> +# generated by git-ptx-patches
> +#tag:base --start-number 1
> +0001-decode-avoid-using-a-static-buffer-in-th_get_pathnam.patch
> +0002-no_maxpathlen.patch
> +0003-CVE-2013-4420.patch
> +0004-Change-th_get_size-macro-to-return-unsigned-int.patch
> +# 8d73710ff3b5b805b75c941056495d29 - git-ptx-patches magic
> diff --git a/rules/libtar.in b/rules/libtar.in
> new file mode 100644
> index 0000000..d8a800d
> --- /dev/null
> +++ b/rules/libtar.in
> @@ -0,0 +1,11 @@
> +## SECTION=system_libraries
> +
> +config LIBTAR
> + tristate
> + prompt "libtar"
> + select ZLIB
> + help
> + libtar is a C library for manipulating POSIX tar files. It handles
> + adding and extracting files to/from a tar archive.
> +
> +# vim: ft=kconfig noet tw=72
> diff --git a/rules/libtar.make b/rules/libtar.make
> new file mode 100644
> index 0000000..2434822
> --- /dev/null
> +++ b/rules/libtar.make
> @@ -0,0 +1,62 @@
> +# -*-makefile-*-
> +#
> +# Copyright (C) 2014 by Alexander Dahl <post@lespocky.de>
> +#
> +# See CREDITS for details about who has contributed to this project.
> +#
> +# For further information about the PTXdist project and license conditions
> +# see the README file.
> +#
> +
> +#
> +# We provide this package
> +#
> +PACKAGES-$(PTXCONF_LIBTAR) += libtar
> +
> +#
> +# Paths and names
> +#
> +LIBTAR_VERSION := 1.2.20
> +LIBTAR_MD5 := dcdcdf8cfbbd3df3862198b0897071b6
> +LIBTAR := libtar-$(LIBTAR_VERSION)
> +LIBTAR_SUFFIX := tar.gz
> +LIBTAR_URL := git://repo.or.cz/libtar.git;tag=v$(LIBTAR_VERSION)
> +LIBTAR_SOURCE := $(SRCDIR)/$(LIBTAR).$(LIBTAR_SUFFIX)
> +LIBTAR_DIR := $(BUILDDIR)/$(LIBTAR)
> +LIBTAR_LICENSE := unknown
> +
> +# ----------------------------------------------------------------------------
> +# Prepare
> +# ----------------------------------------------------------------------------
> +
> +#LIBTAR_CONF_ENV := $(CROSS_ENV)
> +
> +#
> +# autoconf
> +#
> +LIBTAR_CONF_TOOL := autoconf
> +LIBTAR_CONF_OPT := $(CROSS_AUTOCONF_USR) \
> + --disable-encap \
> + --disable-epkg-install \
> + --with-zlib=$(SYSROOT)
> +
> +# ----------------------------------------------------------------------------
> +# Target-Install
> +# ----------------------------------------------------------------------------
> +
> +$(STATEDIR)/libtar.targetinstall:
> + @$(call targetinfo)
> +
> + @$(call install_init, libtar)
> + @$(call install_fixup, libtar,PRIORITY,optional)
> + @$(call install_fixup, libtar,SECTION,base)
> + @$(call install_fixup, libtar,AUTHOR,"Alexander Dahl <post@lespocky.de>")
> + @$(call install_fixup, libtar,DESCRIPTION,missing)
> +
> + @$(call install_lib, libtar, 0, 0, 0644, libtar)
> +
> + @$(call install_finish, libtar)
> +
> + @$(call touch)
> +
> +# vim: ft=make noet
> --
> 1.7.10.4
>
>
> --
> ptxdist mailing list
> ptxdist@pengutronix.de
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
--
ptxdist mailing list
ptxdist@pengutronix.de
prev parent reply other threads:[~2014-03-06 18:14 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-23 13:01 Alexander Dahl
2014-02-26 8:41 ` Alexander Dahl
2014-03-06 17:47 ` Michael Olbrich
2014-03-06 18:14 ` Michael Olbrich [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140306181408.GS32080@pengutronix.de \
--to=m.olbrich@pengutronix.de \
--cc=ptxdist@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox