xfs
[Top] [All Lists]

[PATCH] xfsprogs: skip freelist scans of corrupt agf

To: xfs-oss <xfs@xxxxxxxxxxx>
Subject: [PATCH] xfsprogs: skip freelist scans of corrupt agf
From: Eric Sandeen <sandeen@xxxxxxxxxxx>
Date: Sat, 09 Mar 2013 09:21:55 -0600
Delivered-to: xfs@xxxxxxxxxxx
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20130216 Thunderbird/17.0.3
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.

Thisis 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@xxxxxxxxxx>
---


diff --git a/db/check.c b/db/check.c
index e601e0a..35325b7 100644
--- a/db/check.c
+++ b/db/check.c
@@ -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]);
diff --git a/db/freesp.c b/db/freesp.c
index c4dabad..472b1f7 100644
--- a/db/freesp.c
+++ b/db/freesp.c
@@ -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);
diff --git a/repair/scan.c b/repair/scan.c
index 1d39bdc..6a62dff 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -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]);

<Prev in Thread] Current Thread [Next in Thread>