]> granicus.if.org Git - zfs/commitdiff
Fix for recent zdb -h | -i crashes (seg fault)
authorDon Brady <don.brady@intel.com>
Wed, 24 Jun 2015 18:17:36 +0000 (12:17 -0600)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 26 Jun 2015 21:14:31 +0000 (14:14 -0700)
Allocating SPA_MAXBLOCKSIZE on the stack is a bad idea (even with the
old 128K size). Use malloc instead when allocating temporary block
buffer memory.

Signed-off-by: Don Brady <don.brady@intel.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3522

cmd/zdb/zdb.c
cmd/zdb/zdb_il.c

index 800d49867dea7baa1d2f3e259165f1bcfbb01022..56f56700fc10058f642df2a818ecb8731e7dd0ed 100644 (file)
@@ -1070,7 +1070,7 @@ static void
 dump_history(spa_t *spa)
 {
        nvlist_t **events = NULL;
-       char buf[SPA_MAXBLOCKSIZE];
+       char *buf;
        uint64_t resid, len, off = 0;
        uint_t num = 0;
        int error;
@@ -1080,12 +1080,19 @@ dump_history(spa_t *spa)
        char internalstr[MAXPATHLEN];
        int i;
 
+       if ((buf = malloc(SPA_OLD_MAXBLOCKSIZE)) == NULL) {
+               (void) fprintf(stderr, "%s: unable to allocate I/O buffer\n",
+                   __func__);
+               return;
+       }
+
        do {
-               len = sizeof (buf);
+               len = SPA_OLD_MAXBLOCKSIZE;
 
                if ((error = spa_history_get(spa, &off, &len, buf)) != 0) {
                        (void) fprintf(stderr, "Unable to read history: "
                            "error %d\n", error);
+                       free(buf);
                        return;
                }
 
@@ -1136,6 +1143,7 @@ next:
                        dump_nvlist(events[i], 2);
                }
        }
+       free(buf);
 }
 
 /*ARGSUSED*/
index b85ef7ddd97e48f202076841420a93607f6adb6e..93b905793d601b7c7a64693cb4e4b5bb1910bd32 100644 (file)
@@ -124,7 +124,7 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, lr_write_t *lr)
        char *data, *dlimit;
        blkptr_t *bp = &lr->lr_blkptr;
        zbookmark_phys_t zb;
-       char buf[SPA_MAXBLOCKSIZE];
+       char *buf;
        int verbose = MAX(dump_opt['d'], dump_opt['i']);
        int error;
 
@@ -135,6 +135,9 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, lr_write_t *lr)
        if (txtype == TX_WRITE2 || verbose < 5)
                return;
 
+       if ((buf = malloc(SPA_MAXBLOCKSIZE)) == NULL)
+               return;
+
        if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
                (void) printf("%shas blkptr, %s\n", prefix,
                    !BP_IS_HOLE(bp) &&
@@ -145,13 +148,13 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, lr_write_t *lr)
                if (BP_IS_HOLE(bp)) {
                        (void) printf("\t\t\tLSIZE 0x%llx\n",
                            (u_longlong_t)BP_GET_LSIZE(bp));
-                       bzero(buf, sizeof (buf));
+                       bzero(buf, SPA_MAXBLOCKSIZE);
                        (void) printf("%s<hole>\n", prefix);
-                       return;
+                       goto exit;
                }
                if (bp->blk_birth < zilog->zl_header->zh_claim_txg) {
                        (void) printf("%s<block already committed>\n", prefix);
-                       return;
+                       goto exit;
                }
 
                SET_BOOKMARK(&zb, dmu_objset_id(zilog->zl_os),
@@ -162,7 +165,7 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, lr_write_t *lr)
                    bp, buf, BP_GET_LSIZE(bp), NULL, NULL,
                    ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL, &zb));
                if (error)
-                       return;
+                       goto exit;
                data = buf;
        } else {
                data = (char *)(lr + 1);
@@ -180,6 +183,8 @@ zil_prt_rec_write(zilog_t *zilog, int txtype, lr_write_t *lr)
                data++;
        }
        (void) printf("\n");
+exit:
+       free(buf);
 }
 
 /* ARGSUSED */