Thu Apr 24 09:34:06 2014 UTC ()
Pullup ticket #4388 - requested by he
archivers/libarchive: security patch

Revisions pulled up:
- archivers/libarchive/Makefile                                 1.40
- archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c 1.4
- archivers/libarchive/files/libarchive/archive_read_support_format_tar.c 1.4

---
   Module Name:	pkgsrc
   Committed By:	he
   Date:		Thu Apr  3 13:05:15 UTC 2014

   Modified Files:
   	pkgsrc/archivers/libarchive: Makefile
   	pkgsrc/archivers/libarchive/files/libarchive:
   	    archive_read_support_format_iso9660.c
   	    archive_read_support_format_tar.c

   Log Message:
   Apply fixes for CVE-2011-1777 and CVE-2011-1778 (add check for
   buffer overflows in handling iso9660 and tar images), despite
   Joerg telling me I should have better things to spend my time on.

   Fixes pulled from

     https://bugzilla.redhat.com/show_bug.cgi?id=705849

   Bump PKGREVISION.


(tron)
diff -r1.39 -r1.39.2.1 pkgsrc/archivers/libarchive/Makefile
diff -r1.3 -r1.3.34.1 pkgsrc/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c
diff -r1.3 -r1.3.34.1 pkgsrc/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c

cvs diff -r1.39 -r1.39.2.1 pkgsrc/archivers/libarchive/Makefile (expand / switch to context diff)
--- pkgsrc/archivers/libarchive/Makefile 2014/02/12 23:17:32 1.39
+++ pkgsrc/archivers/libarchive/Makefile 2014/04/24 09:34:06 1.39.2.1
@@ -1,14 +1,14 @@
-# $NetBSD: Makefile,v 1.39 2014/02/12 23:17:32 tron Exp $
+# $NetBSD: Makefile,v 1.39.2.1 2014/04/24 09:34:06 tron Exp $
 #
 
 DISTNAME=	libarchive-2.8.4
-PKGREVISION=	3
+PKGREVISION=	4
 CATEGORIES=	archivers
 MASTER_SITES=	# empty
 DISTFILES=	# empty
 
 MAINTAINER=	joerg@NetBSD.org
-HOMEPAGE=	http://code.google.com/p/libarchive/
+HOMEPAGE=	http://www.libarchive.org/
 COMMENT=	Library to read/create different archive formats
 
 GNU_CONFIGURE=	yes

cvs diff -r1.3 -r1.3.34.1 pkgsrc/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c (expand / switch to context diff)
--- pkgsrc/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c 2010/02/20 03:54:09 1.3
+++ pkgsrc/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c 2014/04/24 09:34:06 1.3.34.1
@@ -405,12 +405,12 @@
 static inline void cache_add_to_next_of_parent(struct iso9660 *iso9660,
 		    struct file_info *file);
 static inline struct file_info *cache_get_entry(struct iso9660 *iso9660);
-static void	heap_add_entry(struct heap_queue *heap,
+static int	heap_add_entry(struct archive_read *a, struct heap_queue *heap,
 		    struct file_info *file, uint64_t key);
 static struct file_info *heap_get_entry(struct heap_queue *heap);
 
-#define add_entry(iso9660, file)	\
-	heap_add_entry(&((iso9660)->pending_files), file, file->offset)
+#define add_entry(arch, iso9660, file)	\
+	heap_add_entry(arch, &((iso9660)->pending_files), file, file->offset)
 #define next_entry(iso9660)		\
 	heap_get_entry(&((iso9660)->pending_files))
 
@@ -968,8 +968,9 @@
 			if (child == NULL)
 				return (ARCHIVE_FATAL);
 			if (child->cl_offset)
-				heap_add_entry(&(iso9660->cl_files),
-				    child, child->cl_offset);
+				if (heap_add_entry(a, &(iso9660->cl_files),
+				    child, child->cl_offset) != ARCHIVE_OK)
+					return (ARCHIVE_FATAL);
 			else {
 				if (child->multi_extent || multi != NULL) {
 					struct content *con;
@@ -993,15 +994,19 @@
 					con->next = NULL;
 					*multi->contents.last = con;
 					multi->contents.last = &(con->next);
-					if (multi == child)
-						add_entry(iso9660, child);
-					else {
+					if (multi == child) {
+						if (add_entry(a, iso9660, child)
+						    != ARCHIVE_OK)
+							return (ARCHIVE_FATAL);
+					} else {
 						multi->size += child->size;
 						if (!child->multi_extent)
 							multi = NULL;
 					}
 				} else
-					add_entry(iso9660, child);
+					if (add_entry(a, iso9660, child)
+					    != ARCHIVE_OK)
+						return (ARCHIVE_FATAL);
 			}
 		}
 	}
