diff options
author | he <he@pkgsrc.org> | 2014-04-03 13:05:14 +0000 |
---|---|---|
committer | he <he@pkgsrc.org> | 2014-04-03 13:05:14 +0000 |
commit | afea5d1b06a07625562b713d4a433379f60ff531 (patch) | |
tree | 098d0c85151428d596bed4fe4e1e3846ed9092df /archivers | |
parent | c9ea67c5d3491a46765da090f8f6800c263bbbad (diff) | |
download | pkgsrc-afea5d1b06a07625562b713d4a433379f60ff531.tar.gz |
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.
Diffstat (limited to 'archivers')
3 files changed, 94 insertions, 53 deletions
diff --git a/archivers/libarchive/Makefile b/archivers/libarchive/Makefile index 321ae4db944..09152775477 100644 --- a/archivers/libarchive/Makefile +++ b/archivers/libarchive/Makefile @@ -1,14 +1,14 @@ -# $NetBSD: Makefile,v 1.39 2014/02/12 23:17:32 tron Exp $ +# $NetBSD: Makefile,v 1.40 2014/04/03 13:05:14 he 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 diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c b/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c index 0c640c88e86..65988ca4fd4 100644 --- a/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c +++ b/archivers/libarchive/files/libarchive/archive_read_support_format_iso9660.c @@ -405,12 +405,12 @@ static inline void cache_add_entry(struct iso9660 *iso9660, 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 @@ read_children(struct archive_read *a, struct file_info *parent) 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 @@ read_children(struct archive_read *a, struct file_info *parent) 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 @@ read_children(struct archive_read *a, struct file_info *parent) } 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 @@ relocate_dir(struct iso9660 *iso9660, struct file_info *file) 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 @@ read_entries(struct archive_read *a) 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 @@ archive_read_format_iso9660_read_header(struct archive_read *a, 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 @@ cache_get_entry(struct iso9660 *iso9660) 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 @@ heap_add_entry(struct heap_queue *heap, struct file_info *file, uint64_t key) 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 @@ heap_add_entry(struct heap_queue *heap, struct file_info *file, uint64_t key) hole = parent; } heap->files[0] = file; + + return (ARCHIVE_OK); } static struct file_info * diff --git a/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c b/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c index dae13dc6e00..d06b18d8da1 100644 --- a/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c +++ b/archivers/libarchive/files/libarchive/archive_read_support_format_tar.c @@ -175,14 +175,15 @@ struct tar { 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_skip(struct archive_read *a); 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 @@ archive_read_format_tar_read_header(struct archive_read *a, * 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 @@ pax_header(struct archive_read *a, struct tar *tar, 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 @@ pax_attribute_xattr(struct archive_entry *entry, * 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 @@ pax_attribute(struct tar *tar, struct archive_entry *entry, 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 @@ pax_attribute(struct tar *tar, struct archive_entry *entry, 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 @@ pax_attribute(struct tar *tar, struct archive_entry *entry, 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 @@ header_gnutar(struct archive_read *a, struct tar *tar, } 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 @@ header_gnutar(struct archive_read *a, struct tar *tar, 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 @@ gnu_add_sparse_entry(struct tar *tar, off_t offset, off_t remaining) tar->sparse_last = p; p->offset = offset; p->remaining = remaining; + return (ARCHIVE_OK); } static void @@ -1782,7 +1794,8 @@ gnu_sparse_old_read(struct archive_read *a, struct tar *tar, }; 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 @@ gnu_sparse_old_read(struct archive_read *a, struct tar *tar, } __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 @@ gnu_sparse_old_parse(struct tar *tar, */ 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 @@ gnu_sparse_01_parse(struct tar *tar, const char *p) 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 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar) 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; |