All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow
@ 2026-07-28  6:55 Shahriyar Jalayeri
  2026-07-28  6:55 ` [PATCH v2 1/2] fs/squashfs: fix integer overflow in directory table allocation Shahriyar Jalayeri
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Shahriyar Jalayeri @ 2026-07-28  6:55 UTC (permalink / raw)
  To: u-boot, Thomas Petazzoni, Miquel Raynal, Joao Marcos Costa,
	u-boot
  Cc: Richard Genoud, Tom Rini, Michael Zimmermann, Eric Kilmer, Argus,
	Shahriyar Jalayeri

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.

Signed-off-by: Shahriyar Jalayeri <shahriyar@byteray.co.uk>
---
Changes in v2:
- Use my real name in the From and Signed-off-by

---
Shahriyar Jalayeri (2):
      fs/squashfs: fix integer overflow in directory table allocation
      test: squashfs: add directory table overflow regression test

 fs/squashfs/sqfs.c                                 | 23 +++++--
 .../test_fs/test_squashfs/test_sqfs_overflow.py    | 75 ++++++++++++++++++++++
 2 files changed, 94 insertions(+), 4 deletions(-)
---
base-commit: fdfe2ec48d5c1c2ed03073d73edd3fdd3fe1ffa1
change-id: 20260723-sqfs-oob-fix-e202a643c3d8

Best regards,
--  
Shahriyar Jalayeri <shahriyar@byteray.co.uk>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/2] fs/squashfs: fix integer overflow in directory table allocation
  2026-07-28  6:55 [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow Shahriyar Jalayeri
@ 2026-07-28  6:55 ` Shahriyar Jalayeri
  2026-07-28  6:55 ` [PATCH v2 2/2] test: squashfs: add directory table overflow regression test Shahriyar Jalayeri
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Shahriyar Jalayeri @ 2026-07-28  6:55 UTC (permalink / raw)
  To: u-boot, Thomas Petazzoni, Miquel Raynal, Joao Marcos Costa,
	u-boot
  Cc: Richard Genoud, Tom Rini, Michael Zimmermann, Eric Kilmer, Argus,
	Shahriyar Jalayeri

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 >= 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 <shahriyar@byteray.co.uk>
---
 fs/squashfs/sqfs.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c
index 0768fc4a7b2..3aadcdd36ec 100644
--- a/fs/squashfs/sqfs.c
+++ b/fs/squashfs/sqfs.c
@@ -852,13 +852,28 @@ static int sqfs_read_directory_table(unsigned char **dir_table, u32 **pos_list)
 	if (metablks_count < 1)
 		goto out;
 
-	*dir_table = malloc(metablks_count * SQFS_METADATA_BLOCK_SIZE);
-	if (!*dir_table)
+	if (__builtin_mul_overflow(metablks_count, SQFS_METADATA_BLOCK_SIZE,
+				   &buf_size)) {
+		metablks_count = -1;
+		goto out;
+	}
+
+	*dir_table = malloc(buf_size);
+	if (!*dir_table) {
+		metablks_count = -1;
+		goto out;
+	}
+
+	if (__builtin_mul_overflow(metablks_count, sizeof(u32), &buf_size)) {
+		metablks_count = -1;
 		goto out;
+	}
 
-	*pos_list = malloc(metablks_count * sizeof(u32));
-	if (!*pos_list)
+	*pos_list = malloc(buf_size);
+	if (!*pos_list) {
+		metablks_count = -1;
 		goto out;
+	}
 
 	ret = sqfs_get_metablk_pos(*pos_list, dtb, table_offset,
 				   metablks_count);

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/2] test: squashfs: add directory table overflow regression test
  2026-07-28  6:55 [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow Shahriyar Jalayeri
  2026-07-28  6:55 ` [PATCH v2 1/2] fs/squashfs: fix integer overflow in directory table allocation Shahriyar Jalayeri
