summaryrefslogtreecommitdiffstats
path: root/meta/recipes-extended/libarchive/libarchive/CVE-2019-1000020.patch
blob: 3e63921346428ec09541644ac09576b2d9ff0a25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
CVE: CVE-2018-1000020
Upstream-Status: Backport
Signed-off-by: Ross Burton <ross.burton@intel.com>

From 8312eaa576014cd9b965012af51bc1f967b12423 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Tue, 1 Jan 2019 17:10:49 +1100
Subject: [PATCH 1/2] iso9660: Fail when expected Rockridge extensions is
 missing

A corrupted or malicious ISO9660 image can cause read_CE() to loop
forever.

read_CE() calls parse_rockridge(), expecting a Rockridge extension
to be read. However, parse_rockridge() is structured as a while
loop starting with a sanity check, and if the sanity check fails
before the loop has run, the function returns ARCHIVE_OK without
advancing the position in the file. This causes read_CE() to retry
indefinitely.

Make parse_rockridge() return ARCHIVE_WARN if it didn't read an
extension. As someone with no real knowledge of the format, this
seems more apt than ARCHIVE_FATAL, but both the call-sites escalate
it to a fatal error immediately anyway.

Found with a combination of AFL, afl-rb (FairFuzz) and qsym.
---
 libarchive/archive_read_support_format_iso9660.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c
index 28acfefbb..bad8f1dfe 100644
--- a/libarchive/archive_read_support_format_iso9660.c
+++ b/libarchive/archive_read_support_format_iso9660.c
@@ -2102,6 +2102,7 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
     const unsigned char *p, const unsigned char *end)
 {
 	struct iso9660 *iso9660;
+	int entry_seen = 0;
 
 	iso9660 = (struct iso9660 *)(a->format->data);
 
@@ -2257,8 +2258,16 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
 		}
 
 		p += p[2];
+		entry_seen = 1;
+	}
+
+	if (entry_seen)
+		return (ARCHIVE_OK);
+	else {
+		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+				  "Tried to parse Rockridge extensions, but none found");
+		return (ARCHIVE_WARN);
 	}
-	return (ARCHIVE_OK);
 }
 
 static int