* [PATCH] erofs-utils: fsck: don't allocate/read too large extents
@ 2023-06-02 3:02 Gao Xiang
2023-06-02 3:05 ` [PATCH v2] " Gao Xiang
0 siblings, 1 reply; 2+ messages in thread
From: Gao Xiang @ 2023-06-02 3:02 UTC (permalink / raw)
To: linux-erofs; +Cc: Gao Xiang, Chaoming Yang
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 with 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>
---
fsck/main.c | 62 ++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 47 insertions(+), 15 deletions(-)
diff --git a/fsck/main.c b/fsck/main.c
index ad40537..6f89a1e 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) {
+ int alloc_rawsize;
+
map.m_la = pos;
if (compressed)
ret = z_erofs_map_blocks_iter(inode, &map,
@@ -420,10 +422,27 @@ 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);
+ 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 +453,25 @@ 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 count, p = 0;
+
+ do {
+ 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);
}
}
@@ -460,6 +486,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.24.4
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [PATCH v2] erofs-utils: fsck: don't allocate/read too large extents
2023-06-02 3:02 [PATCH] erofs-utils: fsck: don't allocate/read too large extents Gao Xiang
@ 2023-06-02 3:05 ` Gao Xiang
0 siblings, 0 replies; 2+ messages in thread
From: Gao Xiang @ 2023-06-02 3:05 UTC (permalink / raw)
To: linux-erofs; +Cc: Gao Xiang, Chaoming Yang
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 with 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>
---
changes since v1:
- use `unsigned int alloc_rawsize` instead.
fsck/main.c | 62 ++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 47 insertions(+), 15 deletions(-)
diff --git a/fsck/main.c b/fsck/main.c
index ad40537..6f89a1e 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,27 @@ 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);
+ 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 +453,25 @@ 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 count, p = 0;
+
+ do {
+ 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);
}
}
@@ -460,6 +486,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.24.4
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2023-06-02 3:05 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-02 3:02 [PATCH] erofs-utils: fsck: don't allocate/read too large extents Gao Xiang
2023-06-02 3:05 ` [PATCH v2] " Gao Xiang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).