@ 2026-07-28  6:55 ` Shahriyar Jalayeri
  2026-08-26 22:32 ` [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow Tom Rini
  2026-08-27 23:53 ` Tom Rini
  3 siblings, 0 replies; 6+ messages in thread
From: Shahriyar Jalayeri @ 2026-07-28  6:55 UTC (permalink / raw)
  To: u-boot, Thomas Petazzoni, Miquel Raynal, Joao Marcos Costa,
	u-boot
  Cc: Richard Genoud, Tom Rini, Michael Zimmermann, Eric Kilmer, Argus,
	Shahriyar Jalayeri

Add a Python test that lists a crafted SquashFS image whose directory
table declares an oversized metadata-block count. Such an image must be
rejected without corrupting the heap, which the test checks by confirming
U-Boot is still responsive afterwards.

Signed-off-by: Shahriyar Jalayeri <shahriyar@byteray.co.uk>
---
 .../test_fs/test_squashfs/test_sqfs_overflow.py    | 75 ++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/test/py/tests/test_fs/test_squashfs/test_sqfs_overflow.py b/test/py/tests/test_fs/test_squashfs/test_sqfs_overflow.py
new file mode 100644
index 00000000000..df7f875a58f
--- /dev/null
+++ b/test/py/tests/test_fs/test_squashfs/test_sqfs_overflow.py
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: GPL-2.0
+# Regression test for the SquashFS directory-table integer overflow.
+
+import os
+import struct
+import pytest
+
+# metadata block size (SQFS_METADATA_BLOCK_SIZE) and metadata header size
+SQFS_METADATA_BLOCK_SIZE = 8192
+# metablks_count that makes metablks_count * SQFS_METADATA_BLOCK_SIZE wrap a
+# 32-bit int back down to a tiny value: (2^19 + 1) * 8192 == 2^32 + 8192.
+NR_METABLKS = (1 << 19) + 1
+
+def make_overflow_image(path):
+    """Build a SquashFS image whose directory table inflates metablks_count so
+    that metablks_count * SQFS_METADATA_BLOCK_SIZE wraps a 32-bit int, then
+    writes one block of data one metadata block past the resulting buffer."""
+    def metahdr(size):
+        # uncompressed metadata block header (bit 15 set)
+        return struct.pack('<H', 0x8000 | (size & 0x7fff))
+
+    # inode table: one small valid uncompressed metadata block
+    inode_region = metahdr(32) + b'\x00' * 32
+    inode_start = 96
+    dir_start = inode_start + len(inode_region)
+
+    # directory table: NR_METABLKS metadata blocks, only block 1 carries data
+    dir_region = bytearray()
+    dir_region += metahdr(0)                          # block 0: empty
+    dir_region += metahdr(200) + b'A' * 200           # block 1: data
+    dir_region += metahdr(0) * (NR_METABLKS - 2)      # blocks 2..N-1: empty
+    frag_start = dir_start + len(dir_region)
+
+    sb = bytearray(96)
+    struct.pack_into('<I', sb, 0, 0x73717368)         # s_magic
+    struct.pack_into('<I', sb, 4, 1)                  # inodes
+    struct.pack_into('<I', sb, 12, 131072)            # block_size
+    struct.pack_into('<H', sb, 20, 1)                 # compression = gzip/zlib
+    struct.pack_into('<H', sb, 22, 17)                # block_log
+    struct.pack_into('<H', sb, 26, 1)                 # no_ids
+    struct.pack_into('<H', sb, 28, 4)                 # s_major
+    struct.pack_into('<Q', sb, 48, frag_start)        # id_table_start
+    struct.pack_into('<Q', sb, 56, 0xffffffffffffffff)  # xattr_id_table_start
+    struct.pack_into('<Q', sb, 64, inode_start)       # inode_table_start
+    struct.pack_into('<Q', sb, 72, dir_start)         # directory_table_start
+    struct.pack_into('<Q', sb, 80, frag_start)        # fragment_table_start
+    struct.pack_into('<Q', sb, 88, 0xffffffffffffffff)  # export_table_start
+
+    img = bytearray(sb) + inode_region + dir_region
+    # pad so the directory-table block read stays within the file
+    need = ((len(img) + 511) // 512 + 1) * 512
+    img += b'\x00' * (need - len(img))
+    struct.pack_into('<Q', img, 40, len(img))         # bytes_used
+
+    with open(path, 'wb') as f:
+        f.write(img)
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_squashfs')
+@pytest.mark.buildconfigspec('fs_squashfs')
+@pytest.mark.singlethread
+def test_sqfs_ls_dir_table_overflow(ubman):
+    """Listing a crafted image whose directory table declares an oversized
+    metadata-block count must be rejected without corrupting the heap.
+    """
+    ubman.restart_uboot()
+    image_path = os.path.join(ubman.config.build_dir, 'sqfs_dir_table_overflow')
+    make_overflow_image(image_path)
+    try:
+        ubman.run_command('host bind 0 {}'.format(image_path))
+        ubman.run_command('sqfsls host 0')
+        # The crafted image must not take the board down.
+        assert 'alive' in ubman.run_command('echo alive')
+    finally:
+        os.remove(image_path)

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow
  2026-07-28  6:55 [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow Shahriyar Jalayeri
  2026-07-28  6:55 ` [PATCH v2 1/2] fs/squashfs: fix integer overflow in directory table allocation Shahriyar Jalayeri
  2026-07-28  6:55 ` [PATCH v2 2/2] test: squashfs: add directory table overflow regression test Shahriyar Jalayeri
@ 2026-08-26 22:32 ` Tom Rini
  2026-08-27  7:25   ` Richard GENOUD
  2026-08-27 23:53 ` Tom Rini
  3 siblings, 1 reply; 6+ messages in thread
From: Tom Rini @ 2026-08-26 22:32 UTC (permalink / raw)
  To: Shahriyar Jalayeri
  Cc: u-boot, Thomas Petazzoni, Miquel Raynal, Joao Marcos Costa,
	u-boot, Richard Genoud, Michael Zimmermann, Eric Kilmer, Argus

[-- Attachment #1: Type: text/plain, Size: 923 bytes --]

On Tue, Jul 28, 2026 at 08:55:38AM +0200, Shahriyar Jalayeri wrote:

> 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.
> 
> Signed-off-by: Shahriyar Jalayeri <shahriyar@byteray.co.uk>
> ---
> Changes in v2:
> - Use my real name in the From and Signed-off-by

Any feedback from the squashfs custodians? Thanks!

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow
  2026-08-26 22:32 ` [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow Tom Rini
@ 2026-08-27  7:25   ` Richard GENOUD
  0 siblings, 0 replies; 6+ messages in thread
From: Richard GENOUD @ 2026-08-27  7:25 UTC (permalink / raw)
  To: Tom Rini, Shahriyar Jalayeri
  Cc: u-boot, Thomas Petazzoni, Miquel Raynal, Joao Marcos Costa,
	u-boot, Michael Zimmermann, Eric Kilmer, Argus

Le 27/08/2026 à 00:32, Tom Rini a écrit :
> On Tue, Jul 28, 2026 at 08:55:38AM +0200, Shahriyar Jalayeri wrote:
> 
>> 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.
>>
>> Signed-off-by: Shahriyar Jalayeri <shahriyar@byteray.co.uk>
>> ---
>> Changes in v2:
>> - Use my real name in the From and Signed-off-by
> 
> Any feedback from the squashfs custodians? Thanks!
> 
Nice patch, looks great!

Reviewed-by: Richard Genoud <richard.genoud@bootlin.com>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow
  2026-07-28  6:55 [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow Shahriyar Jalayeri
                   ` (2 preceding siblings ...)
  2026-08-26 22:32 ` [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow Tom Rini
@ 2026-08-27 23:53 ` Tom Rini
  3 siblings, 0 replies; 6+ messages in thread
From: Tom Rini @ 2026-08-27 23:53 UTC (permalink / raw)
  To: u-boot, Thomas Petazzoni, Miquel Raynal, Joao Marcos Costa,
	u-boot, Shahriyar Jalayeri
  Cc: Richard Genoud, Michael Zimmermann, Eric Kilmer, Argus

On Tue, 28 Jul 2026 08:55:38 +0200, Shahriyar Jalayeri wrote:

> 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.
> 
> [...]

Applied to u-boot/main, thanks!

[1/2] fs/squashfs: fix integer overflow in directory table allocation
      commit: 561ae28cb56a082cfa90c1c421c4955bc215470b
[2/2] test: squashfs: add directory table overflow regression test
      commit: 4750bcfe857c5a0feda86b54f260a11a4e3222cd
-- 
Tom



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-08-27 23:54 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-28  6:55 [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow Shahriyar Jalayeri
2026-07-28  6:55 ` [PATCH v2 1/2] fs/squashfs: fix integer overflow in directory table allocation Shahriyar Jalayeri
2026-07-28  6:55 ` [PATCH v2 2/2] test: squashfs: add directory table overflow regression test Shahriyar Jalayeri
2026-08-26 22:32 ` [PATCH v2 0/2] fs/squashfs: fix directory table integer overflow Tom Rini
2026-08-27  7:25   ` Richard GENOUD
2026-08-27 23:53 ` Tom Rini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.