Blame SOURCES/libarchive-3.1.2-CVE-2015-8920.patch

58251f
From 97f964e3e0ce3ae34bfb4c366a37ba7c0d9610a6 Mon Sep 17 00:00:00 2001
58251f
From: Tim Kientzle <kientzle@acm.org>
58251f
Date: Sat, 7 Feb 2015 12:35:33 -0800
58251f
Subject: [PATCH] Issue 403: Buffer underflow parsing 'ar' header
58251f
58251f
While pruning trailing text from ar filenames, we did not
58251f
check for an empty filename.  This results in reading the byte
58251f
before the filename on the stack.
58251f
58251f
While here, change a number of ar format issues from WARN to FATAL.
58251f
It's better to abort on a damaged file than risk reading garbage.
58251f
No doubt, this will require additional tuning in the future.
58251f
---
58251f
 libarchive/archive_read_support_format_ar.c | 21 ++++++++++++++-------
58251f
 1 file changed, 14 insertions(+), 7 deletions(-)
58251f
58251f
diff --git a/libarchive/archive_read_support_format_ar.c b/libarchive/archive_read_support_format_ar.c
58251f
index 82756c9..4b5b66b 100644
58251f
--- a/libarchive/archive_read_support_format_ar.c
58251f
+++ b/libarchive/archive_read_support_format_ar.c
58251f
@@ -180,7 +180,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
58251f
 	if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) {
58251f
 		archive_set_error(&a->archive, EINVAL,
58251f
 		    "Incorrect file header signature");
58251f
-		return (ARCHIVE_WARN);
58251f
+		return (ARCHIVE_FATAL);
58251f
 	}
58251f
 
58251f
 	/* Copy filename into work buffer. */
58251f
@@ -239,8 +239,15 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
58251f
 	 * and are not terminated in '/', so we don't trim anything
58251f
 	 * that starts with '/'.)
58251f
 	 */
58251f
-	if (filename[0] != '/' && *p == '/')
58251f
+	if (filename[0] != '/' && p > filename && *p == '/') {
58251f
 		*p = '\0';
58251f
+	}
58251f
+
58251f
+	if (p < filename) {
58251f
+		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
58251f
+		    "Found entry with empty filename");
58251f
+		return (ARCHIVE_FATAL);
58251f
+	}
58251f
 
58251f
 	/*
58251f
 	 * '//' is the GNU filename table.
58251f
@@ -262,12 +269,12 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
58251f
 		if (entry_size == 0) {
58251f
 			archive_set_error(&a->archive, EINVAL,
58251f
 			    "Invalid string table");
58251f
-			return (ARCHIVE_WARN);
58251f
+			return (ARCHIVE_FATAL);
58251f
 		}
58251f
 		if (ar->strtab != NULL) {
58251f
 			archive_set_error(&a->archive, EINVAL,
58251f
 			    "More than one string tables exist");
58251f
-			return (ARCHIVE_WARN);
58251f
+			return (ARCHIVE_FATAL);
58251f
 		}
58251f
 
58251f
 		/* Read the filename table into memory. */
58251f
@@ -311,11 +318,11 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
58251f
 		 */
58251f
 		if (ar->strtab == NULL || number > ar->strtab_size) {
58251f
 			archive_set_error(&a->archive, EINVAL,
58251f
-			    "Can't find long filename for entry");
58251f
+			    "Can't find long filename for GNU/SVR4 archive entry");
58251f
 			archive_entry_copy_pathname(entry, filename);
58251f
 			/* Parse the time, owner, mode, size fields. */
58251f
 			ar_parse_common_header(ar, entry, h);
58251f
-			return (ARCHIVE_WARN);
58251f
+			return (ARCHIVE_FATAL);
58251f
 		}
58251f
 
58251f
 		archive_entry_copy_pathname(entry, &ar->strtab[(size_t)number]);
58251f
@@ -573,7 +580,7 @@ bad_string_table:
58251f
 	    "Invalid string table");
58251f
 	free(ar->strtab);
58251f
 	ar->strtab = NULL;
58251f
-	return (ARCHIVE_WARN);
58251f
+	return (ARCHIVE_FATAL);
58251f
 }
58251f
 
58251f
 static uint64_t
58251f
-- 
58251f
2.7.4
58251f