Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 31 Mar 2015 14:29:27 +0000 (UTC)
From:      Christian Weisgerber <naddy@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r382823 - in head/archivers/gcpio: . files
Message-ID:  <201503311429.t2VETRYL020193@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: naddy
Date: Tue Mar 31 14:29:26 2015
New Revision: 382823
URL: https://svnweb.freebsd.org/changeset/ports/382823
QAT: https://qat.redports.org/buildarchive/r382823/

Log:
  CVE-2014-9112: Heap-based buffer overflow in the process_copy_in
  function allows remote attackers to cause a denial of service via
  a large block value in a cpio archive.
  Fix from a series of upstream commits by Sergey Poznyakoff.
  
  CVE-2015-1197: cpio, when using the --no-absolute-filenames option,
  allows local users to write to arbitrary files via a symlink attack
  on a file in an archive.
  Fix from Vitezslav Cizek after 3.5 years of gestation in the SUSE
  bug tracker.
  
  PR:		198954
  Obtained from:	Debian

Added:
  head/archivers/gcpio/files/patch-src_copyin.c   (contents, props changed)
  head/archivers/gcpio/files/patch-src_extern.h   (contents, props changed)
  head/archivers/gcpio/files/patch-src_global.c   (contents, props changed)
  head/archivers/gcpio/files/patch-src_main.c   (contents, props changed)
  head/archivers/gcpio/files/patch-src_util.c   (contents, props changed)
Modified:
  head/archivers/gcpio/Makefile
  head/archivers/gcpio/files/patch-doc_Makefile.in
  head/archivers/gcpio/files/patch-doc_cpio.1
  head/archivers/gcpio/files/patch-gnu_Makefile.in
  head/archivers/gcpio/files/patch-src_filetypes.h

Modified: head/archivers/gcpio/Makefile
==============================================================================
--- head/archivers/gcpio/Makefile	Tue Mar 31 14:27:40 2015	(r382822)
+++ head/archivers/gcpio/Makefile	Tue Mar 31 14:29:26 2015	(r382823)
@@ -2,7 +2,7 @@
 
 PORTNAME=	cpio
 PORTVERSION=	2.11
-PORTREVISION=	2
+PORTREVISION=	3
 CATEGORIES=	archivers
 MASTER_SITES=	${MASTER_SITE_GNU}
 MASTER_SITE_SUBDIR=	${PORTNAME}

Modified: head/archivers/gcpio/files/patch-doc_Makefile.in
==============================================================================
--- head/archivers/gcpio/files/patch-doc_Makefile.in	Tue Mar 31 14:27:40 2015	(r382822)
+++ head/archivers/gcpio/files/patch-doc_Makefile.in	Tue Mar 31 14:29:26 2015	(r382823)
@@ -1,5 +1,5 @@
---- doc/Makefile.in.orig	2010-03-25 22:34:54.000000000 +0100
-+++ doc/Makefile.in	2010-03-25 22:35:08.000000000 +0100
+--- doc/Makefile.in.orig	2010-03-10 13:00:35 UTC
++++ doc/Makefile.in
 @@ -813,7 +813,7 @@ top_build_prefix = @top_build_prefix@
  top_builddir = @top_builddir@
  top_srcdir = @top_srcdir@

Modified: head/archivers/gcpio/files/patch-doc_cpio.1
==============================================================================
--- head/archivers/gcpio/files/patch-doc_cpio.1	Tue Mar 31 14:27:40 2015	(r382822)
+++ head/archivers/gcpio/files/patch-doc_cpio.1	Tue Mar 31 14:29:26 2015	(r382823)
@@ -1,8 +1,7 @@
---- doc/cpio.1.orig	2009-02-14 19:15:50.000000000 +0100
-+++ doc/cpio.1	2010-03-25 22:35:50.000000000 +0100
+--- doc/cpio.1.orig	2009-02-14 18:15:50 UTC
++++ doc/cpio.1
 @@ -1,8 +1,8 @@
--.TH CPIO 1L \" -*- nroff -*-
-+.TH GCPIO 1L \" -*- nroff -*-
+ .TH CPIO 1L \" -*- nroff -*-
  .SH NAME
 -cpio \- copy files to and from archives
 +gcpio \- copy files to and from archives
