summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKarl Mehltretter <kmehltretter@gmail.com>2026-08-29 11:18:49 +0200
committerHerbert Xu <herbert@gondor.apana.org.au>2026-09-11 15:03:04 +1000
commit38ed7182f3491ec1449ff246551e11ad82adba45 (patch)
treea52b4aa5bb0150fd86fb5727d0222370e93dd468 /lib
parent0dd8cded0e6f8c9635fe1d79d60dc7b2599b099b (diff)
downloadlinux-next-38ed7182f3491ec1449ff246551e11ad82adba45.tar.gz
linux-next-38ed7182f3491ec1449ff246551e11ad82adba45.zip
lib/842: reject output overflows from index and short data
The output length passed to sw842_decompress() is the caller's buffer capacity. Indexed copies write 2, 4 or 8 bytes and short-data templates write up to 7, but neither checks that capacity before writing and decrementing p->olen. Overwriting an undersized destination then underflows p->olen, which is unsigned, so every later bounds check in the stream passes. Subsequent operations keep writing past the destination, and a matching CRC lets sw842_decompress() return success with an output length larger than the capacity the caller supplied. This is reachable through zram's compressed writeback path. With 842 selected, targeted corruption of the compressed data on its backing device made a KASAN kernel report vmalloc-out-of-bounds writes in __do_index() and sw842_decompress() when zram read the page back. Check the remaining output before both operations and return -ENOSPC, matching the other output-producing templates. Fixes: 2da572c959dd ("lib: add software 842 compression/decompression") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'lib')
-rw-r--r--lib/842/842_decompress.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/lib/842/842_decompress.c b/lib/842/842_decompress.c
index 582085ef8b49..87d1e0f8a492 100644
--- a/lib/842/842_decompress.c
+++ b/lib/842/842_decompress.c
@@ -165,6 +165,9 @@ static int __do_index(struct sw842_param *p, u8 size, u8 bits, u64 fsize)
u64 index, offset, total = round_down(p->out - p->ostart, 8);
int ret;
+ if (size > p->olen)
+ return -ENOSPC;
+
ret = next_bits(p, &index, bits);
if (ret)
return ret;
@@ -344,6 +347,8 @@ int sw842_decompress(const u8 *in, unsigned int ilen,
if (!bytes || bytes > SHORT_DATA_BITS_MAX)
return -EINVAL;
+ if (bytes > p.olen)
+ return -ENOSPC;
while (bytes-- > 0) {
ret = next_bits(&p, &tmp, 8);