@@ -1014,7 +1019,8 @@
 }
 
 static int
-relocate_dir(struct iso9660 *iso9660, struct file_info *file)
+relocate_dir(struct archive_read *a, struct iso9660 *iso9660,
+	struct file_info *file)
 {
 	struct file_info *re;
 
@@ -1036,7 +1042,9 @@
 		return (1);
 	} else
 		/* This case is wrong pattern. */
-		heap_add_entry(&(iso9660->re_dirs), re, re->offset);
+		if (heap_add_entry(a, &(iso9660->re_dirs), re, re->offset)
+		    != ARCHIVE_OK)
+			return (ARCHIVE_FATAL);
 	return (0);
 }
 
@@ -1063,20 +1071,23 @@
 		     strcmp(file->name.s, ".rr_moved") == 0)) {
 			iso9660->rr_moved = file;
 		} else if (file->re)
-			heap_add_entry(&(iso9660->re_dirs), file,
-			    file->offset);
+			if (heap_add_entry(a, &(iso9660->re_dirs), file,
+			    file->offset) != ARCHIVE_OK)
+				return (ARCHIVE_FATAL);
 		else
 			cache_add_entry(iso9660, file);
 	}
 	if (file != NULL)
-		add_entry(iso9660, file);
+		if (add_entry(a, iso9660, file) != ARCHIVE_OK)
+			return (ARCHIVE_FATAL);
 
 	if (iso9660->rr_moved != NULL) {
 		/*
 		 * Relocate directory which rr_moved has.
 		 */
 		while ((file = heap_get_entry(&(iso9660->cl_files))) != NULL)
-			relocate_dir(iso9660, file);
+			if (relocate_dir(a, iso9660, file) != ARCHIVE_OK)
+				return ARCHIVE_FATAL;
 
 		/* If rr_moved directory still has children,
 		 * Add rr_moved into pending_files to show
@@ -1192,7 +1203,8 @@
 			iso9660->seenJoliet = seenJoliet;
 		}
 		/* Store the root directory in the pending list. */
-		add_entry(iso9660, file);
+		if (add_entry(a, iso9660, file) != ARCHIVE_OK)
+			return (ARCHIVE_FATAL);
 		if (iso9660->seenRockridge) {
 			a->archive.archive_format =
 			    ARCHIVE_FORMAT_ISO9660_ROCKRIDGE;
@@ -2619,8 +2631,9 @@
 	return (file);
 }
 
-static void
-heap_add_entry(struct heap_queue *heap, struct file_info *file, uint64_t key)
+static int
+heap_add_entry(struct archive_read *a, struct heap_queue *heap,
+	struct file_info *file, uint64_t key)
 {
 	uint64_t file_key, parent_key;
 	int hole, parent;
@@ -2633,12 +2646,18 @@
 		if (heap->allocated < 1024)
 			new_size = 1024;
 		/* Overflow might keep us from growing the list. */
-		if (new_size <= heap->allocated)
-			__archive_errx(1, "Out of memory");
+		if (new_size <= heap->allocated) {
+			archive_set_error(&a->archive,
+			    ENOMEM, "Out of memory");
+			return (ARCHIVE_FATAL);
+		}
 		new_pending_files = (struct file_info **)
 		    malloc(new_size * sizeof(new_pending_files[0]));
-		if (new_pending_files == NULL)
-			__archive_errx(1, "Out of memory");
+		if (new_pending_files == NULL) {
+			archive_set_error(&a->archive,
+			    ENOMEM, "Out of memory");
+			return (ARCHIVE_FATAL);
+		}
 		memcpy(new_pending_files, heap->files,
 		    heap->allocated * sizeof(new_pending_files[0]));
 		if (heap->files != NULL)
@@ -2665,6 +2684,8 @@
 		hole = parent;
 	}
 	heap->files[0] = file;
+
+	return (ARCHIVE_OK);
 }
 
 static struct file_info *

cvs diff -r1.3 -r1.3.34.1 pkgsrc/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c (expand / switch to context diff)
--- pkgsrc/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c 2010/02/20 03:54:09 1.3
+++ pkgsrc/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c 2014/04/24 09:34:06 1.3.34.1
@@ -175,14 +175,15 @@
 static ssize_t	UTF8_mbrtowc(wchar_t *pwc, const char *s, size_t n);
 static int	archive_block_is_null(const unsigned char *p);
 static char	*base64_decode(const char *, size_t, size_t *);
