* gnu/packages/compression.scm (libtar)[source]: Add patch.
* gnu/packages/patches/libtar-CVE-2013-4420.patch: New variable.
* gnu/local.mk (dist_patch_DATA): Add it.
This is a follow-up to 89d80159b1.
		
	
			
		
			
				
	
	
		
			118 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			118 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
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
 | 
						|
@@ -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 <libtar.h>
 | 
						|
 
 | 
						|
+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');
 |