]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core-contrib.git/blob
52f475dc424079944bc35dfcdf15886257123ee2
[thirdparty/openembedded/openembedded-core-contrib.git] /
1 From c769805c79d5acede65d96e5786aa5ebb46c01e0 Mon Sep 17 00:00:00 2001
2 From: Gao Xiang <hsiangkao@linux.alibaba.com>
3 Date: Fri, 2 Jun 2023 11:05:19 +0800
4 Subject: [PATCH 1/2] erofs-utils: fsck: don't allocate/read too large extents
5
6 Since some crafted EROFS filesystem images could have insane large
7 extents, which causes unexpected bahaviors when extracting data.
8
9 Fix it by extracting large extents with a buffer of a reasonable
10 maximum size limit and reading multiple times instead.
11
12 Note that only `--extract` option is impacted.
13
14 CVE: CVE-2023-33552
15 Closes: https://nvd.nist.gov/vuln/detail/CVE-2023-33552
16 Reported-by: Chaoming Yang <lometsj@live.com>
17 Fixes: 412c8f908132 ("erofs-utils: fsck: add --extract=X support to extract to path X")
18 Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
19 Link: https://lore.kernel.org/r/20230602030519.117071-1-hsiangkao@linux.alibaba.com
20
21 Upstream-Status: Backport
22 Signed-off-by: Ross Burton <ross.burton@arm.com>
23 ---
24 fsck/main.c | 63 +++++++++++++++++++++++++++++++++++++++++------------
25 1 file changed, 49 insertions(+), 14 deletions(-)
26
27 diff --git a/fsck/main.c b/fsck/main.c
28 index 6b42252..6689ad8 100644
29 --- a/fsck/main.c
30 +++ b/fsck/main.c
31 @@ -392,6 +392,8 @@ static int erofs_verify_inode_data(struct erofs_inode *inode, int outfd)
32 }
33
34 while (pos < inode->i_size) {
35 + unsigned int alloc_rawsize;
36 +
37 map.m_la = pos;
38 if (compressed)
39 ret = z_erofs_map_blocks_iter(inode, &map,
40 @@ -420,10 +422,28 @@ static int erofs_verify_inode_data(struct erofs_inode *inode, int outfd)
41 if (!(map.m_flags & EROFS_MAP_MAPPED) || !fsckcfg.check_decomp)
42 continue;
43
44 - if (map.m_plen > raw_size) {
45 - raw_size = map.m_plen;
46 - raw = realloc(raw, raw_size);
47 - BUG_ON(!raw);
48 + if (map.m_plen > Z_EROFS_PCLUSTER_MAX_SIZE) {
49 + if (compressed) {
50 + erofs_err("invalid pcluster size %" PRIu64 " @ offset %" PRIu64 " of nid %" PRIu64,
51 + map.m_plen, map.m_la,
52 + inode->nid | 0ULL);
53 + ret = -EFSCORRUPTED;
54 + goto out;
55 + }
56 + alloc_rawsize = Z_EROFS_PCLUSTER_MAX_SIZE;
57 + } else {
58 + alloc_rawsize = map.m_plen;
59 + }
60 +
61 + if (alloc_rawsize > raw_size) {
62 + char *newraw = realloc(raw, alloc_rawsize);
63 +
64 + if (!newraw) {
65 + ret = -ENOMEM;
66 + goto out;
67 + }
68 + raw = newraw;
69 + raw_size = alloc_rawsize;
70 }
71
72 if (compressed) {
73 @@ -434,18 +454,27 @@ static int erofs_verify_inode_data(struct erofs_inode *inode, int outfd)
74 }
75 ret = z_erofs_read_one_data(inode, &map, raw, buffer,
76 0, map.m_llen, false);
77 + if (ret)
78 + goto out;
79 +
80 + if (outfd >= 0 && write(outfd, buffer, map.m_llen) < 0)
81 + goto fail_eio;
82 } else {
83 - ret = erofs_read_one_data(&map, raw, 0, map.m_plen);
84 - }
85 - if (ret)
86 - goto out;
87 + u64 p = 0;
88
89 - if (outfd >= 0 && write(outfd, compressed ? buffer : raw,
90 - map.m_llen) < 0) {
91 - erofs_err("I/O error occurred when verifying data chunk @ nid %llu",
92 - inode->nid | 0ULL);
93 - ret = -EIO;
94 - goto out;
95 + do {
96 + u64 count = min_t(u64, alloc_rawsize,
97 + map.m_llen);
98 +
99 + ret = erofs_read_one_data(&map, raw, p, count);
100 + if (ret)
101 + goto out;
102 +
103 + if (outfd >= 0 && write(outfd, raw, count) < 0)
104 + goto fail_eio;
105 + map.m_llen -= count;
106 + p += count;
107 + } while (map.m_llen);
108 }
109 }
110
111 @@ -460,6 +489,12 @@ out:
112 if (buffer)
113 free(buffer);
114 return ret < 0 ? ret : 0;
115 +
116 +fail_eio:
117 + erofs_err("I/O error occurred when verifying data chunk @ nid %llu",
118 + inode->nid | 0ULL);
119 + ret = -EIO;
120 + goto out;
121 }
122
123 static inline int erofs_extract_dir(struct erofs_inode *inode)
124 --
125 2.34.1
126