diff options
author | ahl <none@none> | 2008-04-22 17:56:10 -0700 |
---|---|---|
committer | ahl <none@none> | 2008-04-22 17:56:10 -0700 |
commit | 04bb726ecc2ce091dd01d32316d6730863741df0 (patch) | |
tree | edb5652f9faf15d885f98e48c0c7fad1aa974612 /usr/src/lib/libzfs/common | |
parent | 1e1fedba29f2d95e0defbb93d1ac3da48c89b992 (diff) | |
download | illumos-joyent-04bb726ecc2ce091dd01d32316d6730863741df0.tar.gz |
6691138 dump_filesystem() can lead to SIGSEGV
Diffstat (limited to 'usr/src/lib/libzfs/common')
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_sendrecv.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_sendrecv.c b/usr/src/lib/libzfs/common/libzfs_sendrecv.c index cbeb5284ff..2d44f37a49 100644 --- a/usr/src/lib/libzfs/common/libzfs_sendrecv.c +++ b/usr/src/lib/libzfs/common/libzfs_sendrecv.c @@ -593,12 +593,16 @@ dump_filesystem(zfs_handle_t *zhp, void *arg) (void) snprintf(snapname, sizeof (snapname), "%s@%s", zfs_get_name(zhp), sdd->tosnap); snapzhp = zfs_open(zhp->zfs_hdl, snapname, ZFS_TYPE_SNAPSHOT); - rv = dump_ioctl(snapzhp, - missingfrom ? NULL : sdd->fromsnap, - sdd->fromorigin || missingfrom, - sdd->outfd); - sdd->seento = B_TRUE; - zfs_close(snapzhp); + if (snapzhp == NULL) { + rv = -1; + } else { + rv = dump_ioctl(snapzhp, + missingfrom ? NULL : sdd->fromsnap, + sdd->fromorigin || missingfrom, + sdd->outfd); + sdd->seento = B_TRUE; + zfs_close(snapzhp); + } } return (rv); @@ -644,6 +648,8 @@ again: } zhp = zfs_open(rzhp->zfs_hdl, fsname, ZFS_TYPE_DATASET); + if (zhp == NULL) + return (-1); err = dump_filesystem(zhp, sdd); VERIFY(nvlist_add_boolean(fslist, "sent") == 0); progress = B_TRUE; @@ -1024,30 +1030,36 @@ guid_to_name(libzfs_handle_t *hdl, const char *parent, uint64_t guid, /* * Return true if dataset guid1 is created before guid2. */ -static boolean_t +static int created_before(libzfs_handle_t *hdl, avl_tree_t *avl, uint64_t guid1, uint64_t guid2) { nvlist_t *nvfs; char *fsname, *snapname; char buf[ZFS_MAXNAMELEN]; - boolean_t rv; + int rv; zfs_node_t zn1, zn2; if (guid2 == 0) - return (B_FALSE); + return (0); if (guid1 == 0) - return (B_TRUE); + return (1); nvfs = fsavl_find(avl, guid1, &snapname); VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname)); (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname); zn1.zn_handle = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT); + if (zn1.zn_handle == NULL) + return (-1); nvfs = fsavl_find(avl, guid2, &snapname); VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname)); (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname); zn2.zn_handle = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT); + if (zn2.zn_handle == NULL) { + zfs_close(zn2.zn_handle); + return (-1); + } rv = (zfs_snapshot_compare(&zn1, &zn2) == -1); @@ -1124,8 +1136,9 @@ again: (void) nvlist_lookup_uint64(stream_nvfs, "origin", &stream_originguid); if (stream_nvfs && originguid != stream_originguid) { - if (created_before(hdl, local_avl, stream_originguid, - originguid)) { + switch (created_before(hdl, local_avl, + stream_originguid, originguid)) { + case 1: { /* promote it! */ zfs_cmd_t zc = { 0 }; nvlist_t *origin_nvfs; @@ -1145,6 +1158,14 @@ again: error = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc); if (error == 0) progress = B_TRUE; + break; + } + default: + break; + case -1: + fsavl_destroy(local_avl); + nvlist_free(local_nv); + return (-1); } /* * We had/have the wrong origin, therefore our @@ -1858,7 +1879,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, h = zfs_open(hdl, zc.zc_value, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); *cp = '@'; - if (h) { + if (h != NULL) { if (h->zfs_type == ZFS_TYPE_VOLUME) { err = zvol_create_link(hdl, h->zfs_name); if (err == 0 && ioctl_err == 0) @@ -1867,7 +1888,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, } else if (newfs) { err = zfs_mount(h, NULL, 0); } - zfs_close(h); + zfs_close(h); } } |