On 19.02.25 15:18, Sascha Hauer wrote: > In squashfs_get_link() we have: > > int length = min_t(int, i_size_read(inode), PAGE_SIZE); > > The inode size is a 64bit number directly read from the device which > is interpreted as a 32bit signed number above. An inode size with the > lower 32bits set to 0xffffffff results in length being -1. Later we > do a: > > symlink = malloc(length + 1); > > With length being -1 this results in allocating a zero size buffer which > is then overwritten by following code. > > Fix this by first making sure that the inode length is positive. > Afterwards limit the length to the desired range, explicitly using > loff_t as the type to compare to make sure we do not truncate the > original data type during comparison. > > Reported-by: Jonathan Bar Or <jonathanbaror@xxxxxxxxx> > Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> Reviewed-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> > --- > fs/squashfs/symlink.c | 8 ++++++-- > 1 file changed, 6 insertions(+), 2 deletions(-) > > diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c > index 40b9bdcc8b..cb14eb20a5 100644 > --- a/fs/squashfs/symlink.c > +++ b/fs/squashfs/symlink.c > @@ -43,16 +43,20 @@ > static const char *squashfs_get_link(struct dentry *dentry, struct inode *inode) > { > struct super_block *sb = inode->i_sb; > - int index = 0; > u64 block = squashfs_i(inode)->start; > int offset = squashfs_i(inode)->offset; > - int length = min_t(int, i_size_read(inode) - index, PAGE_SIZE); > + size_t length; > int bytes; > unsigned char *symlink; > > TRACE("Entered squashfs_symlink_readpage, start block " > "%llx, offset %x\n", block, offset); > > + if (i_size_read(inode) < 0) > + return NULL; > + > + length = min_t(loff_t, i_size_read(inode), PAGE_SIZE); > + > symlink = malloc(length + 1); > if (!symlink) > return NULL; -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |