Subject: bin/18593: tar seg fault
To: None <gnats-bugs@gnats.netbsd.org>
From: None <nick@stupid.net>
List: netbsd-bugs
Date: 10/08/2002 22:55:41
>Number:         18593
>Category:       bin
>Synopsis:       tar can be tricked into a seg fault
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Oct 08 22:56:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Nicholas Maniscalco
>Release:        NetBSD 1.6
>Organization:

>Environment:
System: NetBSD anomaly.stupid.net 1.6 NetBSD 1.6 (GENERIC) #0: Sun Sep 29 17:01:32 PDT 2002 fb@anomaly.stupid.net:/usr/src/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:
	tar overflows buffers using strcpy and sprintf.
>How-To-Repeat:
	This may seem awkward, but if you compile and run this program
you'll probably see tar dump core.  Be sure that /netbsd (or some other
reasonably large file) is readable, and that doh.tar can be created in
the cwd.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char **argv, char **envp)
{

  int result = 0;
  char *v[9] = {"tar", "-L", "1", "-cMf", "doh.tar", "-V", NULL, "/netbsd", NULL };
  int len = 100000;

  v[6] = (char*)malloc(sizeof(char) * len);
  v[6][len-1] = '\0';
  memset(v[6], 65, len-1);
  result = execve("/usr/bin/tar", v, envp);
  if(result<0)
    perror("execve");
  return -1;
}

This demonstrates one of the buffer problems.
Please let me know if I left anything out.

>Fix:
Here is a patch

Index: buffer.c
===================================================================
RCS file: /cvsroot/gnusrc/gnu/usr.bin/tar/buffer.c,v
retrieving revision 1.5
diff -r1.5 buffer.c
706c706,708
< 	sprintf (ar_block->header.arch_name, "%s Volume 1", f_volhdr);
---
> 	{
> 	  snprintf (ar_block->header.arch_name, NAMSIZ, "%s Volume 1", f_volhdr);
> 	}
708c710,714
< 	strcpy (ar_block->header.arch_name, f_volhdr);
---
> 	{
> 	  /* could use strlcpy instead */
> 	  strncpy (ar_block->header.arch_name, f_volhdr, NAMSIZ-1);
> 	  ar_block->header.arch_name[NAMSIZ-1] = '\0';
> 	}
791c797,799
< 	  strcpy (real_s_name, save_name);
---
> 	  strncpy (real_s_name, save_name, NAMSIZ-1);
> 	  real_s_name[NAMSIZ-1] = '\0';
> 
991c999,1000
< 	      strcpy (real_s_name, save_name);
---
> 	      strncpy (real_s_name, save_name, NAMSIZ-1);
> 	      real_s_name[NAMSIZ-1] = '\0';
>Release-Note:
>Audit-Trail:
>Unformatted: