NetBSD-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Unable to fsck 4.5TB FFSv2 fs



On Sep 25, 12:15pm, netbsd%precedence.co.uk@localhost (Stephen Borrill) wrote:
-- Subject: Re: Unable to fsck 4.5TB FFSv2 fs

| ** /dev/rld1d
| ** Last Mounted on /usr/backup
| ** Phase 1 - Check Blocks and Sizes
| cannot alloc 4294967292 bytes for inoinfo

that is 0xfffffffc which looks very fishy. This patch adds overflow detection,
can you test it?

Index: pass1.c
===================================================================
RCS file: /cvsroot/src/sbin/fsck_ffs/pass1.c,v
retrieving revision 1.44
diff -u -u -r1.44 pass1.c
--- pass1.c     23 Feb 2008 21:41:48 -0000      1.44
+++ pass1.c     25 Sep 2008 15:47:20 -0000
@@ -66,7 +66,8 @@
 void
 pass1(void)
 {
-       ino_t inumber, inosused;
+       ino_t inumber, inosused, ninosused;
+       size_t inospace;
        int c;
        daddr_t i, cgd;
        struct inodesc idesc;
@@ -151,12 +152,19 @@
                        inostathead[c].il_stat = 0;
                        continue;
                }
-               info = calloc((unsigned)inosused, sizeof(struct inostat));
+               inospace = inosused * sizeof(*info);
+               if (inospace / sizeof(*info) != inosused) {
+                       pfatal("too many inodes %llu\n", (unsigned long long)
+                           inosused);
+                       exit(FSCK_EXIT_CHECK_FAILED);
+               }
+               info = malloc(inospace);
                if (info == NULL) {
-                       pfatal("cannot alloc %u bytes for inoinfo\n",
-                           (unsigned)(sizeof(struct inostat) * inosused));
+                       pfatal("cannot alloc %zu bytes for inoinfo\n",
+                           inospace);
                        exit(FSCK_EXIT_CHECK_FAILED);
                }
+               (void)memset(info, 0, inospace);
                inostathead[c].il_stat = info;
                /*
                 * Scan the allocated inodes.
@@ -178,24 +186,33 @@
                 * really found.
                 */
                if (lastino < (c * sblock->fs_ipg))
-                       inosused = 0;
+                       ninosused = 0;
                else
-                       inosused = lastino - (c * sblock->fs_ipg);
-               inostathead[c].il_numalloced = inosused;
-               if (inosused == 0) {
+                       ninosused = lastino - (c * sblock->fs_ipg);
+               inostathead[c].il_numalloced = ninosused;
+               if (ninosused == 0) {
                        free(inostathead[c].il_stat);
                        inostathead[c].il_stat = 0;
                        continue;
                }
-               info = calloc((unsigned)inosused, sizeof(struct inostat));
-               if (info == NULL) {
-                       pfatal("cannot alloc %u bytes for inoinfo\n",
-                           (unsigned)(sizeof(struct inostat) * inosused));
-                       exit(FSCK_EXIT_CHECK_FAILED);
+               if (ninosused != inosused) {
+                       struct inostat *ninfo;
+                       size_t ninospace = ninosused * sizeof(*ninfo);
+                       if (ninospace / sizeof(*info) != ninosused) {
+                               pfatal("too many inodes %llu\n",
+                                   (unsigned long long)ninosused);
+                               exit(FSCK_EXIT_CHECK_FAILED);
+                       }
+                       ninfo = realloc(info, ninosused);
+                       if (ninfo == NULL) {
+                               pfatal("cannot realloc %zu bytes to %zu "
+                                   "for inoinfo\n", inospace, ninospace);
+                               exit(FSCK_EXIT_CHECK_FAILED);
+                       }
+                       if (ninosused > inosused)
+                               (void)memset(&ninfo[inosused], 0, ninospace - 
inospace);
+                       inostathead[c].il_stat = ninfo;
                }
-               memmove(info, inostathead[c].il_stat, inosused * sizeof(*info));
-               free(inostathead[c].il_stat);
-               inostathead[c].il_stat = info;
        }
 #ifdef PROGRESS
        if (!preen)


Home | Main Index | Thread Index | Old Index