<feed xmlns='http://www.w3.org/2005/Atom'>
<title>u-boot.git/fs/squashfs, branch main</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.</subtitle>
<id>http://cgit.235523.xyz/u-boot.git/atom/fs/squashfs?h=main</id>
<link rel='self' href='http://cgit.235523.xyz/u-boot.git/atom/fs/squashfs?h=main'/>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/u-boot.git/'/>
<updated>2026-08-28T15:00:06Z</updated>
<entry>
<title>Merge patch series "fs/squashfs: fix two out-of-bounds reads on crafted images"</title>
<updated>2026-08-28T15:00:06Z</updated>
<author>
<name>Tom Rini</name>
<email>trini@konsulko.com</email>
</author>
<published>2026-08-28T15:00:06Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/u-boot.git/commit/?id=d40f495e14d6ed1ec401cbe4bdc793cd9ed87d20'/>
<id>urn:sha1:d40f495e14d6ed1ec401cbe4bdc793cd9ed87d20</id>
<content type='text'>
Piyush Paliwal &lt;piyushthepal@gmail.com&gt; says:

Two independent out-of-bounds reads in the SquashFS driver, both reachable
by pointing U-Boot at an attacker-supplied image (e.g. ls/load on a crafted
USB/SD/netboot rootfs). Either one crashes the bootloader (DoS); patch 2 can
also copy adjacent heap memory into the loaded file (information disclosure).

  1/2 sqfs_find_inode()/sqfs_inode_size() walk the decompressed inode table
      using on-disk sizes with no check that the cursor stays inside the
      buffer -&gt; wild read / SEGV, e.g. from a simple "ls".
  2/2 sqfs_read_nest() uses the on-disk fragment offset as an unbounded
      source index into the fragment block -&gt; out-of-bounds heap read when
      loading a fragment-backed file.

Both were found by fuzzing the sandbox build (CONFIG_ASAN) of sqfsls/sqfsload
with mutated images. With the fixes, the crashing inputs are rejected
cleanly, 2000 fuzz iterations produce no further crashes, and the valid-image
path is unchanged.

These are distinct from the 2024 SquashFS CVE cluster (CVE-2024-57254..57259,
fixed in 2025.01-rc1) and from the sqfs_frag_lookup() fix (e365a269df5): the
earlier work added NULL checks at the callers and fixed the symlink-size and
fragment-table paths, but left these inode-table-walk and fragment-data
paths unbounded.

The two patches are independent and can be applied in either order.

Link: https://lore.kernel.org/r/20260612075424.83462-1-piyushthepal@gmail.com
</content>
</entry>
<entry>
<title>fs/squashfs: bound fragment offset/size in sqfs_read_nest()</title>
<updated>2026-08-28T14:55:57Z</updated>
<author>
<name>Piyush Paliwal</name>
<email>piyushthepal@gmail.com</email>
</author>
<published>2026-06-12T07:54:24Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/u-boot.git/commit/?id=923f05ed3e231c51f259bee6e2ac823bdaf1c566'/>
<id>urn:sha1:923f05ed3e231c51f259bee6e2ac823bdaf1c566</id>
<content type='text'>
When reading a fragment-backed file, sqfs_read_nest() copies the file
data out of the fragment block with:

  memcpy(buf + *actread, &amp;fragment_block[finfo.offset],
         finfo.size - *actread);

