Hi, there was a shift-out-bounds bug in minix_statfs in fs/minix/inode.c founded by my custom syzkaller and reproduced in linux-5.13.0-rc6+. #### Simply analyze the vulnerability principle, First, mount a minix file system by minix_fill_super() and initialize some custom basic data. the code is as follows: ``` static int minix_fill_super(struct super_block *s, void *data, int silent) { struct buffer_head *bh; struct buffer_head **map; struct minix_super_block *ms; struct minix3_super_block *m3s = NULL; unsigned long i, block; struct inode *root_inode; struct minix_sb_info *sbi; int ret = -EINVAL; sbi = kzalloc(sizeof(struct minix_sb_info), GFP_KERNEL); if (!sbi) return -ENOMEM; s->s_fs_info = sbi; BUILD_BUG_ON(32 != sizeof (struct minix_inode)); BUILD_BUG_ON(64 != sizeof(struct minix2_inode)); if (!sb_set_blocksize(s, BLOCK_SIZE)) goto out_bad_hblock; if (!(bh = sb_bread(s, 1))) /// -----------------> get minix_super_block's data from super_block goto out_bad_sb; ms = (struct minix_super_block *) bh->b_data; /// --------------> set minix_super_block pointer sbi->s_ms = ms; sbi->s_sbh = bh; sbi->s_mount_state = ms->s_state; sbi->s_ninodes = ms->s_ninodes; sbi->s_nzones = ms->s_nzones; sbi->s_imap_blocks = ms->s_imap_blocks; sbi->s_zmap_blocks = ms->s_zmap_blocks; sbi->s_firstdatazone = ms->s_firstdatazone; sbi->s_log_zone_size = ms->s_log_zone_size; // ------------------> set sbi->s_log_zone_size s->s_maxbytes = ms->s_max_size; s->s_magic = ms->s_magic; ``` Set bh->b_data to sbi. Initialize minix_sb_info by minix_super_block ’s data After the file system is mounted, we can call the statfs syscall and it could invoke the minix_statfs function. the code is as follows: ``` static int minix_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; struct minix_sb_info *sbi = minix_sb(sb); u64 id = huge_encode_dev(sb->s_bdev->bd_dev); buf->f_type = sb->s_magic; buf->f_bsize = sb->s_blocksize; buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size; // -----> shift left buf->f_bfree = minix_count_free_blocks(sb); buf->f_bavail = buf->f_bfree; buf->f_files = sbi->s_ninodes; buf->f_ffree = minix_count_free_inodes(sb); buf->f_namelen = sbi->s_namelen; buf->f_fsid = u64_to_fsid(id); return 0; } ``` if set sbi->s_log_zone_size as a lager num, the (sbi->s_nzones-sbi->s_firstdatazone) will be shift left out of bounds from the 64-bit type 'long unsigned int'. #### crash logs is as follows: ``` [ 1512.826425][ T8010] loop0: detected capacity change from 0 to 16 [ 1512.829202][ T8010] ================================================================================ [ 1512.830892][ T8010] UBSAN: shift-out-of-bounds in fs/minix/inode.c:380:57 [ 1512.851019][ T8010] shift exponent 1024 is too large for 64-bit type 'long unsigned int' [ 1512.852875][ T8010] CPU: 0 PID: 8010 Comm: minix_statfs Not tainted 5.13.0-rc6+ #21 [ 1512.854333][ T8010] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1 04/01/2014 [ 1512.856165][ T8010] Call Trace: [ 1512.856809][ T8010] dump_stack+0x7f/0xad [ 1512.857629][ T8010] ubsan_epilogue+0x5/0x40 [ 1512.858417][ T8010] __ubsan_handle_shift_out_of_bounds.cold+0x61/0x10e [ 1512.859634][ T8010] ? __lock_acquire+0x3b6/0x2680 [ 1512.860566][ T8010] minix_statfs.cold+0x16/0x1f [ 1512.861453][ T8010] statfs_by_dentry+0x48/0x70 [ 1512.862314][ T8010] vfs_statfs+0x11/0xc0 [ 1512.863095][ T8010] fd_statfs+0x29/0x60 [ 1512.863860][ T8010] __do_sys_fstatfs+0x20/0x50 [ 1512.864733][ T8010] do_syscall_64+0x3a/0xb0 [ 1512.865820][ T8010] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 1512.866948][ T8010] RIP: 0033:0x44e74d [ 1512.867804][ T8010] Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff 8 [ 1512.871739][ T8010] RSP: 002b:00007ffe06c55808 EFLAGS: 00000217 ORIG_RAX: 000000000000008a [ 1512.873195][ T8010] RAX: ffffffffffffffda RBX: 0000000000400530 RCX: 000000000044e74d [ 1512.874585][ T8010] RDX: 000000000044d9f7 RSI: 0000000000000000 RDI: 0000000000000005 [ 1512.875939][ T8010] RBP: 00007ffe06c55820 R08: 00007ffe06c55664 R09: 0000000000000000 [ 1512.877284][ T8010] R10: 00007ffe06c556e0 R11: 0000000000000217 R12: 0000000000403750 [ 1512.878665][ T8010] R13: 0000000000000000 R14: 00000000004c6018 R15: 0000000000000000 [ 1512.881676][ T8010] ================================================================================ [ 1512.883289][ T8010] Kernel panic - not syncing: panic_on_warn set ... [ 1512.884457][ T8010] CPU: 0 PID: 8010 Comm: minix_statfs Not tainted 5.13.0-rc6+ #21 [ 1512.885851][ T8010] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1 04/01/2014 [ 1512.887598][ T8010] Call Trace: [ 1512.888186][ T8010] dump_stack+0x7f/0xad [ 1512.888935][ T8010] panic+0x147/0x31a [ 1512.889623][ T8010] ubsan_epilogue+0x3f/0x40 [ 1512.890392][ T8010] __ubsan_handle_shift_out_of_bounds.cold+0x61/0x10e [ 1512.891527][ T8010] ? __lock_acquire+0x3b6/0x2680 [ 1512.892353][ T8010] minix_statfs.cold+0x16/0x1f [ 1512.893202][ T8010] statfs_by_dentry+0x48/0x70 [ 1512.894033][ T8010] vfs_statfs+0x11/0xc0 [ 1512.894759][ T8010] fd_statfs+0x29/0x60 [ 1512.895483][ T8010] __do_sys_fstatfs+0x20/0x50 [ 1512.896298][ T8010] do_syscall_64+0x3a/0xb0 [ 1512.897103][ T8010] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 1512.898136][ T8010] RIP: 0033:0x44e74d [ 1512.898823][ T8010] Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff 8 [ 1512.902284][ T8010] RSP: 002b:00007ffe06c55808 EFLAGS: 00000217 ORIG_RAX: 000000000000008a [ 1512.903771][ T8010] RAX: ffffffffffffffda RBX: 0000000000400530 RCX: 000000000044e74d [ 1512.905263][ T8010] RDX: 000000000044d9f7 RSI: 0000000000000000 RDI: 0000000000000005 [ 1512.906723][ T8010] RBP: 00007ffe06c55820 R08: 00007ffe06c55664 R09: 0000000000000000 [ 1512.908181][ T8010] R10: 00007ffe06c556e0 R11: 0000000000000217 R12: 0000000000403750 [ 1512.909661][ T8010] R13: 0000000000000000 R14: 00000000004c6018 R15: 0000000000000000 [ 1512.911356][ T8010] Kernel Offset: disabled [ 1512.912216][ T8010] Rebooting in 86400 seconds.. ``` The attachment is a reproduction. Regards, butt3rflyh4ck -- Active Defense Lab of Venustech
Attachment:
repro.cprog
Description: Binary data