]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfsprogs: skip freelist scans of corrupt agf
authorEric Sandeen <sandeen@sandeen.net>
Sat, 9 Mar 2013 15:21:55 +0000 (15:21 +0000)
committerRich Johnston <rjohnston@sgi.com>
Mon, 11 Mar 2013 12:10:08 +0000 (07:10 -0500)
If an agf has bad values in the freelist, this can wreak
havoc if, for example, first > last and the loop
never exits; we index agfl->agfl_bno[i] off into the weeds.

If they're off, warn about it and skip the scan.

This is done both in xfs_check and xfs_db's freespace cmd.

Also fix uninit'd variable "i" from previous, similar fix
for xfs_repair.

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Rich Johnston <rjohnston@sgi.com>
db/check.c
db/freesp.c
repair/scan.c

index e601e0af0a54571e6987be5fe5878537317f635b..35325b7979447e6f5874951c9e68fe329a16a609 100644 (file)
@@ -4112,6 +4112,16 @@ scan_freelist(
                return;
        }
        i = be32_to_cpu(agf->agf_flfirst);
+
+       /* verify agf values before proceeding */
+       if (be32_to_cpu(agf->agf_flfirst) >= XFS_AGFL_SIZE(mp) ||
+           be32_to_cpu(agf->agf_fllast) >= XFS_AGFL_SIZE(mp)) {
+               dbprintf(_("agf %d freelist blocks bad, skipping "
+                         "freelist scan\n"), i);
+               pop_cur();
+               return;
+       }
+
        count = 0;
        for (;;) {
                bno = be32_to_cpu(agfl->agfl_bno[i]);
index c4dabad165909e844d32b3ec8ed4ea32fe380a26..472b1f7bc35560c67b53c647450db2c59b5fbd13 100644 (file)
@@ -239,6 +239,16 @@ scan_freelist(
                                XFS_FSS_TO_BB(mp, 1), DB_RING_IGN, NULL);
        agfl = iocur_top->data;
        i = be32_to_cpu(agf->agf_flfirst);
+
+       /* verify agf values before proceeding */
+       if (be32_to_cpu(agf->agf_flfirst) >= XFS_AGFL_SIZE(mp) ||
+           be32_to_cpu(agf->agf_fllast) >= XFS_AGFL_SIZE(mp)) {
+               dbprintf(_("agf %d freelist blocks bad, skipping "
+                         "freelist scan\n"), i);
+               pop_cur();
+               return;
+       }
+
        for (;;) {
                bno = be32_to_cpu(agfl->agfl_bno[i]);
                addtohist(seqno, bno, 1);
index 1d39bdc7dacb8574713313d2d238b39c4d9f8c4f..6a62dfff03448a754f964b1cc1e6914c75751a83 100644 (file)
@@ -1066,6 +1066,7 @@ scan_freelist(
                return;
        }
        agfl = XFS_BUF_TO_AGFL(agflbuf);
+       i = be32_to_cpu(agf->agf_flfirst);
 
        if (no_modify) {
                /* agf values not fixed in verify_set_agf, so recheck */
@@ -1078,7 +1079,6 @@ scan_freelist(
        } else /* should have been fixed in verify_set_agf() */
                ASSERT(0);
 
-       i = be32_to_cpu(agf->agf_flfirst);
        count = 0;
        for (;;) {
                bno = be32_to_cpu(agfl->agfl_bno[i]);