summaryrefslogtreecommitdiff
path: root/archivers
diff options
context:
space:
mode:
authorlkundrak <lkundrak@pkgsrc.org>2007-07-13 09:26:31 +0000
committerlkundrak <lkundrak@pkgsrc.org>2007-07-13 09:26:31 +0000
commit439c9678a868914b629e763ba2dadd32ab78100e (patch)
tree7474142a3770ab05568b3fe07a7b581b4c91c9d6 /archivers
parent440b684548bc27ca74d32104ab982d0834ca43ac (diff)
downloadpkgsrc-439c9678a868914b629e763ba2dadd32ab78100e.tar.gz
Fix for FreeBSD-SA-07:05.libarchive CVE-2007-3641, CVE-2007-3644 and
CVE-2007-3645. PKGREVISION bump.
Diffstat (limited to 'archivers')
-rw-r--r--archivers/libarchive/Makefile3
-rw-r--r--archivers/libarchive/distinfo3
-rw-r--r--archivers/libarchive/patches/patch-ad230
3 files changed, 234 insertions, 2 deletions
diff --git a/archivers/libarchive/Makefile b/archivers/libarchive/Makefile
index 3aaf343a49b..c77f882fef9 100644
--- a/archivers/libarchive/Makefile
+++ b/archivers/libarchive/Makefile
@@ -1,7 +1,8 @@
-# $NetBSD: Makefile,v 1.16 2006/11/14 13:50:13 joerg Exp $
+# $NetBSD: Makefile,v 1.17 2007/07/13 09:26:31 lkundrak Exp $
#
DISTNAME= libarchive-1.3.1
+PKGREVISION= 1
CATEGORIES= archivers
MASTER_SITES= http://people.freebsd.org/~kientzle/libarchive/src/
diff --git a/archivers/libarchive/distinfo b/archivers/libarchive/distinfo
index d785aed7de3..e3a2deb6b23 100644
--- a/archivers/libarchive/distinfo
+++ b/archivers/libarchive/distinfo
@@ -1,7 +1,8 @@
-$NetBSD: distinfo,v 1.13 2006/11/10 00:29:44 adrianp Exp $
+$NetBSD: distinfo,v 1.14 2007/07/13 09:26:31 lkundrak Exp $
SHA1 (libarchive-1.3.1.tar.gz) = aed6eda15b012adbb88af0f0d76887920ffe7bbf
RMD160 (libarchive-1.3.1.tar.gz) = e518f802d9a50afcfede6dd7cbb4f42b2cbe12a1
Size (libarchive-1.3.1.tar.gz) = 901173 bytes
SHA1 (patch-ab) = 5e92405b0898123d8240f332475d13abe85f8ad3
SHA1 (patch-ac) = 5775e26d19ace2b94c870c0e8de8e6efbe4b5c63
+SHA1 (patch-ad) = ea7a7ae72ca85589830aefae6e6e4f9f4ba45c7a
diff --git a/archivers/libarchive/patches/patch-ad b/archivers/libarchive/patches/patch-ad
new file mode 100644
index 00000000000..ef3080bb4dd
--- /dev/null
+++ b/archivers/libarchive/patches/patch-ad
@@ -0,0 +1,230 @@
+$NetBSD: patch-ad,v 1.1 2007/07/13 09:26:32 lkundrak Exp $
+
+Fix for CVE-2007-3641, CVE-2007-3644 and CVE-2007-3645 from FreeBSD-SA-07:05.libarchive
+
+--- libarchive/archive_read_support_format_tar.c.orig 2006-09-05 08:00:48.000000000 +0200
++++ libarchive/archive_read_support_format_tar.c 2007-07-13 11:35:48.000000000 +0200
+@@ -670,7 +670,13 @@ tar_read_header(struct archive *a, struc
+ }
+ }
+ --tar->header_recursion_depth;
+- return (err);
++ /* We return warnings or success as-is. Anything else is fatal. */
++ if (err == ARCHIVE_WARN || err == ARCHIVE_OK)
++ return (err);
++ if (err == ARCHIVE_EOF)
++ /* EOF when recursively reading a header is bad. */
++ archive_set_error(a, EINVAL, "Damaged tar archive");
++ return (ARCHIVE_FATAL);
+ }
+
+ /*
+@@ -741,32 +747,55 @@ static int
+ header_Solaris_ACL(struct archive *a, struct tar *tar,
+ struct archive_entry *entry, struct stat *st, const void *h)
+ {
+- int err, err2;
+- char *p;
++ const struct archive_entry_header_ustar *header;
++ size_t size;
++ int err;
++ char *acl, *p;
+ wchar_t *wp;
+
++ /*
++ * read_body_to_string adds a NUL terminator, but we need a little
++ * more to make sure that we don't overrun acl_text later.
++ */
++ header = (const struct archive_entry_header_ustar *)h;
++ size = tar_atol(header->size, sizeof(header->size));
+ err = read_body_to_string(a, tar, &(tar->acl_text), h);
+- err2 = tar_read_header(a, tar, entry, st);
+- err = err_combine(err, err2);
+-
+- /* XXX Ensure p doesn't overrun acl_text */
++ if (err != ARCHIVE_OK)
++ return (err);
++ err = tar_read_header(a, tar, entry, st);
++ if ((err != ARCHIVE_OK) && (err != ARCHIVE_WARN))
++ return (err);
+
+ /* Skip leading octal number. */
+ /* XXX TODO: Parse the octal number and sanity-check it. */
+- p = tar->acl_text.s;
+- while (*p != '\0')
++ p = acl = tar->acl_text.s;
++ while (*p != '\0' && p < acl + size)
+ p++;
+ p++;
+
+- wp = malloc((strlen(p) + 1) * sizeof(wchar_t));
+- if (wp != NULL) {
+- utf8_decode(wp, p, strlen(p));
+- err2 = __archive_entry_acl_parse_w(entry, wp,
+- ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+- err = err_combine(err, err2);
+- free(wp);
++ if (p >= acl + size) {
++ archive_set_error(a, ARCHIVE_ERRNO_MISC,
++ "Malformed Solaris ACL attribute");
++ return(ARCHIVE_WARN);
+ }
+
++ /* Skip leading octal number. */
++ size -= (p - acl);
++ acl = p;
++
++ while (*p != '\0' && p < acl + size)
++ p++;
++
++ wp = malloc((p - acl + 1) * sizeof(wchar_t));
++ if (wp == NULL) {
++ archive_set_error(a, ENOMEM,
++ "Can't allocate work buffer for ACL parsing");
++ return (ARCHIVE_FATAL);
++ }
++ utf8_decode(wp, acl, p - acl);
++ err = __archive_entry_acl_parse_w(entry, wp,
++ ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
++ free(wp);
+ return (err);
+ }
+
+@@ -777,15 +806,17 @@ static int
+ header_longlink(struct archive *a, struct tar *tar,
+ struct archive_entry *entry, struct stat *st, const void *h)
+ {
+- int err, err2;
++ int err;
+
+ err = read_body_to_string(a, tar, &(tar->longlink), h);
+- err2 = tar_read_header(a, tar, entry, st);
+- if (err == ARCHIVE_OK && err2 == ARCHIVE_OK) {
+- /* Set symlink if symlink already set, else hardlink. */
+- archive_entry_set_link(entry, tar->longlink.s);
+- }
+- return (err_combine(err, err2));
++ if (err != ARCHIVE_OK)
++ return (err);
++ err = tar_read_header(a, tar, entry, st);
++ if ((err != ARCHIVE_OK) && (err != ARCHIVE_WARN))
++ return (err);
++ /* Set symlink if symlink already set, else hardlink. */
++ archive_entry_set_link(entry, tar->longlink.s);
++ return (ARCHIVE_OK);
+ }
+
+ /*
+@@ -795,14 +826,17 @@ static int
+ header_longname(struct archive *a, struct tar *tar,
+ struct archive_entry *entry, struct stat *st, const void *h)
+ {
+- int err, err2;
++ int err;
+
+ err = read_body_to_string(a, tar, &(tar->longname), h);
++ if (err != ARCHIVE_OK)
++ return (err);
+ /* Read and parse "real" header, then override name. */
+- err2 = tar_read_header(a, tar, entry, st);
+- if (err == ARCHIVE_OK && err2 == ARCHIVE_OK)
+- archive_entry_set_pathname(entry, tar->longname.s);
+- return (err_combine(err, err2));
++ err = tar_read_header(a, tar, entry, st);
++ if ((err != ARCHIVE_OK) && (err != ARCHIVE_WARN))
++ return (err);
++ archive_entry_set_pathname(entry, tar->longname.s);
++ return (ARCHIVE_OK);
+ }
+
+
+@@ -836,12 +870,20 @@ read_body_to_string(struct archive *a, s
+ header = h;
+ size = tar_atol(header->size, sizeof(header->size));
+
++ /* Sanity check. */
++ if ((size > 1048576) || (size < 0)) {
++ archive_set_error(a, EINVAL, "Special header too large");
++ return (ARCHIVE_FATAL);
++ }
++
+ /* Read the body into the string. */
+ archive_string_ensure(as, size+1);
+ padded_size = (size + 511) & ~ 511;
+ dest = as->s;
+ while (padded_size > 0) {
+ bytes_read = (a->compression_read_ahead)(a, &src, padded_size);
++ if (bytes_read == 0)
++ return (ARCHIVE_EOF);
+ if (bytes_read < 0)
+ return (ARCHIVE_FATAL);
+ if (bytes_read > padded_size)
+@@ -1027,11 +1069,13 @@ static int
+ header_pax_global(struct archive *a, struct tar *tar,
+ struct archive_entry *entry, struct stat *st, const void *h)
+ {
+- int err, err2;
++ int err;
+
+ err = read_body_to_string(a, tar, &(tar->pax_global), h);
+- err2 = tar_read_header(a, tar, entry, st);
+- return (err_combine(err, err2));
++ if (err != ARCHIVE_OK)
++ return (err);
++ err = tar_read_header(a, tar, entry, st);
++ return (err);
+ }
+
+ static int
+@@ -1040,10 +1084,14 @@ header_pax_extensions(struct archive *a,
+ {
+ int err, err2;
+
+- read_body_to_string(a, tar, &(tar->pax_header), h);
++ err = read_body_to_string(a, tar, &(tar->pax_header), h);
++ if (err != ARCHIVE_OK)
++ return (err);
+
+ /* Parse the next header. */
+ err = tar_read_header(a, tar, entry, st);
++ if ((err != ARCHIVE_OK) && (err != ARCHIVE_WARN))
++ return (err);
+
+ /*
+ * TODO: Parse global/default options into 'entry' struct here
+@@ -1141,8 +1189,11 @@ pax_header(struct archive *a, struct tar
+ l--;
+ break;
+ }
+- if (*p < '0' || *p > '9')
+- return (-1);
++ if (*p < '0' || *p > '9') {
++ archive_set_error(a, ARCHIVE_ERRNO_MISC,
++ "Ignoring malformed pax extended attributes");
++ return (ARCHIVE_WARN);
++ }
+ line_length *= 10;
+ line_length += *p - '0';
+ if (line_length > 999999) {
+@@ -1154,8 +1205,19 @@ pax_header(struct archive *a, struct tar
+ l--;
+ }
+
+- if (line_length > attr_length)
+- return (0);
++ /*
++ * Parsed length must be no bigger than available data,
++ * at least 1, and the last character of the line must
++ * be '\n'.
++ */
++ if (line_length > attr_length
++ || line_length < 1
++ || attr[line_length - 1] != '\n')
++ {
++ archive_set_error(a, ARCHIVE_ERRNO_MISC,
++ "Ignoring malformed pax extended attribute");
++ return (ARCHIVE_WARN);
++ }
+
+ /* Ensure pax_entry buffer is big enough. */
+ if (tar->pax_entry_length <= line_length) {