6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gao Xiang hsiangkao@linux.alibaba.com
[ Upstream commit f2a12cc3b97f062186568a7b94ddb7aa2ef68140 ]
Currently, the decompression logic incorrectly spins if compressed data is truncated in crafted (deliberately corrupted) images.
Fixes: 7c35de4df105 ("erofs: Zstandard compression support") Reported-by: Robert Morris rtm@csail.mit.edu Closes: https://lore.kernel.org/r/50958.1761605413@localhost Signed-off-by: Gao Xiang hsiangkao@linux.alibaba.com Reviewed-by: Chunhai Guo guochunhai@vivo.com Reviewed-by: Chao Yu chao@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- fs/erofs/decompressor_zstd.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/fs/erofs/decompressor_zstd.c b/fs/erofs/decompressor_zstd.c index 7e177304967e1..24f4731a7a6d4 100644 --- a/fs/erofs/decompressor_zstd.c +++ b/fs/erofs/decompressor_zstd.c @@ -178,7 +178,6 @@ static int z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq, dctx.bounce = strm->bounce;
do { - dctx.avail_out = out_buf.size - out_buf.pos; dctx.inbuf_sz = in_buf.size; dctx.inbuf_pos = in_buf.pos; err = z_erofs_stream_switch_bufs(&dctx, &out_buf.dst, @@ -194,14 +193,18 @@ static int z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq, in_buf.pos = dctx.inbuf_pos;
zerr = zstd_decompress_stream(stream, &out_buf, &in_buf); - if (zstd_is_error(zerr) || (!zerr && rq->outputsize)) { + dctx.avail_out = out_buf.size - out_buf.pos; + if (zstd_is_error(zerr) || + ((rq->outputsize + dctx.avail_out) && (!zerr || (zerr > 0 && + !(rq->inputsize + in_buf.size - in_buf.pos))))) { erofs_err(sb, "failed to decompress in[%u] out[%u]: %s", rq->inputsize, rq->outputsize, - zerr ? zstd_get_error_name(zerr) : "unexpected end of stream"); + zstd_is_error(zerr) ? zstd_get_error_name(zerr) : + "unexpected end of stream"); err = -EFSCORRUPTED; break; } - } while (rq->outputsize || out_buf.pos < out_buf.size); + } while (rq->outputsize + dctx.avail_out);
if (dctx.kout) kunmap_local(dctx.kout);
linux-stable-mirror@lists.linaro.org