[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250923220652.568416-2-phillip@squashfs.org.uk>
Date: Tue, 23 Sep 2025 23:06:51 +0100
From: Phillip Lougher <phillip@...ashfs.org.uk>
To: akpm@...ux-foundation.org,
linux-kernel@...r.kernel.org
Cc: Phillip Lougher <phillip@...ashfs.org.uk>
Subject: [PATCH 1/2] Squashfs: add additional inode sanity checking
Add an additional sanity check when reading regular file inodes.
A regular file if the file size is an exact multiple of the filesystem
block size cannot have a fragment. This is because by definition a
fragment block stores tailends which are not a whole block in size.
Signed-off-by: Phillip Lougher <phillip@...ashfs.org.uk>
---
fs/squashfs/inode.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index d5918eba27e3..77eec1772998 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -140,8 +140,17 @@ int squashfs_read_inode(struct inode *inode, long long ino)
if (err < 0)
goto failed_read;
+ inode->i_size = le32_to_cpu(sqsh_ino->file_size);
frag = le32_to_cpu(sqsh_ino->fragment);
if (frag != SQUASHFS_INVALID_FRAG) {
+ /*
+ * the file cannot have a fragment (tailend) and have a
+ * file size a multiple of the block size
+ */
+ if ((inode->i_size & (msblk->block_size - 1)) == 0) {
+ err = -EINVAL;
+ goto failed_read;
+ }
frag_offset = le32_to_cpu(sqsh_ino->offset);
frag_size = squashfs_frag_lookup(sb, frag, &frag_blk);
if (frag_size < 0) {
@@ -155,7 +164,6 @@ int squashfs_read_inode(struct inode *inode, long long ino)
}
set_nlink(inode, 1);
- inode->i_size = le32_to_cpu(sqsh_ino->file_size);
inode->i_fop = &generic_ro_fops;
inode->i_mode |= S_IFREG;
inode->i_blocks = ((inode->i_size - 1) >> 9) + 1;
@@ -183,8 +191,17 @@ int squashfs_read_inode(struct inode *inode, long long ino)
if (err < 0)
goto failed_read;
+ inode->i_size = le64_to_cpu(sqsh_ino->file_size);
frag = le32_to_cpu(sqsh_ino->fragment);
if (frag != SQUASHFS_INVALID_FRAG) {
+ /*
+ * the file cannot have a fragment (tailend) and have a
+ * file size a multiple of the block size
+ */
+ if ((inode->i_size & (msblk->block_size - 1)) == 0) {
+ err = -EINVAL;
+ goto failed_read;
+ }
frag_offset = le32_to_cpu(sqsh_ino->offset);
frag_size = squashfs_frag_lookup(sb, frag, &frag_blk);
if (frag_size < 0) {
@@ -199,7 +216,6 @@ int squashfs_read_inode(struct inode *inode, long long ino)
xattr_id = le32_to_cpu(sqsh_ino->xattr);
set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
- inode->i_size = le64_to_cpu(sqsh_ino->file_size);
inode->i_op = &squashfs_inode_ops;
inode->i_fop = &generic_ro_fops;
inode->i_mode |= S_IFREG;
--
2.39.5
Powered by blists - more mailing lists