Author: kib
Date: Fri Oct 28 11:34:32 2016
New Revision: 308024
URL: https://svnweb.freebsd.org/changeset/base/308024

Log:
  Ensure that cluster allocations never allocate clusters outside the
  volume limits.  In particular:
  - Assert that usemap_alloc() and usemap_free() cluster number argument
    is valid.
  - In chainlength(), return 0 if cluster start is after the max cluster.
  - In chainlength(), cut the calculated cluster chain length at the max
    cluster.
  - For true paranoia, after the pm_inusemap is calculated in
    fillinusemap(), reset all bits in the array for clusters after the
    max cluster, as in-use.
  
  Reported and tested by:       pho
  Sponsored by: The FreeBSD Foundation
  MFC after:    2 weeks

Modified:
  head/sys/fs/msdosfs/msdosfs_fat.c

Modified: head/sys/fs/msdosfs/msdosfs_fat.c
==============================================================================
--- head/sys/fs/msdosfs/msdosfs_fat.c   Fri Oct 28 11:26:44 2016        
(r308023)
+++ head/sys/fs/msdosfs/msdosfs_fat.c   Fri Oct 28 11:34:32 2016        
(r308024)
@@ -382,6 +382,8 @@ usemap_alloc(struct msdosfsmount *pmp, u
 
        MSDOSFS_ASSERT_MP_LOCKED(pmp);
 
+       KASSERT(cn <= pmp->pm_maxcluster, ("cn too large %lu %lu", cn,
+           pmp->pm_maxcluster));
        KASSERT((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0,
            ("usemap_alloc on ro msdosfs mount"));
        KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS)))
@@ -398,6 +400,9 @@ usemap_free(struct msdosfsmount *pmp, u_
 {
 
        MSDOSFS_ASSERT_MP_LOCKED(pmp);
+
+       KASSERT(cn <= pmp->pm_maxcluster, ("cn too large %lu %lu", cn,
+           pmp->pm_maxcluster));
        KASSERT((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0,
            ("usemap_free on ro msdosfs mount"));
        pmp->pm_freeclustercount++;
@@ -637,6 +642,8 @@ chainlength(struct msdosfsmount *pmp, u_
 
        MSDOSFS_ASSERT_MP_LOCKED(pmp);
 
+       if (start > pmp->pm_maxcluster)
+               return (0);
        max_idx = pmp->pm_maxcluster / N_INUSEBITS;
        idx = start / N_INUSEBITS;
        start %= N_INUSEBITS;
@@ -644,11 +651,18 @@ chainlength(struct msdosfsmount *pmp, u_
        map &= ~((1 << start) - 1);
        if (map) {
                len = ffs(map) - 1 - start;
-               return (len > count ? count : len);
+               len = MIN(len, count);
+               if (start + len > pmp->pm_maxcluster)
+                       len = pmp->pm_maxcluster - start + 1;
+               return (len);
        }
        len = N_INUSEBITS - start;
-       if (len >= count)
-               return (count);
+       if (len >= count) {
+               len = count;
+               if (start + len > pmp->pm_maxcluster)
+                       len = pmp->pm_maxcluster - start + 1;
+               return (len);
+       }
        while (++idx <= max_idx) {
                if (len >= count)
                        break;
@@ -659,7 +673,10 @@ chainlength(struct msdosfsmount *pmp, u_
                }
                len += N_INUSEBITS;
        }
-       return (len > count ? count : len);
+       len = MIN(len, count);
+       if (start + len > pmp->pm_maxcluster)
+               len = pmp->pm_maxcluster - start + 1;
+       return (len);
 }
 
 /*
@@ -918,6 +935,11 @@ fillinusemap(struct msdosfsmount *pmp)
        }
        if (bp != NULL)
                brelse(bp);
+
+       for (cn = pmp->pm_maxcluster + 1; cn < (pmp->pm_maxcluster +
+           N_INUSEBITS) / N_INUSEBITS; cn++)
+               pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS);
+
        return (0);
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to