finfo.offset (the fragment's byte offset) and finfo.size come straight
from the on-disk inode and are never validated against the fragment
block length. Unlike the data-block loop above it, this path does not
clamp the source span, so a crafted inode makes the memcpy read past the
fragment buffer -&gt; out-of-bounds heap read. The leaked bytes are copied
into the user-visible load buffer (information disclosure) or fault.
This affects both the compressed (dest_len bytes) and the uncompressed
(table_size bytes) fragment cases.

Validate finfo.offset and the copy length against the available fragment
data before each memcpy and reject malformed inodes.

Found by fuzzing the sandbox (CONFIG_ASAN) sqfsload with mutated images:
before, SEGV in sqfs_read_nest() at the fragment memcpy; after, malformed
images are rejected and valid fragmented files still load correctly.

Fixes: 0008d8086649 ("fs/squashfs: fix reading of fragmented files")
Cc: stable@vger.kernel.org
Signed-off-by: Piyush Paliwal &lt;piyushthepal@gmail.com&gt;
Reviewed-by: Richard Genoud &lt;richard.genoud@bootlin.com&gt;
</content>
</entry>
<entry>
<title>fs/squashfs: bound the inode table walk in sqfs_find_inode()</title>
<updated>2026-08-28T14:55:57Z</updated>
<author>
<name>Piyush Paliwal</name>
<email>piyushthepal@gmail.com</email>
</author>
<published>2026-06-12T07:54:23Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/u-boot.git/commit/?id=73ada2f433a99fb2f443bb76268f5ab023b11868'/>
<id>urn:sha1:73ada2f433a99fb2f443bb76268f5ab023b11868</id>
<content type='text'>
sqfs_find_inode() walks the decompressed inode table advancing
"offset += sqfs_inode_size(base, ...)" with no check that offset stays
within the table (metablks_count * SQFS_METADATA_BLOCK_SIZE). All sizes
come from the on-disk image, including the unbounded extended-directory
(LDIR) index walk and the regular-file block-list term in
sqfs_inode_size(). A crafted image makes base run off the end of the
buffer -&gt; out-of-bounds read / SEGV, reachable simply by listing the
image (ls/sqfsls) or any operation that resolves a path.

The earlier fix 3fb1df1e5 ("squashfs: Check sqfs_find_inode() return
value") only added NULL checks at the call sites; it did not add the
missing internal bound, so the wild read still occurs before the
function can return. c8e929e5 fixed only the symlink case of
sqfs_inode_size(), leaving the LDIR index walk unbounded.

Thread the inode table size from sqfs_read_inode_table() through the
squashfs_dir_stream to sqfs_find_inode(), and:
 - reject an inode whose base header does not fit in the table;
 - pass the remaining byte count to sqfs_inode_size() and validate every
   variable-length read (LDIR index list, REG/LREG block list, symlink,
   device/ipc inodes) against it, with overflow-checked arithmetic;
 - reject an inode whose computed size leaves the table.

Found by fuzzing the sandbox (CONFIG_ASAN) sqfsls/sqfsload with mutated
images. Before: SEGV in sqfs_find_inode (sqfs_inode.c) and in
sqfs_inode_size() LDIR walk. After: malformed images are rejected
cleanly; 2000 fuzz iterations produce no crash and the valid-image path
is unchanged.

Fixes: c51006130370 ("fs/squashfs: new filesystem")
Cc: stable@vger.kernel.org
Signed-off-by: Piyush Paliwal &lt;piyushthepal@gmail.com&gt;
Reviewed-by: Richard Genoud &lt;richard.genoud@bootlin.com&gt;
</content>
</entry>
<entry>
<title>Merge patch series "fs/squashfs: fix directory table integer overflow"</title>
<updated>2026-08-27T21:05:06Z</updated>
<author>
<name>Tom Rini</name>
<email>trini@konsulko.com</email>
</author>
<published>2026-08-27T21:05:06Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/u-boot.git/commit/?id=658fc6aee95784139f070f9945cb3bc5da8d7d22'/>
<id>urn:sha1:658fc6aee95784139f070f9945cb3bc5da8d7d22</id>
<content type='text'>
Shahriyar Jalayeri &lt;shahriyar@byteray.co.uk&gt; says:

This fixes an integer overflow in the SquashFS directory-table reader
that leads to a heap out-of-bounds write, and adds a regression test.

sqfs_read_directory_table() sizes the directory table with an int
multiply (metablks_count * SQFS_METADATA_BLOCK_SIZE) that wraps for a
crafted image, under-allocating the buffer that the fill loop then
overruns. It is reached by listing or reading the image (sqfsls /
sqfsload). Patch 1 guards the allocation with __builtin_mul_overflow();
patch 2 adds a test that a crafted image is rejected.

Based on v2026.07 (fdfe2ec48d5c). A reproducer is available on request.

[trini: As part of the merge, this touches on what commit
 9a9d46cb5e1a ("fs/squashfs: fix heap exhaustion during symlink resolution")
 also handles, but they appear to be separate issues]
Link: https://lore.kernel.org/r/20260728-sqfs-oob-fix-v2-0-077d9f0e01c4@byteray.co.uk
</content>
</entry>
<entry>
<title>fs/squashfs: fix integer overflow in directory table allocation</title>
<updated>2026-08-27T21:01:02Z</updated>
<author>
<name>Shahriyar Jalayeri</name>
<email>shahriyar@byteray.co.uk</email>
</author>
<published>2026-07-28T06:55:39Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/u-boot.git/commit/?id=561ae28cb56a082cfa90c1c421c4955bc215470b'/>
<id>urn:sha1:561ae28cb56a082cfa90c1c421c4955bc215470b</id>
<content type='text'>
sqfs_read_directory_table() allocates the directory table with
malloc(metablks_count * SQFS_METADATA_BLOCK_SIZE). metablks_count is an
int and SQFS_METADATA_BLOCK_SIZE is 8192, so the multiply is evaluated in
int and wraps for metablks_count &gt;= 2^19. metablks_count comes from the
attacker-controlled superblock (sqfs_count_metablks() grows it by one per
2-byte metadata header), so a crafted image under-allocates the buffer
while the fill loop still writes metablks_count metadata blocks into it,
a heap out-of-bounds write. It is reached by listing or reading the image
(sqfsls / sqfsload). The position list allocation on the next line has the
same unchecked-multiply shape.

Size both allocations with __builtin_mul_overflow() and reject the image
on overflow, as the disk-read buffers earlier in the same function already
do. Set the error return when either allocation fails so the caller does
not proceed with a NULL directory table.

Fixes: c51006130370 ("fs/squashfs: new filesystem")
Signed-off-by: Shahriyar Jalayeri &lt;shahriyar@byteray.co.uk&gt;
Reviewed-by: Richard Genoud &lt;richard.genoud@bootlin.com&gt;
</content>
</entry>
<entry>
<title>fs/squashfs: bound the offset returned by sqfs_dir_offset()</title>
<updated>2026-08-27T21:00:03Z</updated>
<author>
<name>Pranav Rajendran</name>
<email>pranavkasthuri@gmail.com</email>
</author>
<published>2026-08-15T22:01:15Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/u-boot.git/commit/?id=e007b43a272edae8a63ad66f0151ceaf8cf003c1'/>
<id>urn:sha1:e007b43a272edae8a63ad66f0151ceaf8cf003c1</id>
<content type='text'>
Commit 57e0bb7bf00d ("fs/squashfs: add sqfs_dir_offset() error checks")
made sqfs_search_dir() reject negative returns from sqfs_dir_offset(),
but the positive range is still unbounded. Both parts of the returned
offset come from the image: 'offset' is a 16-bit inode field used
verbatim, and the matched metadata block index may be the last one in
m_list, in which case the returned block (j + 1) is one past the end
of the directory table.

The callers use the result to index dirs-&gt;dir_table[], which
sqfs_read_directory_table() allocates as m_count metadata blocks, and
then memcpy() a directory header out of it. A crafted image can
therefore read up to 64 KiB past the end of that allocation.

Reject an inode offset that cannot address a decompressed metadata
block, and verify that the resulting directory header lies entirely
within the directory table.

The existing 'offset &lt; 0' test is dropped: 'offset' is assigned from
get_unaligned_le16() and so is never negative, meaning the test never
fired. The new upper bound covers what it was meant to catch.

Fixes: c51006130370 ("fs/squashfs: new filesystem")
Signed-off-by: Pranav Rajendran &lt;pranavkasthuri@gmail.com&gt;
Reviewed-by: Richard Genoud &lt;richard.genoud@bootlin.com&gt;
</content>
</entry>
<entry>
<title>fs/squashfs: bound fragment table accesses in sqfs_frag_lookup()</title>
<updated>2026-08-27T21:00:03Z</updated>
<author>
<name>Pranav Rajendran</name>
<email>pranavkasthuri@gmail.com</email>
</author>
<published>2026-08-15T22:01:14Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/u-boot.git/commit/?id=fc557ef9fe116b3245265629cf1d3ab4ac7a480c'/>
<id>urn:sha1:fc557ef9fe116b3245265629cf1d3ab4ac7a480c</id>
<content type='text'>
sqfs_frag_lookup() validates its fragment index only against
sblk-&gt;fragments, which is read from the image superblock and is
therefore under the control of whoever supplies the image. Every
buffer access derived from that index is then made without checking
it against the size of the buffer actually read from the device:

 - the fragment index table entry at 'table_offset + block *
   sizeof(u64)' can be read past the end of 'table', as 'block' is
   inode_fragment_index / SQFS_MAX_ENTRIES and has no upper bound;

 - the metadata block header and payload are read from
   'metadata_buffer' at 'table_offset', but that buffer is sized from
   start_block, which comes from the unvalidated index table entry
   above. A start_block just below sblk-&gt;fragment_table_start yields a
   single-block buffer while SQFS_METADATA_SIZE(header) may be up to
   SQFS_METADATA_BLOCK_SIZE, so both the decompression source and the
   memcpy() source can run past the end of the buffer;

 - 'entries' is allocated with SQFS_METADATA_BLOCK_SIZE bytes but only
   partially filled, so entries[offset] can read uninitialised heap
   memory when the metadata block holds fewer than offset + 1 entries.

Compute the size of both buffers explicitly, rejecting the
multiplication overflow the way sqfs_read_directory_table() already
does, and check each access against it. Also track how much of
'entries' was populated and reject an index beyond that.

A crafted SquashFS image can trigger all three cases, either crashing
U-Boot or feeding adjacent heap contents into the fragment entry that
the following data read is based on.

Fixes: c51006130370 ("fs/squashfs: new filesystem")
Signed-off-by: Pranav Rajendran &lt;pranavkasthuri@gmail.com&gt;
Reviewed-by: Richard Genoud &lt;richard.genoud@bootlin.com&gt;
</content>
</entry>
<entry>
<title>Merge patch series "fs/squashfs: fix symlink load failure on large images"</title>
<updated>2026-07-25T13:55:35Z</updated>
<author>
<name>Tom Rini</name>
<email>trini@konsulko.com</email>
</author>
<published>2026-07-25T13:55:35Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/u-boot.git/commit/?id=b635d43bca429500cb8ef20aa151cb5773b9a8a5'/>
<id>urn:sha1:b635d43bca429500cb8ef20aa151cb5773b9a8a5</id>
<content type='text'>
Allan ELKAIM &lt;allan.elkaim@gmail.com&gt; says:

sqfsload fails to load a file through a symlink when the squashfs
image contains a large number of inodes (e.g. a rootfs that includes
the tzdata timezone database).

Root cause: sqfs_read_nest() resolves the symlink by calling itself
recursively without first freeing the parent directory's inode and
directory table buffers. This causes a temporary double allocation
that can exhaust the U-Boot heap. When malloc() subsequently fails
inside sqfs_read_directory_table(), the error goes undetected and
sqfs_search_dir() is called with a NULL pos_list pointer, leading to:

  Error: invalid inode reference to directory table.
  Failed to load '/boot/Image'

Patch 1 fixes the structural problem (temporary double allocation)
and plugs the silent NULL pointer path in sqfs_read_directory_table().
Patch 2 adds the missing return-value checks on sqfs_dir_offset() that
turn any residual lookup failure into a clean error propagation.

Patch 3 (reworked in v3 following Richard Genoud's review) fixes
pre-existing leaks of dirs-&gt;entry on the error paths of
sqfs_search_dir(), by centralizing the cleanup at the 'out' label.

All patches are independent and can be reviewed separately.

The bug was first observed on U-Boot v2024.01 and is still present
on v2026.04. The patches have been tested on a Raspberry Pi CM4
running U-Boot v2026.04 (Yocto Scarthgap 5.0.17) with a 325 MB
squashfs rootfs containing 22 517 inodes. The symlink
/boot/Image -&gt; Image-6.6.63-v8 now resolves successfully.

This series addresses the bug reported at:
https://lists.u-boot-project.org/pipermail/u-boot/2026-May/618533.html

Link: https://lore.kernel.org/r/20260713142420.2618339-1-allan.elkaim@gmail.com
</content>
</entry>
<entry>
<title>fs/squashfs: fix dirs-&gt;entry leaks on sqfs_search_dir() error paths</title>
<updated>2026-07-25T00:39:29Z</updated>
<author>
<name>Allan ELKAIM</name>
<email>allan.elkaim@gmail.com</email>
</author>
<published>2026-07-13T14:22:47Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/u-boot.git/commit/?id=171b604888537dd7112ffddaa13abb16932eabd0'/>
<id>urn:sha1:171b604888537dd7112ffddaa13abb16932eabd0</id>
<content type='text'>
Several error paths in sqfs_search_dir() return through 'goto out'
while a directory entry obtained from sqfs_readdir_nest() is still
held, leaking dirs-&gt;entry: the inode lookup failure, the symlink
nesting limit check, every allocation/tokenization failure during
symlink resolution, and the case where readdir aborts after an
entry was already read.

Instead of freeing dirs-&gt;entry at each error site, centralize the
cleanup at the 'out' label: on error, no valid entry may be handed
back to the caller, so it can be freed unconditionally there. On
success, dirs-&gt;entry is already NULL: it is freed at the end of
each token iteration and before recursing into a symlink target,
and the root directory path never allocates it.

Explicit frees remain only where a success path needs them:
between reads in the readdir loop, at the end of each token
iteration, and before the recursive call. The now-redundant frees
on individual error paths are removed.

Suggested-by: Richard Genoud &lt;richard.genoud@bootlin.com&gt;
Signed-off-by: Allan ELKAIM &lt;allan.elkaim@gmail.com&gt;
</content>
</entry>
<entry>
<title>fs/squashfs: add sqfs_dir_offset() error checks</title>
<updated>2026-07-25T00:39:29Z</updated>
<author>
<name>Allan ELKAIM</name>
<email>allan.elkaim@gmail.com</email>
</author>
<published>2026-07-13T14:22:45Z</published>
<link rel='alternate' type='text/html' href='http://cgit.235523.xyz/u-boot.git/commit/?id=57e0bb7bf00dadd7537f93609afb955108ce22c7'/>
<id>urn:sha1:57e0bb7bf00dadd7537f93609afb955108ce22c7</id>
<content type='text'>
sqfs_dir_offset() returns a negative errno on failure, but three
call sites in sqfs_search_dir() use the return value as an array
index without checking for errors first. If the lookup fails,
dirs-&gt;table is set to an invalid address, leading to undefined
behavior.

Add negative-value guards after each sqfs_dir_offset() call so
that any lookup failure propagates cleanly as an error rather
than producing incorrect results.

Note: the corresponding sqfs_find_inode() NULL checks and the
heap exhaustion fix during symlink resolution are applied in
separate patches.

Acked-by: Miquel Raynal &lt;miquel.raynal@bootlin.com&gt;
Reviewed-by: Richard Genoud &lt;richard.genoud@bootlin.com&gt;
Signed-off-by: Allan ELKAIM &lt;allan.elkaim@gmail.com&gt;
</content>
</entry>
</feed>