@@ -21,8 +20,11 @@
  {\-i|\-\-extract} [\-bcdfmnrtsuvBSV] [\-C bytes] [\-E file] [\-H format]
  [\-M message] [\-R [user][:.][group]] [\-I [[user@]host:]archive]
  [\-F [[user@]host:]archive] [\-\-file=[[user@]host:]archive]
-@@ -24,7 +24,7 @@ cpio \- copy files to and from archives
+@@ -22,9 +22,10 @@ cpio \- copy files to and from archives
+ [\-\-owner=[user][:.][group]] [\-\-no-preserve-owner] [\-\-message=message]
+ [\-\-force\-local] [\-\-no\-absolute\-filenames] [\-\-sparse]
  [\-\-only\-verify\-crc] [\-\-to\-stdout] [\-\-quiet] [\-\-rsh-command=command]
++[\-\-extract\-over\-symlinks]
  [\-\-help] [\-\-version] [pattern...] [< archive]
  
 -.B cpio

Modified: head/archivers/gcpio/files/patch-gnu_Makefile.in
==============================================================================
--- head/archivers/gcpio/files/patch-gnu_Makefile.in	Tue Mar 31 14:27:40 2015	(r382822)
+++ head/archivers/gcpio/files/patch-gnu_Makefile.in	Tue Mar 31 14:29:26 2015	(r382823)
@@ -1,5 +1,5 @@
---- gnu/Makefile.in.orig	2010-03-25 22:13:33.000000000 +0100
-+++ gnu/Makefile.in	2010-03-25 22:14:21.000000000 +0100
+--- gnu/Makefile.in.orig	2010-03-10 13:00:36 UTC
++++ gnu/Makefile.in
 @@ -1720,7 +1720,7 @@ inttypes.h: inttypes.in.h $(WARN_ON_USE_
  # avoid installing it.
  

Added: head/archivers/gcpio/files/patch-src_copyin.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/archivers/gcpio/files/patch-src_copyin.c	Tue Mar 31 14:29:26 2015	(r382823)
@@ -0,0 +1,184 @@
+--- src/copyin.c.orig	2010-02-15 10:02:23 UTC
++++ src/copyin.c
+@@ -124,10 +124,30 @@ tape_skip_padding (int in_file_des, off_
+   if (pad != 0)
+     tape_toss_input (in_file_des, pad);
+ }
+-
++
++static char *
++get_link_name (struct cpio_file_stat *file_hdr, int in_file_des)
++{
++  char *link_name;
++  
++  if (file_hdr->c_filesize < 0 || file_hdr->c_filesize > SIZE_MAX-1)
++    {
++      error (0, 0, _("%s: stored filename length is out of range"),
++	     file_hdr->c_name);
++      link_name = NULL;
++    }
++  else
++    {
++      link_name = xmalloc (file_hdr->c_filesize + 1);
++      tape_buffered_read (link_name, in_file_des, file_hdr->c_filesize);
++      link_name[file_hdr->c_filesize] = '\0';
++      tape_skip_padding (in_file_des, file_hdr->c_filesize);
++    }
++  return link_name;
++}
+ 
+ static void
+-list_file(struct cpio_file_stat* file_hdr, int in_file_des)
++list_file (struct cpio_file_stat* file_hdr, int in_file_des)
+ {
+   if (verbose_flag)
+     {
+@@ -136,21 +156,16 @@ list_file(struct cpio_file_stat* file_hd
+ 	{
+ 	  if (archive_format != arf_tar && archive_format != arf_ustar)
+ 	    {
+-	      char *link_name = NULL;	/* Name of hard and symbolic links.  */
+-
+-	      link_name = (char *) xmalloc ((unsigned int) file_hdr->c_filesize + 1);
+-	      link_name[file_hdr->c_filesize] = '\0';
+-	      tape_buffered_read (link_name, in_file_des, file_hdr->c_filesize);
+-	      long_format (file_hdr, link_name);
+-	      free (link_name);
+-	      tape_skip_padding (in_file_des, file_hdr->c_filesize);
+-	      return;
++	      char *link_name = get_link_name (file_hdr, in_file_des);
++	      if (link_name)
++		{
++		  long_format (file_hdr, link_name);
++		  free (link_name);
++		}
+ 	    }
+ 	  else
+-	    {
+-	      long_format (file_hdr, file_hdr->c_tar_linkname);
+-	      return;
+-	    }
++	    long_format (file_hdr, file_hdr->c_tar_linkname);
++	  return;
+ 	}
+       else
+ #endif
+@@ -640,7 +655,7 @@ copyin_device (struct cpio_file_stat* fi
+ }
+ 
+ static void
+-copyin_link(struct cpio_file_stat *file_hdr, int in_file_des)
++copyin_link (struct cpio_file_stat *file_hdr, int in_file_des)
+ {
+   char *link_name = NULL;	/* Name of hard and symbolic links.  */
+   int res;			/* Result of various function calls.  */
+@@ -650,10 +665,9 @@ copyin_link(struct cpio_file_stat *file_
+ 
+   if (archive_format != arf_tar && archive_format != arf_ustar)
+     {
+-      link_name = (char *) xmalloc ((unsigned int) file_hdr->c_filesize + 1);
+-      link_name[file_hdr->c_filesize] = '\0';
+-      tape_buffered_read (link_name, in_file_des, file_hdr->c_filesize);
+-      tape_skip_padding (in_file_des, file_hdr->c_filesize);
++      link_name = get_link_name (file_hdr, in_file_des);
++      if (!link_name)
++	return;
+     }
+   else
+     {
+@@ -686,6 +700,51 @@ copyin_link(struct cpio_file_stat *file_
+   free (link_name);
+ }
+ 
++
++static int
++path_contains_symlink(char *path)
++{
++  struct stat st;
++  char *slash;
++  char *nextslash;
++
++  /* we got NULL pointer or empty string */
++  if (!path || !*path) {
++    return false;
++  }
++
++  slash = path;
++
++  while ((nextslash = strchr(slash + 1, '/')) != NULL) {
++    slash = nextslash;
++    *slash = '\0';
++
++    if (lstat(path, &st) != 0) {
++      if (errno == ELOOP) {
++        /* ELOOP - too many symlinks */
++        *slash = '/';
++        return true;
++      } else if (errno == ENOMEM) {
++        /* No memory for lstat - terminate */
++        xalloc_die();
++      } else {
++        /* cannot lstat path - give up */
++        *slash = '/';
++        return false;
++      }
++    }
++
++    if (S_ISLNK(st.st_mode)) {
++      *slash = '/';
++      return true;
++    }
++
++    *slash = '/';
++  }
++
++  return false;
++}
++
+ static void
+ copyin_file (struct cpio_file_stat *file_hdr, int in_file_des)
+ {
+@@ -1005,7 +1064,7 @@ read_in_header (struct cpio_file_stat *f
+ 
+   file_hdr->c_tar_linkname = NULL;
+ 
+-  tape_buffered_read (magic.str, in_des, 6L);
++  tape_buffered_read (magic.str, in_des, sizeof (magic.str));
+   while (1)
+     {
+       if (append_flag)
+@@ -1050,8 +1109,8 @@ read_in_header (struct cpio_file_stat *f
+ 	  break;
+ 	}
+       bytes_skipped++;
+-      memmove (magic.str, magic.str + 1, 5);
+-      tape_buffered_read (magic.str, in_des, 1L);
++      memmove (magic.str, magic.str + 1, sizeof (magic.str) - 1);
++      tape_buffered_read (magic.str + sizeof (magic.str) - 1, in_des, 1L);
+     }
+ }
+ 
+@@ -1457,6 +1516,23 @@ process_copy_in ()
+ 	{
+ 	  /* Copy the input file into the directory structure.  */
+ 
++          /* Can we write files over symlinks? */
++          if (!extract_over_symlinks)
++            {
++              if (path_contains_symlink(file_hdr.c_name))
++                {
++                  /* skip the file */
++                  /*
++                  fprintf(stderr, "Can't write over symlinks. Skipping %s\n", file_hdr.c_name);
++                  tape_toss_input (in_file_des, file_hdr.c_filesize);
++                  tape_skip_padding (in_file_des, file_hdr.c_filesize);
++                  continue;
++                  */
++                  /* terminate */
++	          error (1, 0, _("Can't write over symlinks: %s\n"), file_hdr.c_name);
++                }
++            }
++
+ 	  /* Do we need to rename the file? */
+ 	  if (rename_flag || rename_batch_file)
+ 	    {

Added: head/archivers/gcpio/files/patch-src_extern.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/archivers/gcpio/files/patch-src_extern.h	Tue Mar 31 14:29:26 2015	(r382823)
@@ -0,0 +1,10 @@
+--- src/extern.h.orig	2010-02-15 10:02:23 UTC
++++ src/extern.h
+@@ -95,6 +95,7 @@ extern char input_is_special;
+ extern char output_is_special;
+ extern char input_is_seekable;
+ extern char output_is_seekable;
++extern bool extract_over_symlinks;
+ extern int (*xstat) ();
+ extern void (*copy_function) ();
+ 

Modified: head/archivers/gcpio/files/patch-src_filetypes.h
==============================================================================
--- head/archivers/gcpio/files/patch-src_filetypes.h	Tue Mar 31 14:27:40 2015	(r382822)
+++ head/archivers/gcpio/files/patch-src_filetypes.h	Tue Mar 31 14:29:26 2015	(r382823)
@@ -1,5 +1,5 @@
---- src/filetypes.h.orig	2010-04-19 22:01:16.000000000 +0200
-+++ src/filetypes.h	2010-04-19 22:04:16.000000000 +0200
+--- src/filetypes.h.orig	2010-02-12 10:19:23 UTC
++++ src/filetypes.h
 @@ -81,5 +81,9 @@
  #ifndef S_ISLNK
  #define lstat stat

Added: head/archivers/gcpio/files/patch-src_global.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/archivers/gcpio/files/patch-src_global.c	Tue Mar 31 14:29:26 2015	(r382823)
@@ -0,0 +1,12 @@
+--- src/global.c.orig	2010-02-12 10:19:23 UTC
++++ src/global.c
+@@ -187,6 +187,9 @@ bool to_stdout_option = false;
+ /* The name this program was run with.  */
+ char *program_name;
+ 
++/* Extract files over symbolic links */
++bool extract_over_symlinks;
++
+ /* A pointer to either lstat or stat, depending on whether
+    dereferencing of symlinks is done for input files.  */
+ int (*xstat) ();

Added: head/archivers/gcpio/files/patch-src_main.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/archivers/gcpio/files/patch-src_main.c	Tue Mar 31 14:29:26 2015	(r382823)
@@ -0,0 +1,32 @@
+--- src/main.c.orig	2010-02-12 11:35:09 UTC
++++ src/main.c
+@@ -57,7 +57,8 @@ enum cpio_options {
+   FORCE_LOCAL_OPTION,            
+   DEBUG_OPTION,                  
+   BLOCK_SIZE_OPTION,             
+-  TO_STDOUT_OPTION
++  TO_STDOUT_OPTION,
++  EXTRACT_OVER_SYMLINKS
+ };
+ 
+ const char *program_authors[] =
+@@ -222,6 +223,8 @@ static struct argp_option options[] = {
+    N_("Create leading directories where needed"), GRID+1 },
+   {"no-preserve-owner", NO_PRESERVE_OWNER_OPTION, 0, 0,
+    N_("Do not change the ownership of the files"), GRID+1 },
++  {"extract-over-symlinks", EXTRACT_OVER_SYMLINKS, 0, 0,
++   N_("Force writing over symbolic links"), GRID+1 },
+   {"unconditional", 'u', NULL, 0,
+    N_("Replace all files unconditionally"), GRID+1 },
+   {"sparse", SPARSE_OPTION, NULL, 0,
+@@ -412,6 +415,10 @@ crc newc odc bin ustar tar (all-caps als
+       no_chown_flag = true;
+       break;
+ 
++    case EXTRACT_OVER_SYMLINKS:		        /* --extract-over-symlinks */
++      extract_over_symlinks = true;
++      break;
++
+     case 'o':		/* Copy-out mode.  */
+       if (copy_function != 0)
+ 	error (PAXEXIT_FAILURE, 0, _("Mode already defined"));

Added: head/archivers/gcpio/files/patch-src_util.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/archivers/gcpio/files/patch-src_util.c	Tue Mar 31 14:29:26 2015	(r382823)
@@ -0,0 +1,14 @@
+--- src/util.c.orig	2010-03-10 10:22:30 UTC
++++ src/util.c
+@@ -206,10 +206,7 @@ tape_fill_input_buffer (int in_des, int 
+   if (input_size < 0)
+     error (1, errno, _("read error"));
+   if (input_size == 0)
+-    {
+-      error (0, 0, _("premature end of file"));
+-      exit (1);
+-    }
++    error (PAXEXIT_FAILURE, 0, _("premature end of file"));
+   input_bytes += input_size;
+ }
+ 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201503311429.t2VETRYL020193>