mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Richard Weinberger <richard@nod.at>,
	Richard Weinberger <richard@sigma-star.at>,
	Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH 1/6] squashfs: be more careful about metadata corruption
Date: Wed, 17 Jul 2024 08:33:23 +0200	[thread overview]
Message-ID: <20240717063328.2810835-2-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20240717063328.2810835-1-a.fatoum@pengutronix.de>

This is a port of Linux commit 01cfb7937a9af2abb1136c7e89fbf3fd92952956:

| Author:     Linus Torvalds <torvalds@linux-foundation.org>
| AuthorDate: Sun Jul 29 12:44:46 2018 -0700
|
| Anatoly Trosinenko reports that a corrupted squashfs image can cause a
| kernel oops.  It turns out that squashfs can end up being confused about
| negative fragment lengths.
|
| The regular squashfs_read_data() does check for negative lengths, but
| squashfs_read_metadata() did not, and the fragment size code just
| blindly trusted the on-disk value.  Fix both the fragment parsing and
| the metadata reading code.
|
| Reported-by: Anatoly Trosinenko <anatoly.trosinenko@gmail.com>
| Cc: Al Viro <viro@zeniv.linux.org.uk>
| Cc: Phillip Lougher <phillip@squashfs.org.uk>
| Cc: stable@kernel.org
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Reported-by: Richard Weinberger <richard@sigma-star.at>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 fs/squashfs/cache.c       |  3 +++
 fs/squashfs/file.c        |  8 ++++++--
 fs/squashfs/fragment.c    |  4 +---
 fs/squashfs/squashfs_fs.h | 11 +++++++++++
 4 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c
index 766bc99493b9..5a027d6fe5d0 100644
--- a/fs/squashfs/cache.c
+++ b/fs/squashfs/cache.c
@@ -284,6 +284,9 @@ int squashfs_read_metadata(struct super_block *sb, void *buffer,
 
 	TRACE("Entered squashfs_read_metadata [%llx:%x]\n", *block, *offset);
 
+	if (unlikely(length < 0))
+		return -EIO;
+
 	while (length) {
 		entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0);
 		if (entry->error) {
diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
index 0806f90b9667..1413ef7ecbd8 100644
--- a/fs/squashfs/file.c
+++ b/fs/squashfs/file.c
@@ -169,7 +169,11 @@ static long long read_indexes(struct super_block *sb, int n,
 		}
 
 		for (i = 0; i < blocks; i++) {
-			int size = le32_to_cpu(blist[i]);
+			int size = squashfs_block_size(blist[i]);
+			if (size < 0) {
+				err = size;
+				goto failure;
+			}
 			block += SQUASHFS_COMPRESSED_SIZE_BLOCK(size);
 		}
 		n -= blocks;
@@ -340,7 +344,7 @@ static int read_blocklist(struct inode *inode, int index, u64 *block)
 			sizeof(size));
 	if (res < 0)
 		return res;
-	return le32_to_cpu(size);
+	return squashfs_block_size(size);
 }
 
 /* Copy data into page cache  */
diff --git a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c
index 2b99ff52e334..343444000e02 100644
--- a/fs/squashfs/fragment.c
+++ b/fs/squashfs/fragment.c
@@ -56,9 +56,7 @@ int squashfs_frag_lookup(struct super_block *sb, unsigned int fragment,
 		return size;
 
 	*fragment_block = le64_to_cpu(fragment_entry.start_block);
-	size = le32_to_cpu(fragment_entry.size);
-
-	return size;
+	return squashfs_block_size(fragment_entry.size);
 }
 
 
diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h
index 279a3db1bcb2..6ce6ed01ba76 100644
--- a/fs/squashfs/squashfs_fs.h
+++ b/fs/squashfs/squashfs_fs.h
@@ -1,5 +1,10 @@
 #ifndef SQUASHFS_FS
 #define SQUASHFS_FS
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+
 /*
  * Squashfs
  *
@@ -125,6 +130,12 @@
 
 #define SQUASHFS_COMPRESSED_BLOCK(B)	(!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
 
+static inline int squashfs_block_size(__le32 raw)
+{
+	u32 size = le32_to_cpu(raw);
+	return (size >> 25) ? -EIO : size;
+}
+
 /*
  * Inode number ops.  Inodes consist of a compressed block number, and an
  * uncompressed offset within that block
-- 
2.39.2




  reply	other threads:[~2024-07-17  6:34 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-17  6:33 [PATCH 0/6] squashfs: harden against crafted metadata Ahmad Fatoum
2024-07-17  6:33 ` Ahmad Fatoum [this message]
2024-07-17  6:33 ` [PATCH 2/6] squashfs: more metadata hardening Ahmad Fatoum
2024-07-17  6:33 ` [PATCH 3/6] squashfs metadata 2: electric boogaloo Ahmad Fatoum
2024-07-17  6:33 ` [PATCH 4/6] squashfs: more metadata hardening Ahmad Fatoum
2024-07-17  6:33 ` [PATCH 5/6] Squashfs: Compute expected length from inode size rather than block length Ahmad Fatoum
2024-07-17  6:33 ` [PATCH 6/6] squashfs: refuse mount of squashfs images with non-128K block size Ahmad Fatoum
2024-07-19  6:36 ` [PATCH 0/6] squashfs: harden against crafted metadata Sascha Hauer

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=20240717063328.2810835-2-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    --cc=richard@nod.at \
    --cc=richard@sigma-star.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