Re: [PATCH V7] squashfs: Add symlink size check in squash_read_inode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 03/08/2024 08:43, Lizhi Xu wrote:
syzbot report KMSAN: uninit-value in pick_link, the root cause is that
squashfs_symlink_read_folio did not check the length, resulting in folio
not being initialized and did not return the corresponding error code.

The length is calculated from i_size, this case is about symlink, so i_size
value is derived from symlink_size, so it is necessary to add a check to
confirm that symlink_size value is valid, otherwise an error -EINVAL will
be returned.

If symlink_size is too large, it may result in a negative value when
calculating length in squashfs_symlink_read_folio due to int overflow,
and its value must be greater than PAGE_SIZE at this time.

Reported-and-tested-by: syzbot+24ac24ff58dc5b0d26b9@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=24ac24ff58dc5b0d26b9
Signed-off-by: Lizhi Xu <lizhi.xu@xxxxxxxxxxxxx>
---
  fs/squashfs/inode.c | 9 ++++++++-
  1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index 16bd693d0b3a..bed6764e4461 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -273,14 +273,21 @@ int squashfs_read_inode(struct inode *inode, long long ino)
  	case SQUASHFS_SYMLINK_TYPE:
  	case SQUASHFS_LSYMLINK_TYPE: {
  		struct squashfs_symlink_inode *sqsh_ino = &squashfs_ino.symlink;
+		loff_t symlink_size;
err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
  				sizeof(*sqsh_ino));
  		if (err < 0)
  			goto failed_read;
+ symlink_size = le32_to_cpu(sqsh_ino->symlink_size);
+		if (symlink_size > PAGE_SIZE) {
+			ERROR("Corrupted symlink, size [%llu]\n", symlink_size);
+			return -EINVAL;
+		}
+
  		set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
-		inode->i_size = le32_to_cpu(sqsh_ino->symlink_size);
+		inode->i_size = symlink_size;

NACK. I see no reason to introduce an intermediate variable here.

Please do what Al Viro suggested.

Thanks

Phillip Lougher
--
Squashfs author and maintainer

BTW I have been on vacation since last week, and only saw
this today.

  		inode->i_op = &squashfs_symlink_inode_ops;
  		inode_nohighmem(inode);
  		inode->i_data.a_ops = &squashfs_symlink_aops;





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux