From 6368b4e47128986d8376c8a79a2b33bdb3dddb92 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Mon, 17 Sep 2018 16:16:57 +0000 Subject: [PATCH] Fix an nvpair leak in vdev_geom_read_config(). Also change the behaviour slightly: instead of freeing "config" if the last nvlist doesn't pass the tests, return the last config that did pass those tests. This matches the comment at the beginning of the function. PR: 230704 Diagnosed by: avg Reviewed by: asomers, avg Tested by: Mark Martinec Approved by: re (gjb) MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential revision: https://reviews.freebsd.org/D17202 --- .../opensolaris/uts/common/fs/zfs/vdev_geom.c | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c index aa8a400f2d7..7794bd50552 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c @@ -415,9 +415,10 @@ vdev_geom_io(struct g_consumer *cp, int *cmds, void **datas, off_t *offsets, * least one valid label was found. */ static int -vdev_geom_read_config(struct g_consumer *cp, nvlist_t **config) +vdev_geom_read_config(struct g_consumer *cp, nvlist_t **configp) { struct g_provider *pp; + nvlist_t *config; vdev_phys_t *vdev_lists[VDEV_LABELS]; char *buf; size_t buflen; @@ -442,7 +443,6 @@ vdev_geom_read_config(struct g_consumer *cp, nvlist_t **config) buflen = sizeof(vdev_lists[0]->vp_nvlist); - *config = NULL; /* Create all of the IO requests */ for (l = 0; l < VDEV_LABELS; l++) { cmds[l] = BIO_READ; @@ -458,6 +458,7 @@ vdev_geom_read_config(struct g_consumer *cp, nvlist_t **config) VDEV_LABELS); /* Parse the labels */ + config = *configp = NULL; nlabels = 0; for (l = 0; l < VDEV_LABELS; l++) { if (errors[l] != 0) @@ -465,25 +466,27 @@ vdev_geom_read_config(struct g_consumer *cp, nvlist_t **config) buf = vdev_lists[l]->vp_nvlist; - if (nvlist_unpack(buf, buflen, config, 0) != 0) + if (nvlist_unpack(buf, buflen, &config, 0) != 0) continue; - if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_STATE, + if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, &state) != 0 || state > POOL_STATE_L2CACHE) { - nvlist_free(*config); - *config = NULL; + nvlist_free(config); continue; } if (state != POOL_STATE_SPARE && state != POOL_STATE_L2CACHE && - (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_TXG, + (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_TXG, &txg) != 0 || txg == 0)) { - nvlist_free(*config); - *config = NULL; + nvlist_free(config); continue; } + if (*configp != NULL) + nvlist_free(*configp); + *configp = config; + nlabels++; }