sysv_new_inode() uses the on-disk free-inode count (s_ninode) as an index into the free-inode cache (s_inode, SYSV_NICINOD entries) without bounding it, and sysv_new_block() does the same with s_nfree and the free-block cache (s_free, SYSV_NICFREE entries). A crafted superblock with an inflated count causes an out-of-bounds read far past the cache array (KASAN), reachable from a mounted crafted SysV image by creating a file. The on-disk format requires s_ninode <= SYSV_NICINOD and s_nfree <= SYSV_NICFREE; reject a superblock that violates this at mount time, which protects both allocation paths. Signed-off-by: Marouane El Moufid --- fs/sysv/super.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/sysv/super.c b/fs/sysv/super.c --- a/fs/sysv/super.c +++ b/fs/sysv/super.c @@ -315,6 +315,14 @@ if (sbi->s_firstdatazone < sbi->s_firstinodezone) return 0; + if (fs16_to_cpu(sbi, *sbi->s_sb_fic_count) > sbi->s_fic_size || + fs16_to_cpu(sbi, *sbi->s_bcache_count) > sbi->s_flc_size) { + if (!silent) + printk("SysV FS: corrupt free-list count in superblock on device %s\n", + sb->s_id); + return 0; + } + sbi->s_ndatazones = sbi->s_nzones - sbi->s_firstdatazone; sbi->s_inodes_per_block = bsize >> 6; sbi->s_inodes_per_block_1 = (bsize >> 6)-1;