git: ba2c98389b78 - main - msdosfs: sanity check sector count from BPB

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sat, 08 Jan 2022 04:29:35 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=ba2c98389b78b548aedac0be53121df909c3fe2f

commit ba2c98389b78b548aedac0be53121df909c3fe2f
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-12-30 19:45:40 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-01-08 03:41:44 +0000

    msdosfs: sanity check sector count from BPB
    
    We use sector count to size the FAT inuse bitset.  If sector count is
    corrupted, kernel might be tricked into doing unbound allocation.
    Ensure that the sector count does not exceed the actual volume size.
    
    In collaboration with:  pho
    Reviewed by:    markj, mckusick
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D33721
---
 sys/fs/msdosfs/msdosfs_vfsops.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
index 5eb6ad04eab9..8ef46e063420 100644
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -558,6 +558,14 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp)
 	}
 
 	pmp->pm_HugeSectors *= pmp->pm_BlkPerSec;
+	if ((off_t)pmp->pm_HugeSectors * pmp->pm_BytesPerSec <
+	    pmp->pm_HugeSectors /* overflow */ ||
+	    (off_t)pmp->pm_HugeSectors * pmp->pm_BytesPerSec >
+	    cp->provider->mediasize /* past end of vol */) {
+		error = EINVAL;
+		goto error_exit;
+	}
+
 	pmp->pm_HiddenSects *= pmp->pm_BlkPerSec;	/* XXX not used? */
 	pmp->pm_FATsecs     *= pmp->pm_BlkPerSec;
 	SecPerClust         *= pmp->pm_BlkPerSec;
@@ -577,6 +585,10 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp)
 		pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
 	}
 
+	if (pmp->pm_HugeSectors <= pmp->pm_firstcluster) {
+		error = EINVAL;
+		goto error_exit;
+	}
 	pmp->pm_maxcluster = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
 	    SecPerClust + 1;
 	pmp->pm_fatsize = pmp->pm_FATsecs * DEV_BSIZE;	/* XXX not used? */