--- Begin Message ---
Package: libarchive
Version: 2.8.5-3
Severity: normal
Tags: patch
User: [email protected]
Usertags: origin-ubuntu precise ubuntu-patch
*** /tmp/tmp_Ru6Y6
In Ubuntu, the attached patch was applied to achieve the following:
* SECURITY UPDATE: arbitrary code execution via iso9660 overflows
- debian/patches/CVE-2011-1777.patch: correctly fail on out of memory
conditions in libarchive/archive_read_support_format_iso9660.c.
- CVE-2011-1777
* SECURITY UPDATE: arbitrary code execution via tar overflows
- debian/patches/CVE-2011-1778.patch: correctly fail on out of memory
conditions in libarchive/archive_read_support_format_tar.c
- CVE-2011-1778
Thanks for considering the patch.
-- System Information:
Debian Release: wheezy/sid
APT prefers oneiric-updates
APT policy: (500, 'oneiric-updates'), (500, 'oneiric-security'), (500,
'oneiric-proposed'), (500, 'oneiric')
Architecture: amd64 (x86_64)
Kernel: Linux 3.0.0-14-generic (SMP w/4 CPU cores)
Locale: LANG=en_CA.UTF-8, LC_CTYPE=en_CA.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
diff -Nru libarchive-2.8.5/debian/changelog libarchive-2.8.5/debian/changelog
diff -Nru libarchive-2.8.5/debian/patches/CVE-2011-1777.patch libarchive-2.8.5/debian/patches/CVE-2011-1777.patch
--- libarchive-2.8.5/debian/patches/CVE-2011-1777.patch 1969-12-31 19:00:00.000000000 -0500
+++ libarchive-2.8.5/debian/patches/CVE-2011-1777.patch 2011-12-09 10:37:29.000000000 -0500
@@ -0,0 +1,108 @@
+Description: fix arbitrary code execution via iso9660 overflows
+Origin: backport, http://code.google.com/p/libarchive/source/detail?r=3158
+
+Index: libarchive-2.8.5/libarchive/archive_read_support_format_iso9660.c
+===================================================================
+--- libarchive-2.8.5.orig/libarchive/archive_read_support_format_iso9660.c 2011-12-09 10:36:34.547552016 -0500
++++ libarchive-2.8.5/libarchive/archive_read_support_format_iso9660.c 2011-12-09 10:37:08.643552304 -0500
+@@ -417,12 +417,12 @@
+ static inline void cache_add_entry(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))
+
+@@ -1010,15 +1010,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);
+ }
+ }
+
+@@ -1118,7 +1122,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;
+@@ -2745,8 +2750,8 @@
+ 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;
+@@ -2759,12 +2764,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)
+@@ -2784,13 +2795,15 @@
+ parent_key = heap->files[parent]->key;
+ if (file_key >= parent_key) {
+ heap->files[hole] = file;
+- return;
++ return (ARCHIVE_OK);
+ }
+ // Move parent into hole <==> move hole up tree.
+ heap->files[hole] = heap->files[parent];
+ hole = parent;
+ }
+ heap->files[0] = file;
++
++ return (ARCHIVE_OK);
+ }
+
+ static struct file_info *
diff -Nru libarchive-2.8.5/debian/patches/CVE-2011-1778.patch libarchive-2.8.5/debian/patches/CVE-2011-1778.patch
--- libarchive-2.8.5/debian/patches/CVE-2011-1778.patch 1969-12-31 19:00:00.000000000 -0500
+++ libarchive-2.8.5/debian/patches/CVE-2011-1778.patch 2011-12-09 09:59:48.000000000 -0500
@@ -0,0 +1,217 @@
+Description: fix arbitrary code execution via tar overflows
+Origin: backport, http://code.google.com/p/libarchive/source/detail?r=3160
+
+Index: libarchive-2.8.5/libarchive/archive_read_support_format_tar.c
+===================================================================
+--- libarchive-2.8.5.orig/libarchive/archive_read_support_format_tar.c 2011-12-09 09:51:39.695529263 -0500
++++ libarchive-2.8.5/libarchive/archive_read_support_format_tar.c 2011-12-09 09:51:55.023529391 -0500
+@@ -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;
diff -Nru libarchive-2.8.5/debian/patches/series libarchive-2.8.5/debian/patches/series
--- libarchive-2.8.5/debian/patches/series 2011-09-17 17:28:15.000000000 -0400
+++ libarchive-2.8.5/debian/patches/series 2011-12-09 10:36:27.000000000 -0500
@@ -7,3 +7,5 @@
0007-Patch-from-upstream-rev-2888.patch
0008-Patch-from-upstream-rev-2940.patch
autoreconf.patch
+CVE-2011-1777.patch
+CVE-2011-1778.patch
--- End Message ---