Subversion Repositories libtar

Compare Revisions

Ignore whitespace Rev 23 → Rev 24

/trunk/debian/changelog
5,8 → 5,15
* 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.
 
-- Magnus Holmgren <holmgren@debian.org> Thu, 13 Feb 2014 21:20:23 +0100
-- Magnus Holmgren <holmgren@debian.org> Sat, 15 Feb 2014 21:20:03 +0100
 
libtar (1.2.20-1) unstable; urgency=high
 
/trunk/debian/patches/CVE-2013-4420.patch
0,0 → 1,105
Author: Raphael Geissert <geissert@debian.org>
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
@@ -21,13 +21,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);
size_t pathlen =
strlen(t->th_buf.prefix) + strlen(t->th_buf.name) + 2;
@@ -43,12 +72,12 @@ th_get_pathname(TAR *t)
if (t->th_buf.prefix[0] == '\0')
{
- snprintf(t->th_pathname, pathlen, "%.100s", t->th_buf.name);
+ snprintf(t->th_pathname, pathlen, "%.100s", safer_name_suffix(t->th_buf.name));
}
else
{
snprintf(t->th_pathname, pathlen, "%.155s/%.100s",
- t->th_buf.prefix, t->th_buf.name);
+ t->th_buf.prefix, safer_name_suffix(t->th_buf.name));
}
/* will be deallocated in tar_close() */
--- 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*);
/trunk/debian/patches/series
1,2 → 1,3
no_static_buffers.patch
no_maxpathlen.patch
CVE-2013-4420.patch