-static void	 gnu_add_sparse_entry(struct tar *,
+static int	gnu_add_sparse_entry(struct archive_read *, struct tar *,
 		    off_t offset, off_t remaining);
 static void	gnu_clear_sparse_list(struct tar *);
 static int	gnu_sparse_old_read(struct archive_read *, struct tar *,
 		    const struct archive_entry_header_gnutar *header);
-static void	gnu_sparse_old_parse(struct tar *,
+static int	gnu_sparse_old_parse(struct archive_read *, struct tar *,
 		    const struct gnu_sparse *sparse, int length);
-static int	gnu_sparse_01_parse(struct tar *, const char *);
+static int	gnu_sparse_01_parse(struct archive_read *, struct tar *,
+		    const char *);
 static ssize_t	gnu_sparse_10_read(struct archive_read *, struct tar *);
 static int	header_Solaris_ACL(struct archive_read *,  struct tar *,
 		    struct archive_entry *, const void *);
@@ -212,8 +213,8 @@
 static int	archive_read_format_tar_read_header(struct archive_read *,
 		    struct archive_entry *);
 static int	checksum(struct archive_read *, const void *);
-static int 	pax_attribute(struct tar *, struct archive_entry *,
-		    char *key, char *value);
+static int 	pax_attribute(struct archive_read *, struct tar *,
+		    struct archive_entry *, char *key, char *value);
 static int 	pax_header(struct archive_read *, struct tar *,
 		    struct archive_entry *, char *attr);
 static void	pax_time(const char *, int64_t *sec, long *nanos);
@@ -419,7 +420,9 @@
 	 * a single block.
 	 */
 	if (tar->sparse_list == NULL)
-		gnu_add_sparse_entry(tar, 0, tar->entry_bytes_remaining);
+		if (gnu_add_sparse_entry(a, tar, 0, tar->entry_bytes_remaining)
+		    != ARCHIVE_OK)
+			return (ARCHIVE_FATAL);
 
 	if (r == ARCHIVE_OK) {
 		/*
@@ -1269,7 +1272,7 @@
 		value = p + 1;
 
 		/* Identify this attribute and set it in the entry. */
-		err2 = pax_attribute(tar, entry, key, value);
+		err2 = pax_attribute(a, tar, entry, key, value);
 		err = err_combine(err, err2);
 
 		/* Skip to next line */
@@ -1395,8 +1398,8 @@
  * any of them look useful.
  */
 static int
-pax_attribute(struct tar *tar, struct archive_entry *entry,
-    char *key, char *value)
+pax_attribute(struct archive_read *a, struct tar *tar,
+	struct archive_entry *entry, char *key, char *value)
 {
 	int64_t s;
 	long n;
@@ -1414,8 +1417,10 @@
 		if (strcmp(key, "GNU.sparse.offset") == 0) {
 			tar->sparse_offset = tar_atol10(value, strlen(value));
 			if (tar->sparse_numbytes != -1) {
-				gnu_add_sparse_entry(tar,
-				    tar->sparse_offset, tar->sparse_numbytes);
+				if (gnu_add_sparse_entry(a, tar,
+				    tar->sparse_offset, tar->sparse_numbytes)
+				    != ARCHIVE_OK)
+					return (ARCHIVE_FATAL);
 				tar->sparse_offset = -1;
 				tar->sparse_numbytes = -1;
 			}
@@ -1423,8 +1428,10 @@
 		if (strcmp(key, "GNU.sparse.numbytes") == 0) {
 			tar->sparse_numbytes = tar_atol10(value, strlen(value));
 			if (tar->sparse_numbytes != -1) {
-				gnu_add_sparse_entry(tar,
-				    tar->sparse_offset, tar->sparse_numbytes);
+				if (gnu_add_sparse_entry(a, tar,
+				    tar->sparse_offset, tar->sparse_numbytes)
+				    != ARCHIVE_OK)
+					return (ARCHIVE_FATAL);
 				tar->sparse_offset = -1;
 				tar->sparse_numbytes = -1;
 			}
@@ -1438,7 +1445,7 @@
 		if (strcmp(key, "GNU.sparse.map") == 0) {
 			tar->sparse_gnu_major = 0;
 			tar->sparse_gnu_minor = 1;
-			if (gnu_sparse_01_parse(tar, value) != ARCHIVE_OK)
+			if (gnu_sparse_01_parse(a, tar, value) != ARCHIVE_OK)
 				return (ARCHIVE_WARN);
 		}
 
@@ -1716,7 +1723,8 @@
 	}
 
 	if (header->sparse[0].offset[0] != 0) {
-		gnu_sparse_old_read(a, tar, header);
+		if (gnu_sparse_old_read(a, tar, header) != ARCHIVE_OK)
+			return (ARCHIVE_FATAL);
 	} else {
 		if (header->isextended[0] != 0) {
 			/* XXX WTF? XXX */
@@ -1726,14 +1734,17 @@
 	return (0);
 }
 
-static void
-gnu_add_sparse_entry(struct tar *tar, off_t offset, off_t remaining)
+static int
+gnu_add_sparse_entry(struct archive_read *a, struct tar *tar, off_t offset,
+	off_t remaining)
 {
 	struct sparse_block *p;
 
 	p = (struct sparse_block *)malloc(sizeof(*p));
-	if (p == NULL)
-		__archive_errx(1, "Out of memory");
+	if (p == NULL) {
+		archive_set_error(&a->archive, ENOMEM, "Out of memory");
+		return (ARCHIVE_FATAL);
+	}
 	memset(p, 0, sizeof(*p));
 	if (tar->sparse_last != NULL)
 		tar->sparse_last->next = p;
@@ -1742,6 +1753,7 @@
 	tar->sparse_last = p;
 	p->offset = offset;
 	p->remaining = remaining;
+	return (ARCHIVE_OK);
 }
 
 static void
@@ -1782,7 +1794,8 @@
 	};
 	const struct extended *ext;
 
-	gnu_sparse_old_parse(tar, header->sparse, 4);
+	if (gnu_sparse_old_parse(a, tar, header->sparse, 4) != ARCHIVE_OK)
+		return (ARCHIVE_FATAL);
 	if (header->isextended[0] == 0)
 		return (ARCHIVE_OK);
 
@@ -1798,24 +1811,28 @@
 		}
 		__archive_read_consume(a, 512);
 		ext = (const struct extended *)data;
-		gnu_sparse_old_parse(tar, ext->sparse, 21);
+		if (gnu_sparse_old_parse(a, tar, ext->sparse, 21) != ARCHIVE_OK)
+			return (ARCHIVE_FATAL);
 	} while (ext->isextended[0] != 0);
 	if (tar->sparse_list != NULL)
 		tar->entry_offset = tar->sparse_list->offset;
 	return (ARCHIVE_OK);
 }
 
-static void
-gnu_sparse_old_parse(struct tar *tar,
+static int
+gnu_sparse_old_parse(struct archive_read *a, struct tar *tar,
     const struct gnu_sparse *sparse, int length)
 {
 	while (length > 0 && sparse->offset[0] != 0) {
-		gnu_add_sparse_entry(tar,
+		if (gnu_add_sparse_entry(a, tar,
 		    tar_atol(sparse->offset, sizeof(sparse->offset)),
-		    tar_atol(sparse->numbytes, sizeof(sparse->numbytes)));
+		    tar_atol(sparse->numbytes, sizeof(sparse->numbytes)))
+		    != ARCHIVE_OK)
+			return (ARCHIVE_FATAL);
 		sparse++;
 		length--;
 	}
+	return (ARCHIVE_OK);
 }
 
 /*
@@ -1845,7 +1862,7 @@
  */
 
 static int
-gnu_sparse_01_parse(struct tar *tar, const char *p)
+gnu_sparse_01_parse(struct archive_read *a, struct tar *tar, const char *p)
 {
 	const char *e;
 	off_t offset = -1, size = -1;
@@ -1865,7 +1882,9 @@
 			size = tar_atol10(p, e - p);
 			if (size < 0)
 				return (ARCHIVE_WARN);
-			gnu_add_sparse_entry(tar, offset, size);
+			if (gnu_add_sparse_entry(a, tar, offset, size)
+			    != ARCHIVE_OK)
+				return (ARCHIVE_FATAL);
 			offset = -1;
 		}
 		if (*e == '\0')
@@ -1969,7 +1988,8 @@
 		if (size < 0)
 			return (ARCHIVE_FATAL);
 		/* Add a new sparse entry. */
-		gnu_add_sparse_entry(tar, offset, size);
+		if (gnu_add_sparse_entry(a, tar, offset, size) != ARCHIVE_OK)
+			return (ARCHIVE_FATAL);
 	}
 	/* Skip rest of block... */
 	bytes_read = tar->entry_bytes_remaining - remaining;