jwakely / rpms / binutils

Forked from rpms/binutils 2 years ago
Clone
Blob Blame History Raw
diff -cpr ../binutils-2.24.orig/bfd/archive.c ./bfd/archive.c
*** ../binutils-2.24.orig/bfd/archive.c	2014-11-13 11:08:46.720741346 +0000
--- ./bfd/archive.c	2014-11-13 11:12:38.908876606 +0000
*************** _bfd_slurp_extended_name_table (bfd *abf
*** 1299,1304 ****
--- 1299,1306 ----
  	{
  	byebye:
  	  free (namedata);
+ 	  bfd_ardata (abfd)->extended_names = NULL;
+ 	  bfd_ardata (abfd)->extended_names_size = 0;
  	  return FALSE;
  	}
  
diff -cpr ../binutils-2.24.orig/binutils/ar.c ./binutils/ar.c
*** ../binutils-2.24.orig/binutils/ar.c	2014-11-13 11:08:46.808741776 +0000
--- ./binutils/ar.c	2014-11-13 11:10:10.510151199 +0000
*************** extract_file (bfd *abfd)
*** 1031,1036 ****
--- 1031,1045 ----
    bfd_size_type size;
    struct stat buf;
  
+   /* PR binutils/17533: Do not allow directory traversal
+      outside of the current directory tree.  */
+   if (! is_valid_archive_path (bfd_get_filename (abfd)))
+     {
+       non_fatal (_("illegal pathname found in archive member: %s"),
+ 		 bfd_get_filename (abfd));
+       return;
+     }
+ 
    if (bfd_stat_arch_elt (abfd, &buf) != 0)
      /* xgettext:c-format */
      fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
Only in ./binutils: ar.c.orig
diff -cpr ../binutils-2.24.orig/binutils/bucomm.c ./binutils/bucomm.c
*** ../binutils-2.24.orig/binutils/bucomm.c	2014-11-13 11:08:46.791741693 +0000
--- ./binutils/bucomm.c	2014-11-13 11:10:10.511151188 +0000
*************** bfd_get_archive_filename (const bfd *abf
*** 624,626 ****
--- 624,652 ----
  	   bfd_get_filename (abfd));
    return buf;
  }
