head 1.2; access; symbols pkgsrc-2013Q2:1.2.0.24 pkgsrc-2013Q2-base:1.2 pkgsrc-2012Q4:1.2.0.22 pkgsrc-2012Q4-base:1.2 pkgsrc-2011Q4:1.2.0.20 pkgsrc-2011Q4-base:1.2 pkgsrc-2011Q2:1.2.0.18 pkgsrc-2011Q2-base:1.2 pkgsrc-2009Q4:1.2.0.16 pkgsrc-2009Q4-base:1.2 pkgsrc-2008Q4:1.2.0.14 pkgsrc-2008Q4-base:1.2 pkgsrc-2008Q3:1.2.0.12 pkgsrc-2008Q3-base:1.2 cube-native-xorg:1.2.0.10 cube-native-xorg-base:1.2 pkgsrc-2008Q2:1.2.0.8 pkgsrc-2008Q2-base:1.2 pkgsrc-2008Q1:1.2.0.6 pkgsrc-2008Q1-base:1.2 pkgsrc-2007Q4:1.2.0.4 pkgsrc-2007Q4-base:1.2 pkgsrc-2007Q3:1.2.0.2 pkgsrc-2007Q3-base:1.2 pkgsrc-2007Q2:1.1.0.2; locks; strict; comment @# @; 1.2 date 2007.07.29.17.35.15; author joerg; state dead; branches; next 1.1; 1.1 date 2007.07.13.09.26.32; author lkundrak; state Exp; branches 1.1.2.1; next ; 1.1.2.1 date 2007.07.13.09.26.32; author ghen; state dead; branches; next 1.1.2.2; 1.1.2.2 date 2007.07.27.22.39.34; author ghen; state Exp; branches; next ; desc @@ 1.2 log @Update libarchive to 2.2.5. Biggest changes are: - massive performance improvements, up to 40% for bsdtar compared to 1.x - support for external (de)compressors, ar-chives and many other goodies. @ text @$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) { @ 1.1 log @Fix for FreeBSD-SA-07:05.libarchive CVE-2007-3641, CVE-2007-3644 and CVE-2007-3645. PKGREVISION bump. @ text @d1 1 a1 1 $NetBSD$ @ 1.1.2.1 log @file patch-ad was added on branch pkgsrc-2007Q2 on 2007-07-27 22:39:34 +0000 @ text @d1 230 @ 1.1.2.2 log @Pullup ticket 2144 - requested by lkundrak security fix for libarchive - pkgsrc/archivers/libarchive/Makefile 1.17 - pkgsrc/archivers/libarchive/distinfo 1.14 - pkgsrc/archivers/libarchive/patches/patch-ad 1.1 Module Name: pkgsrc Committed By: lkundrak Date: Fri Jul 13 09:26:32 UTC 2007 Modified Files: pkgsrc/archivers/libarchive: Makefile distinfo Added Files: pkgsrc/archivers/libarchive/patches: patch-ad Log Message: Fix for FreeBSD-SA-07:05.libarchive CVE-2007-3641, CVE-2007-3644 and CVE-2007-3645. PKGREVISION bump. @ text @a0 230 $NetBSD$ 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) { @