Brad Bishop | 1932369 | 2019-04-05 15:28:33 -0400 | [diff] [blame] | 1 | CVE: CVE-2019-1000020 |
| 2 | Upstream-Status: Backport |
| 3 | Signed-off-by: Ross Burton <ross.burton@intel.com> |
| 4 | |
| 5 | From 8312eaa576014cd9b965012af51bc1f967b12423 Mon Sep 17 00:00:00 2001 |
| 6 | From: Daniel Axtens <dja@axtens.net> |
| 7 | Date: Tue, 1 Jan 2019 17:10:49 +1100 |
| 8 | Subject: [PATCH 1/2] iso9660: Fail when expected Rockridge extensions is |
| 9 | missing |
| 10 | |
| 11 | A corrupted or malicious ISO9660 image can cause read_CE() to loop |
| 12 | forever. |
| 13 | |
| 14 | read_CE() calls parse_rockridge(), expecting a Rockridge extension |
| 15 | to be read. However, parse_rockridge() is structured as a while |
| 16 | loop starting with a sanity check, and if the sanity check fails |
| 17 | before the loop has run, the function returns ARCHIVE_OK without |
| 18 | advancing the position in the file. This causes read_CE() to retry |
| 19 | indefinitely. |
| 20 | |
| 21 | Make parse_rockridge() return ARCHIVE_WARN if it didn't read an |
| 22 | extension. As someone with no real knowledge of the format, this |
| 23 | seems more apt than ARCHIVE_FATAL, but both the call-sites escalate |
| 24 | it to a fatal error immediately anyway. |
| 25 | |
| 26 | Found with a combination of AFL, afl-rb (FairFuzz) and qsym. |
| 27 | --- |
| 28 | libarchive/archive_read_support_format_iso9660.c | 11 ++++++++++- |
| 29 | 1 file changed, 10 insertions(+), 1 deletion(-) |
| 30 | |
| 31 | diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c |
| 32 | index 28acfefbb..bad8f1dfe 100644 |
| 33 | --- a/libarchive/archive_read_support_format_iso9660.c |
| 34 | +++ b/libarchive/archive_read_support_format_iso9660.c |
| 35 | @@ -2102,6 +2102,7 @@ parse_rockridge(struct archive_read *a, struct file_info *file, |
| 36 | const unsigned char *p, const unsigned char *end) |
| 37 | { |
| 38 | struct iso9660 *iso9660; |
| 39 | + int entry_seen = 0; |
| 40 | |
| 41 | iso9660 = (struct iso9660 *)(a->format->data); |
| 42 | |
| 43 | @@ -2257,8 +2258,16 @@ parse_rockridge(struct archive_read *a, struct file_info *file, |
| 44 | } |
| 45 | |
| 46 | p += p[2]; |
| 47 | + entry_seen = 1; |
| 48 | + } |
| 49 | + |
| 50 | + if (entry_seen) |
| 51 | + return (ARCHIVE_OK); |
| 52 | + else { |
| 53 | + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, |
| 54 | + "Tried to parse Rockridge extensions, but none found"); |
| 55 | + return (ARCHIVE_WARN); |
| 56 | } |
| 57 | - return (ARCHIVE_OK); |
| 58 | } |
| 59 | |
| 60 | static int |
| 61 | |