Author: delphij
Date: Thu Oct  1 18:58:06 2020
New Revision: 366338
URL: https://svnweb.freebsd.org/changeset/base/366338

Log:
  MFS r366305: MFC r366064, r366065, r366215
  
  sbin/fsck_msdosfs: Fix an integer overflow on 32-bit platforms
  
  Approved by:  re (gjb)

Modified:
  releng/12.2/sbin/fsck_msdosfs/dir.c
Directory Properties:
  releng/12.2/   (props changed)

Modified: releng/12.2/sbin/fsck_msdosfs/dir.c
==============================================================================
--- releng/12.2/sbin/fsck_msdosfs/dir.c Thu Oct  1 18:56:44 2020        
(r366337)
+++ releng/12.2/sbin/fsck_msdosfs/dir.c Thu Oct  1 18:58:06 2020        
(r366338)
@@ -388,7 +388,8 @@ static int
 checksize(struct fat_descriptor *fat, u_char *p, struct dosDirEntry *dir)
 {
        int ret = FSOK;
-       size_t physicalSize;
+       size_t chainsize;
+       u_int64_t physicalSize;
        struct bootblock *boot;
 
        boot = fat_get_boot(fat);
@@ -401,9 +402,9 @@ checksize(struct fat_descriptor *fat, u_char *p, struc
        } else {
                if (!fat_is_valid_cl(fat, dir->head))
                        return FSERROR;
-               ret = checkchain(fat, dir->head, &physicalSize);
+               ret = checkchain(fat, dir->head, &chainsize);
                /*
-                * Upon return, physicalSize would hold the chain length
+                * Upon return, chainsize would hold the chain length
                 * that checkchain() was able to validate, but if the user
                 * refused the proposed repair, it would be unsafe to
                 * proceed with directory entry fix, so bail out in that
@@ -412,11 +413,17 @@ checksize(struct fat_descriptor *fat, u_char *p, struc
                if (ret == FSERROR) {
                        return (FSERROR);
                }
-               physicalSize *= boot->ClusterSize;
+               /*
+                * The maximum file size on FAT32 is 4GiB - 1, which
+                * will occupy a cluster chain of exactly 4GiB in
+                * size.  On 32-bit platforms, since size_t is 32-bit,
+                * it would wrap back to 0.
+                */
+               physicalSize = (u_int64_t)chainsize * boot->ClusterSize;
        }
        if (physicalSize < dir->size) {
-               pwarn("size of %s is %u, should at most be %zu\n",
-                     fullpath(dir), dir->size, physicalSize);
+               pwarn("size of %s is %u, should at most be %ju\n",
+                     fullpath(dir), dir->size, (uintmax_t)physicalSize);
                if (ask(1, "Truncate")) {
                        dir->size = physicalSize;
                        p[28] = (u_char)physicalSize;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to