[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240803040729.1677477-1-lizhi.xu@windriver.com>
Date: Sat, 3 Aug 2024 12:07:29 +0800
From: Lizhi Xu <lizhi.xu@...driver.com>
To: <viro@...iv.linux.org.uk>
CC: <brauner@...nel.org>, <jack@...e.cz>, <linux-fsdevel@...r.kernel.org>,
<linux-kernel@...r.kernel.org>, <lizhi.xu@...driver.com>,
<phillip@...ashfs.org.uk>, <squashfs-devel@...ts.sourceforge.net>,
<syzbot+24ac24ff58dc5b0d26b9@...kaller.appspotmail.com>,
<syzkaller-bugs@...glegroups.com>
Subject: [PATCH V6] squashfs: Add symlink size check in squash_read_inode
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
when i_size is initialized to confirm that its value is correct, otherwise
an error -EINVAL will be returned.
If symlink_size is too large, it will result in a negative value when
calculating length in squashfs_symlink_read_folio, and its value must
be greater than PAGE_SIZE at this time.
Reported-and-tested-by: syzbot+24ac24ff58dc5b0d26b9@...kaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=24ac24ff58dc5b0d26b9
Signed-off-by: Lizhi Xu <lizhi.xu@...driver.com>
---
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;
inode->i_op = &squashfs_symlink_inode_ops;
inode_nohighmem(inode);
inode->i_data.a_ops = &squashfs_symlink_aops;
--
2.43.0
Powered by blists - more mailing lists