[PATCH] fs/sysv: validate free-list counts from the superblock

From: Marouane El Moufid

Date: Sun Oct 25 2026 - 18:04:43 EST


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 <eun0us@xxxxxxxxxxx>
---
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;