* 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');
 |