Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Please login to access the resource
openSUSE:Leap:42.3:Staging:A
libarchive
CVE-2015-8930.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File CVE-2015-8930.patch of Package libarchive
commit 39fc59391b7cf2a007bffce280c1e3e66674258f Author: Tim Kientzle <kientzle@acm.org> Date: Sat Apr 11 22:44:12 2015 -0700 Issue #522: Dir loop in malformed ISO causes segfault Github Issue #522 revealed that we could blow the stack when recursing to assemble ISO paths. I saw this happen at 130,000 dir levels. This patch addresses this by limiting the directory recursion to 1,000 elements. TODO: It would be even better to track and detect the dir loop directly. Index: libarchive-3.1.2/libarchive/archive_read_support_format_iso9660.c =================================================================== --- libarchive-3.1.2.orig/libarchive/archive_read_support_format_iso9660.c +++ libarchive-3.1.2/libarchive/archive_read_support_format_iso9660.c @@ -387,7 +387,7 @@ static int archive_read_format_iso9660_r static int archive_read_format_iso9660_read_data_skip(struct archive_read *); static int archive_read_format_iso9660_read_header(struct archive_read *, struct archive_entry *); -static const char *build_pathname(struct archive_string *, struct file_info *); +static const char *build_pathname(struct archive_string *, struct file_info *, int); static int build_pathname_utf16be(unsigned char *, size_t, size_t *, struct file_info *); #if DEBUG @@ -1223,6 +1223,7 @@ archive_read_format_iso9660_read_header( archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Pathname is too long"); + return (ARCHIVE_FATAL); } r = archive_entry_copy_pathname_l(entry, @@ -1245,9 +1246,16 @@ archive_read_format_iso9660_read_header( rd_r = ARCHIVE_WARN; } } else { - archive_string_empty(&iso9660->pathname); - archive_entry_set_pathname(entry, - build_pathname(&iso9660->pathname, file)); + const char *path = build_pathname(&iso9660->pathname, file, 0); + if (path == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname is too long"); + return (ARCHIVE_FATAL); + } else { + archive_string_empty(&iso9660->pathname); + archive_entry_set_pathname(entry, path); + } } iso9660->entry_bytes_remaining = file->size; @@ -1742,12 +1750,12 @@ parse_file_info(struct archive_read *a, const unsigned char *isodirrec) { struct iso9660 *iso9660; - struct file_info *file; + struct file_info *file, *filep; size_t name_len; const unsigned char *rr_start, *rr_end; const unsigned char *p; size_t dr_len; - uint64_t fsize; + uint64_t fsize, offset; int32_t location; int flags; @@ -1791,6 +1799,16 @@ parse_file_info(struct archive_read *a, return (NULL); } + /* Sanity check that this entry does not create a cycle. */ + offset = iso9660->logical_block_size * (uint64_t)location; + for (filep = parent; filep != NULL; filep = filep->parent) { + if (filep->offset == offset) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Directory structure contains loop"); + return (NULL); + } + } + /* Create a new file entry and copy data from the ISO dir record. */ file = (struct file_info *)calloc(1, sizeof(*file)); if (file == NULL) { @@ -1799,7 +1817,7 @@ parse_file_info(struct archive_read *a, return (NULL); } file->parent = parent; - file->offset = iso9660->logical_block_size * (uint64_t)location; + file->offset = offset; file->size = fsize; file->mtime = isodate7(isodirrec + DR_date_offset); file->ctime = file->atime = file->mtime; @@ -3164,10 +3182,17 @@ time_from_tm(struct tm *t) } static const char * -build_pathname(struct archive_string *as, struct file_info *file) +build_pathname(struct archive_string *as, struct file_info *file, int depth) { + // Plain ISO9660 only allows 8 dir levels; if we get + // to 1000, then something is very, very wrong. + if (depth > 1000) { + return NULL; + } if (file->parent != NULL && archive_strlen(&file->parent->name) > 0) { - build_pathname(as, file->parent); + if (build_pathname(as, file->parent, depth + 1) == NULL) { + return NULL; + } archive_strcat(as, "/"); } if (archive_strlen(&file->name) == 0)
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor