| From f165bd0d32998a59aab2ad1b71f75ab4cb18c288 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 14 Oct 2020 22:01:09 +0530 |
| Subject: gfs2: add validation checks for size of superblock |
| |
| From: Anant Thazhemadam <anant.thazhemadam@gmail.com> |
| |
| [ Upstream commit 0ddc5154b24c96f20e94d653b0a814438de6032b ] |
| |
| In gfs2_check_sb(), no validation checks are performed with regards to |
| the size of the superblock. |
| syzkaller detected a slab-out-of-bounds bug that was primarily caused |
| because the block size for a superblock was set to zero. |
| A valid size for a superblock is a power of 2 between 512 and PAGE_SIZE. |
| Performing validation checks and ensuring that the size of the superblock |
| is valid fixes this bug. |
| |
| Reported-by: syzbot+af90d47a37376844e731@syzkaller.appspotmail.com |
| Tested-by: syzbot+af90d47a37376844e731@syzkaller.appspotmail.com |
| Suggested-by: Andrew Price <anprice@redhat.com> |
| Signed-off-by: Anant Thazhemadam <anant.thazhemadam@gmail.com> |
| [Minor code reordering.] |
| Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/gfs2/ops_fstype.c | 18 +++++++++++------- |
| 1 file changed, 11 insertions(+), 7 deletions(-) |
| |
| diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c |
| index 5bd602a290f72..03c33fc03c055 100644 |
| --- a/fs/gfs2/ops_fstype.c |
| +++ b/fs/gfs2/ops_fstype.c |
| @@ -169,15 +169,19 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent) |
| return -EINVAL; |
| } |
| |
| - /* If format numbers match exactly, we're done. */ |
| - |
| - if (sb->sb_fs_format == GFS2_FORMAT_FS && |
| - sb->sb_multihost_format == GFS2_FORMAT_MULTI) |
| - return 0; |
| + if (sb->sb_fs_format != GFS2_FORMAT_FS || |
| + sb->sb_multihost_format != GFS2_FORMAT_MULTI) { |
| + fs_warn(sdp, "Unknown on-disk format, unable to mount\n"); |
| + return -EINVAL; |
| + } |
| |
| - fs_warn(sdp, "Unknown on-disk format, unable to mount\n"); |
| + if (sb->sb_bsize < 512 || sb->sb_bsize > PAGE_SIZE || |
| + (sb->sb_bsize & (sb->sb_bsize - 1))) { |
| + pr_warn("Invalid superblock size\n"); |
| + return -EINVAL; |
| + } |
| |
| - return -EINVAL; |
| + return 0; |
| } |
| |
| static void end_bio_io_page(struct bio *bio) |
| -- |
| 2.27.0 |
| |