From: Jay Vadayath <jay@artiphishell.com>
To: David Woodhouse <dwmw2@infradead.org>,
Richard Weinberger <richard@nod.at>
Cc: linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org,
Jay Vadayath <jay@artiphishell.com>
Subject: [PATCH] jffs2: reject undersized input in jffs2_dynrubin_decompress
Date: Thu, 22 Oct 2026 11:19:05 -0700 [thread overview]
Message-ID: <20261022181905.35588-1-jay@artiphishell.com> (raw)
jffs2_dynrubin_decompress() reads an 8-byte probability prefix
(data_in[0..7]) out of a compressed data node and then passes
sourcelen - 8 (csize - 8) as the input length to rubin_do_decompress().
The compressed buffer is a kmalloc(csize) slab filled from the on-disk
node, but nothing checks that csize is at least 8 before the prefix is
read or before the subtraction. When a node declares csize < 8 the read
of data_in[0..7] already runs past the end of the slab, and sourcelen - 8
underflows to roughly 4 GiB, which defeats the pullbit() bound and lets
rubin_do_decompress() keep reading unbounded.
A hostile jffs2 image that carries a data node with
compr == JFFS2_COMPR_DYNRUBIN (on-disk id 0x03 routes to this
decompressor) and a tiny csize therefore causes an out-of-bounds read of
the compressed-input slab. Reachable from any user who can cause the file
to be read on a mounted attacker-supplied jffs2 image (e.g. cat on the
file; the image dd'd to /dev/mtdblock0 via CONFIG_MTD_MTDRAM). The
decompressor stays registered even when compression is disabled, so the
code path is always live.
BUG: KASAN: slab-out-of-bounds in jffs2_dynrubin_decompress+0x170/0x1c0
Read of size 1 at addr ffff888006b45a64 by task poc/125
Call Trace:
dump_stack_lvl+0x64/0x80
print_report+0xd0/0x630
kasan_report+0xe5/0x120
jffs2_dynrubin_decompress+0x170/0x1c0
jffs2_decompress
jffs2_read_dnode
...
Reject any node whose compressed size is smaller than the 8-byte prefix
(if (sourcelen < 8) return -1;), and additionally bound pullbit() so that
a stream claiming more output than the input provides is treated as a run
of zero bits instead of walking off the kmalloc(csize) buffer.
This bug was discovered by Artiphishell, which
generated a from-scratch jffs2 image (cleanmarker + dirent + inode node
with CRCs computed via crc32_le) and a mount+cat reproducer that reliably
triggers the KASAN report on an unpatched kernel (csize=4 -> kmalloc(4)
-> reads data_in[0..7]). The fix below was drafted with the Claude coding
assistant; a userspace reproducer is available on request.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Jay Vadayath <jay@artiphishell.com>
---
fs/jffs2/compr_rubin.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c
index 9854253d0108..98bbab157c62 100644
--- a/fs/jffs2/compr_rubin.c
+++ b/fs/jffs2/compr_rubin.c
@@ -78,6 +78,12 @@ static inline int pullbit(struct pushpull *pp)
{
int bit;
+ /* On decompress buflen bounds the input; treat an overrun as zero bits. */
+ if ((pp->ofs >> 3) >= pp->buflen) {
+ pp->ofs++;
+ return 0;
+ }
+
bit = (pp->buf[pp->ofs >> 3] >> (7-(pp->ofs & 7))) & 1;
pp->ofs++;
@@ -392,6 +398,10 @@ static int jffs2_dynrubin_decompress(unsigned char *data_in,
int bits[8];
int c;
+ /* Need the 8-byte prefix; also avoids the sourcelen-8 underflow. */
+ if (sourcelen < 8)
+ return -1;
+
for (c=0; c<8; c++)
bits[c] = data_in[c];
--
2.51.2
reply other threads:[~2026-10-22 18:19 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261022181905.35588-1-jay@artiphishell.com \
--to=jay@artiphishell.com \
--cc=dwmw2@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=richard@nod.at \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®