From a425f5bff92f2db78f588543f49ce3abbd98a7f9 Mon Sep 17 00:00:00 2001 From: luozhengzheng Date: Thu, 1 Sep 2016 10:23:10 +0800 Subject: [PATCH] Fix memleak in zfs_do_* and zpool_do_* Reviewed-by: Brian Behlendorf Signed-off-by: luozhengzheng Closes #5056 --- cmd/zfs/zfs_main.c | 45 ++++++++++++++++++++++++++++++++---------- cmd/zpool/zpool_main.c | 28 +++++++++++++++++++++----- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 8a8f56af99..063ee7c54b 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -659,8 +659,10 @@ zfs_do_clone(int argc, char **argv) while ((c = getopt(argc, argv, "o:p")) != -1) { switch (c) { case 'o': - if (parseprop(props, optarg) != 0) + if (parseprop(props, optarg) != 0) { + nvlist_free(props); return (1); + } break; case 'p': parents = B_TRUE; @@ -692,8 +694,10 @@ zfs_do_clone(int argc, char **argv) } /* open the source dataset */ - if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL) + if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL) { + nvlist_free(props); return (1); + } if (parents && zfs_name_valid(argv[1], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) { @@ -703,10 +707,16 @@ zfs_do_clone(int argc, char **argv) * complain. */ if (zfs_dataset_exists(g_zfs, argv[1], ZFS_TYPE_FILESYSTEM | - ZFS_TYPE_VOLUME)) + ZFS_TYPE_VOLUME)) { + zfs_close(zhp); + nvlist_free(props); return (0); - if (zfs_create_ancestors(g_zfs, argv[1]) != 0) + } + if (zfs_create_ancestors(g_zfs, argv[1]) != 0) { + zfs_close(zhp); + nvlist_free(props); return (1); + } } /* pass to libzfs */ @@ -1280,8 +1290,10 @@ zfs_do_destroy(int argc, char **argv) *at = '\0'; zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); - if (zhp == NULL) + if (zhp == NULL) { + nvlist_free(cb.cb_nvl); return (1); + } cb.cb_snapspec = at + 1; if (gather_snapshots(zfs_handle_dup(zhp), &cb) != 0 || @@ -1370,7 +1382,7 @@ zfs_do_destroy(int argc, char **argv) "cannot destroy bookmark"); } - nvlist_free(cb.cb_nvl); + nvlist_free(nvl); return (err); } else { @@ -3645,8 +3657,11 @@ zfs_do_snapshot(int argc, char **argv) while ((c = getopt(argc, argv, "ro:")) != -1) { switch (c) { case 'o': - if (parseprop(props, optarg) != 0) + if (parseprop(props, optarg) != 0) { + nvlist_free(sd.sd_nvl); + nvlist_free(props); return (1); + } break; case 'r': sd.sd_recursive = B_TRUE; @@ -3937,8 +3952,10 @@ zfs_do_receive(int argc, char **argv) while ((c = getopt(argc, argv, ":o:denuvFsA")) != -1) { switch (c) { case 'o': - if (parseprop(props, optarg) != 0) + if (parseprop(props, optarg) != 0) { + nvlist_free(props); return (1); + } break; case 'd': flags.isprefix = B_TRUE; @@ -4012,9 +4029,12 @@ zfs_do_receive(int argc, char **argv) ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) { zfs_handle_t *zhp = zfs_open(g_zfs, namebuf, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); - if (zhp == NULL) + if (zhp == NULL) { + nvlist_free(props); return (1); + } err = zfs_destroy(zhp, B_FALSE); + zfs_close(zhp); } else { zfs_handle_t *zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); @@ -4027,11 +4047,14 @@ zfs_do_receive(int argc, char **argv) gettext("'%s' does not have any " "resumable receive state to abort\n"), argv[0]); + nvlist_free(props); + zfs_close(zhp); return (1); } err = zfs_destroy(zhp, B_FALSE); + zfs_close(zhp); } - + nvlist_free(props); return (err != 0); } @@ -4040,9 +4063,11 @@ zfs_do_receive(int argc, char **argv) gettext("Error: Backup stream can not be read " "from a terminal.\n" "You must redirect standard input.\n")); + nvlist_free(props); return (1); } err = zfs_receive(g_zfs, argv[0], props, &flags, STDIN_FILENO, NULL); + nvlist_free(props); return (err != 0); } diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index 09531b21df..e512688b77 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -1296,6 +1296,7 @@ zpool_do_destroy(int argc, char **argv) if (zpool_disable_datasets(zhp, force) != 0) { (void) fprintf(stderr, gettext("could not destroy '%s': " "could not unmount datasets\n"), zpool_get_name(zhp)); + zpool_close(zhp); return (1); } @@ -2343,6 +2344,7 @@ zpool_do_import(int argc, char **argv) if (searchdirs != NULL) free(searchdirs); + nvlist_free(props); nvlist_free(policy); return (1); } @@ -2449,6 +2451,8 @@ zpool_do_import(int argc, char **argv) if (envdup != NULL) free(envdup); nvlist_free(policy); + nvlist_free(pools); + nvlist_free(props); return (1); } @@ -4749,13 +4753,16 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing) usage(B_FALSE); } - if ((zhp = zpool_open(g_zfs, poolname)) == NULL) + if ((zhp = zpool_open(g_zfs, poolname)) == NULL) { + nvlist_free(props); return (1); + } if (zpool_get_config(zhp, NULL) == NULL) { (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"), poolname); zpool_close(zhp); + nvlist_free(props); return (1); } @@ -4763,11 +4770,13 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing) argc, argv); if (nvroot == NULL) { zpool_close(zhp); + nvlist_free(props); return (1); } ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); + nvlist_free(props); nvlist_free(nvroot); zpool_close(zhp); @@ -4973,8 +4982,10 @@ zpool_do_split(int argc, char **argv) argc -= 2; argv += 2; - if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) + if ((zhp = zpool_open(g_zfs, srcpool)) == NULL) { + nvlist_free(props); return (1); + } config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv); if (config == NULL) { @@ -4986,20 +4997,25 @@ zpool_do_split(int argc, char **argv) print_vdev_tree(NULL, newpool, config, 0, B_FALSE, flags.name_flags); } - nvlist_free(config); } zpool_close(zhp); - if (ret != 0 || flags.dryrun || !flags.import) + if (ret != 0 || flags.dryrun || !flags.import) { + nvlist_free(config); + nvlist_free(props); return (ret); + } /* * The split was successful. Now we need to open the new * pool and import it. */ - if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) + if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL) { + nvlist_free(config); + nvlist_free(props); return (1); + } if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && zpool_enable_datasets(zhp, mntopts, 0) != 0) { ret = 1; @@ -5009,6 +5025,8 @@ zpool_do_split(int argc, char **argv) "different altroot\n"), "zpool import"); } zpool_close(zhp); + nvlist_free(config); + nvlist_free(props); return (ret); }