[PATCH] erofs: fix unsigned underflow in z_erofs_lz4_handle_overlap()

Junrui Luo
2026-04-09T07:00:08Z

In z_erofs_lz4_handle_overlap(), the index expression
"rq->outpages - rq->inpages + i" is computed in unsigned arithmetic.
If outpages < inpages, the subtraction wraps to a large value and
the subsequent rq->out[] access reads past the decompressed_pages
array.

z_erofs_map_sanity_check() does not enforce m_plen <= m_llen, so a
crafted image declaring m_plen > m_llen can produce outpages < inpages.

The in-place branch is currently unreachable: it requires both
partial_decoding == false and omargin > 0, but these are mutually
exclusive. partial_decoding == false requires pcl->length == m_llen,
which in turn requires (offset + end == m_la + m_llen) where
offset + end is page-aligned from folio boundaries. This forces
m_la + m_llen to be page-aligned, making oend page-aligned and
omargin zero.

Nonetheless, guard the branch with an explicit outpages >= inpages
check so the underflow cannot occur if future changes break this
alignment invariant.

Fixes: 598162d05080 ("erofs: support decompress big pcluster for lz4 backend")
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
---
fs/erofs/decompressor.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c
index 3c54e95964c9..2b065f8c3f71 100644
--- a/fs/erofs/decompressor.c
+++ b/fs/erofs/decompressor.c
@@ -145,6 +145,7 @@ static void *z_erofs_lz4_handle_overlap(const struct z_erofs_decompress_req *rq,
oend = rq->pageofs_out + rq->outputsize;
omargin = PAGE_ALIGN(oend) - oend;
if (!rq->partial_decoding && may_inplace &&
+ rq->outpages >= rq->inpages &&
omargin >= LZ4_DECOMPRESS_INPLACE_MARGIN(rq->inputsize)) {
for (i = 0; i < rq->inpages; ++i)
if (rq->out[rq->outpages - rq->inpages + i] !=

---
base-commit: 7aaa8047eafd0bd628065b15757d9b48c5f9c07d
change-id: 20260409-fixes-9430aaf958d5

Best regards,
--
Junrui Luo <moonafterrain@outlook.com>