+ 
+ /* Returns TRUE iff PATHNAME, a filename of an archive member,
+    is valid for writing.  For security reasons absolute paths
+    and paths containing /../ are not allowed.  See PR 17533.  */
+ 
+ bfd_boolean
+ is_valid_archive_path (char const * pathname)
+ {
+   const char * n = pathname;
+ 
+   if (IS_ABSOLUTE_PATH (n))
+     return FALSE;
+ 
+   while (*n)
+     {
+       if (*n == '.' && *++n == '.' && ( ! *++n || IS_DIR_SEPARATOR (*n)))
+ 	return FALSE;
+ 
+       while (*n && ! IS_DIR_SEPARATOR (*n))
+ 	n++;
+       while (IS_DIR_SEPARATOR (*n))
+ 	n++;
+     }
+ 
+   return TRUE;
+ }
diff -cpr ../binutils-2.24.orig/binutils/bucomm.h ./binutils/bucomm.h
*** ../binutils-2.24.orig/binutils/bucomm.h	2014-11-13 11:08:46.798741727 +0000
--- ./binutils/bucomm.h	2014-11-13 11:10:10.511151188 +0000
*************** bfd_vma parse_vma (const char *, const c
*** 58,63 ****
--- 58,65 ----
  
  off_t get_file_size (const char *);
  
+ bfd_boolean is_valid_archive_path (char const *);
+ 
  extern char *program_name;
  
  /* filemode.c */
diff -cpr ../binutils-2.24.orig/binutils/doc/binutils.texi ./binutils/doc/binutils.texi
*** ../binutils-2.24.orig/binutils/doc/binutils.texi	2014-11-13 11:08:46.955742495 +0000
--- ./binutils/doc/binutils.texi	2014-11-13 11:10:10.513151165 +0000
*************** a normal archive.  Instead the elements
*** 234,240 ****
  individually to the second archive.
  
  The paths to the elements of the archive are stored relative to the
! archive itself.
  
  @cindex compatibility, @command{ar}
  @cindex @command{ar} compatibility
--- 234,241 ----
  individually to the second archive.
  
  The paths to the elements of the archive are stored relative to the
! archive itself.  For security reasons absolute paths and paths with a
! @code{/../} component are not allowed.
  
  @cindex compatibility, @command{ar}
  @cindex @command{ar} compatibility
diff -cpr ../binutils-2.24.orig/binutils/objcopy.c ./binutils/objcopy.c
*** ../binutils-2.24.orig/binutils/objcopy.c	2014-11-13 11:08:46.798741727 +0000
--- ./binutils/objcopy.c	2014-11-13 11:10:10.514151156 +0000
*************** copy_archive (bfd *ibfd, bfd *obfd, cons
*** 2182,2187 ****
--- 2182,2197 ----
        bfd_boolean del = TRUE;
        bfd_boolean ok_object;
  
+       /* PR binutils/17533: Do not allow directory traversal
+ 	 outside of the current directory tree by archive members.  */
+       if (! is_valid_archive_path (bfd_get_filename (this_element)))
+ 	{
+ 	  non_fatal (_("illegal pathname found in archive member: %s"),
+ 		     bfd_get_filename (this_element));
+ 	  status = 1;
+ 	  goto cleanup_and_exit;
+ 	}
+ 
        /* Create an output file for this member.  */
        output_name = concat (dir, "/",
  			    bfd_get_filename (this_element), (char *) 0);
*************** copy_archive (bfd *ibfd, bfd *obfd, cons
*** 2191,2198 ****
  	{
  	  output_name = make_tempdir (output_name);
  	  if (output_name == NULL)
! 	    fatal (_("cannot create tempdir for archive copying (error: %s)"),
! 		   strerror (errno));
  
  	  l = (struct name_list *) xmalloc (sizeof (struct name_list));
  	  l->name = output_name;
--- 2201,2212 ----
  	{
  	  output_name = make_tempdir (output_name);
  	  if (output_name == NULL)
! 	    {
! 	      non_fatal (_("cannot create tempdir for archive copying (error: %s)"),
! 			 strerror (errno));
! 	      status = 1;
! 	      goto cleanup_and_exit;
! 	    }
  
  	  l = (struct name_list *) xmalloc (sizeof (struct name_list));
  	  l->name = output_name;
*************** copy_archive (bfd *ibfd, bfd *obfd, cons
*** 2234,2240 ****
  	{
  	  bfd_nonfatal_message (output_name, NULL, NULL, NULL);
  	  status = 1;
! 	  return;
  	}
  
        if (ok_object)
--- 2248,2254 ----
  	{
  	  bfd_nonfatal_message (output_name, NULL, NULL, NULL);
  	  status = 1;
! 	  goto cleanup_and_exit;
  	}
  
        if (ok_object)
*************** copy_archive (bfd *ibfd, bfd *obfd, cons
*** 2295,2301 ****
      {
        status = 1;
        bfd_nonfatal_message (filename, NULL, NULL, NULL);
-       return;
      }
  
    filename = bfd_get_filename (ibfd);
--- 2309,2314 ----
*************** copy_archive (bfd *ibfd, bfd *obfd, cons
*** 2303,2311 ****
      {
        status = 1;
        bfd_nonfatal_message (filename, NULL, NULL, NULL);
-       return;
      }
  
    /* Delete all the files that we opened.  */
    for (l = list; l != NULL; l = l->next)
      {
--- 2316,2324 ----
      {
        status = 1;
        bfd_nonfatal_message (filename, NULL, NULL, NULL);
      }
  
+  cleanup_and_exit:
    /* Delete all the files that we opened.  */
    for (l = list; l != NULL; l = l->next)
      {