summaryrefslogtreecommitdiff
path: root/poky/meta/recipes-devtools/erofs-utils/erofs-utils/CVE-2023-33552-3.patch
blob: c05d62c5dda9d518df41fc23ce4aa0160d4922ae (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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
From b4e155ba759ae389c5f71cd13d97eb3bcf2c1adf Mon Sep 17 00:00:00 2001
From: Gao Xiang <hsiangkao@linux.alibaba.com>
Date: Fri, 2 Jun 2023 11:05:19 +0800
Subject: [PATCH] erofs-utils: fsck: don't allocate/read too large extents

Since some crafted EROFS filesystem images could have insane large
extents, which causes unexpected bahaviors when extracting data.

Fix it by extracting large extents with a buffer of a reasonable
maximum size limit and reading multiple times instead.

Note that only `--extract` option is impacted.

CVE: CVE-2023-33552
Closes: https://nvd.nist.gov/vuln/detail/CVE-2023-33552
Reported-by: Chaoming Yang <lometsj@live.com>
Fixes: 412c8f908132 ("erofs-utils: fsck: add --extract=X support to extract to path X")
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20230602030519.117071-1-hsiangkao@linux.alibaba.com

CVE: CVE-2023-33552
Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs-utils.git/patch/?id=2145dff03dd3f3f74bcda3b52160fbad37f7fcfe]
Signed-off-by: Changqing Li <changqing.li@windriver.com>
---
 fsck/main.c | 64 ++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 49 insertions(+), 15 deletions(-)

diff --git a/fsck/main.c b/fsck/main.c
index 92ef17a..1bd1117 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -392,6 +392,8 @@ static int erofs_verify_inode_data(struct erofs_inode *inode, int outfd)
 	}
 
 	while (pos < inode->i_size) {
+		unsigned int alloc_rawsize;
+
 		map.m_la = pos;
 		if (compressed)
 			ret = z_erofs_map_blocks_iter(inode, &map,
@@ -420,10 +422,28 @@ static int erofs_verify_inode_data(struct erofs_inode *inode, int outfd)
 		if (!(map.m_flags & EROFS_MAP_MAPPED) || !fsckcfg.check_decomp)
 			continue;
 
-		if (map.m_plen > raw_size) {
-			raw_size = map.m_plen;
-			raw = realloc(raw, raw_size);
-			BUG_ON(!raw);
+		if (map.m_plen > Z_EROFS_PCLUSTER_MAX_SIZE) {
+			if (compressed) {
+				erofs_err("invalid pcluster size %" PRIu64 " @ offset %" PRIu64 " of nid %" PRIu64,
+					  map.m_plen, map.m_la,
+					  inode->nid | 0ULL);
+				ret = -EFSCORRUPTED;
+				goto out;
+			}
+			alloc_rawsize = Z_EROFS_PCLUSTER_MAX_SIZE;
+		} else {
+			alloc_rawsize = map.m_plen;
+		}
+
+		if (alloc_rawsize > raw_size) {
+			char *newraw = realloc(raw, alloc_rawsize);
+
+			if (!newraw) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			raw = newraw;
+			raw_size = alloc_rawsize;
 		}
 
 		if (compressed) {
@@ -434,18 +454,26 @@ static int erofs_verify_inode_data(struct erofs_inode *inode, int outfd)
 			}
 			ret = z_erofs_read_one_data(inode, &map, raw, buffer,
 						0, map.m_llen, false);
-		} else {
-			ret = erofs_read_one_data(&map, raw, 0, map.m_plen);
-		}
-		if (ret)
-			goto out;
+			if (ret)
+				goto out;
 
-		if (outfd >= 0 && write(outfd, compressed ? buffer : raw,
-					map.m_llen) < 0) {
-			erofs_err("I/O error occurred when verifying data chunk @ nid %llu",
-				  inode->nid | 0ULL);
-			ret = -EIO;
-			goto out;
+			if (outfd >= 0 && write(outfd, buffer, map.m_llen) < 0)
+				goto fail_eio;
+		} else {
+			u64 p = 0;
+			do {
+				u64 count = min_t(u64, alloc_rawsize,
+						map.m_llen);
+
+				ret = erofs_read_one_data(&map, raw, p, count);
+				if (ret)
+					goto out;
+
+				if (outfd >= 0 && write(outfd, raw, count) < 0)
+					goto fail_eio;
+				map.m_llen -= count;
+				p += count;
+			} while (map.m_llen);
 		}
 	}
 
@@ -461,6 +489,12 @@ out:
 	if (buffer)
 		free(buffer);
 	return ret < 0 ? ret : 0;
+
+fail_eio:
+	erofs_err("I/O error occurred when verifying data chunk @ nid %llu",
+		  inode->nid | 0ULL);
+	ret = -EIO;
+	goto out;
 }
 
 static inline int erofs_extract_dir(struct erofs_inode *inode)
-- 
2.25.1