From d21d5b8248cf38d1518c9beccc350bc9081ff6be Mon Sep 17 00:00:00 2001 From: Giuseppe Di Natale Date: Fri, 3 Feb 2017 13:24:44 -0800 Subject: [PATCH] OpenZFS 4521 - zfstest is trying to execute evil "zfs unmount -a" Authored by: Yuri Pankov Reviewed by: Andriy Gapon Reviewed by: Dan McDonald Reviewed by: Matthew Ahrens Reviewed by: John Kennedy Approved by: Robert Mustacchi Reviewed-by: Brian Behlendorf Reviewed-by: George Melikov Ported-by: Giuseppe Di Natale Porting Notes: - Correctly set __ZFS_POOL_RESTRICT in inherit_001_pos OpenZFS-issue: https://www.illumos.org/issues/4521 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/8808ac5 Closes #5674 --- cmd/zfs/zfs_main.c | 11 +++++- include/libzfs.h | 4 ++- lib/libzfs/libzfs_config.c | 35 +++++++++++++------ lib/libzfs/libzfs_dataset.c | 11 +++++- scripts/zfs-tests.sh | 3 ++ .../inheritance/inherit_001_pos.ksh | 2 +- 6 files changed, 52 insertions(+), 14 deletions(-) diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 952244b9f4..5074913a5e 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -25,8 +25,8 @@ * Copyright 2012 Milan Jurik. All rights reserved. * Copyright (c) 2012, Joyent, Inc. All rights reserved. * Copyright (c) 2013 Steven Hartland. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. * Copyright 2016 Igor Kozhukhov . + * Copyright 2016 Nexenta Systems, Inc. */ #include @@ -6563,6 +6563,15 @@ unshare_unmount(int op, int argc, char **argv) continue; } + /* + * Ignore datasets that are excluded/restricted by + * parent pool name. + */ + if (zpool_skip_pool(zfs_get_pool_name(zhp))) { + zfs_close(zhp); + continue; + } + switch (op) { case OP_SHARE: verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, diff --git a/include/libzfs.h b/include/libzfs.h index d74bf6b10f..0b5fe76dc5 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -24,8 +24,8 @@ * Copyright (c) 2011, 2015 by Delphix. All rights reserved. * Copyright (c) 2012, Joyent, Inc. All rights reserved. * Copyright (c) 2013 Steven Hartland. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2016, Intel Corporation. + * Copyright 2016 Nexenta Systems, Inc. */ #ifndef _LIBZFS_H @@ -237,6 +237,7 @@ extern void zpool_free_handles(libzfs_handle_t *); */ typedef int (*zpool_iter_f)(zpool_handle_t *, void *); extern int zpool_iter(libzfs_handle_t *, zpool_iter_f, void *); +extern boolean_t zpool_skip_pool(const char *); /* * Functions to create and destroy pools @@ -448,6 +449,7 @@ extern void zfs_close(zfs_handle_t *); extern zfs_type_t zfs_get_type(const zfs_handle_t *); extern const char *zfs_get_name(const zfs_handle_t *); extern zpool_handle_t *zfs_get_pool_handle(const zfs_handle_t *); +extern const char *zfs_get_pool_name(const zfs_handle_t *); /* * Property management functions. Some functions are shared with the kernel, diff --git a/lib/libzfs/libzfs_config.c b/lib/libzfs/libzfs_config.c index 4585a2b776..67379d0721 100644 --- a/lib/libzfs/libzfs_config.c +++ b/lib/libzfs/libzfs_config.c @@ -27,6 +27,7 @@ /* * Copyright (c) 2012 by Delphix. All rights reserved. * Copyright (c) 2015 by Syneto S.R.L. All rights reserved. + * Copyright 2016 Nexenta Systems, Inc. */ /* @@ -326,33 +327,47 @@ zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing) } /* - * If the __ZFS_POOL_RESTRICT environment variable is set we only iterate over - * pools it lists. + * The following environment variables are undocumented + * and should be used for testing purposes only: * - * This is an undocumented feature for use during testing only. + * __ZFS_POOL_EXCLUDE - don't iterate over the pools it lists + * __ZFS_POOL_RESTRICT - iterate only over the pools it lists * * This function returns B_TRUE if the pool should be skipped * during iteration. */ -static boolean_t -check_restricted(const char *poolname) +boolean_t +zpool_skip_pool(const char *poolname) { static boolean_t initialized = B_FALSE; - static char *restricted = NULL; + static const char *exclude = NULL; + static const char *restricted = NULL; const char *cur, *end; - int len, namelen; + int len; + int namelen = strlen(poolname); if (!initialized) { initialized = B_TRUE; + exclude = getenv("__ZFS_POOL_EXCLUDE"); restricted = getenv("__ZFS_POOL_RESTRICT"); } + if (exclude != NULL) { + cur = exclude; + do { + end = strchr(cur, ' '); + len = (NULL == end) ? strlen(cur) : (end - cur); + if (len == namelen && 0 == strncmp(cur, poolname, len)) + return (B_TRUE); + cur += (len + 1); + } while (NULL != end); + } + if (NULL == restricted) return (B_FALSE); cur = restricted; - namelen = strlen(poolname); do { end = strchr(cur, ' '); len = (NULL == end) ? strlen(cur) : (end - cur); @@ -390,7 +405,7 @@ zpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data) for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { - if (check_restricted(cn->cn_name)) + if (zpool_skip_pool(cn->cn_name)) continue; if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) { @@ -428,7 +443,7 @@ zfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data) for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL; cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) { - if (check_restricted(cn->cn_name)) + if (zpool_skip_pool(cn->cn_name)) continue; if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL) diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c index 7c3ef744d3..79c9dae6e4 100644 --- a/lib/libzfs/libzfs_dataset.c +++ b/lib/libzfs/libzfs_dataset.c @@ -27,7 +27,7 @@ * Copyright (c) 2012 Pawel Jakub Dawidek . * Copyright (c) 2013 Martin Matuska. All rights reserved. * Copyright (c) 2013 Steven Hartland. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2016 Nexenta Systems, Inc. */ #include @@ -3052,6 +3052,15 @@ zfs_get_name(const zfs_handle_t *zhp) return (zhp->zfs_name); } +/* + * Returns the name of the parent pool for the given zfs handle. + */ +const char * +zfs_get_pool_name(const zfs_handle_t *zhp) +{ + return (zhp->zpool_hdl->zpool_name); +} + /* * Returns the type of the given zfs handle. */ diff --git a/scripts/zfs-tests.sh b/scripts/zfs-tests.sh index 01fb2b2899..2e27c0a1c4 100755 --- a/scripts/zfs-tests.sh +++ b/scripts/zfs-tests.sh @@ -279,6 +279,8 @@ if [ -z "${KEEP}" ]; then fi fi +__ZFS_POOL_EXCLUDE="$(echo $KEEP | sed ':a;N;s/\n/ /g;ba')" + msg msg "--- Configuration ---" msg "Runfile: $RUNFILE" @@ -341,6 +343,7 @@ export STF_TOOLS export STF_SUITE export DISKS export KEEP +export __ZFS_POOL_EXCLUDE msg "${TEST_RUNNER} ${QUIET} -c ${RUNFILE} -i ${STF_SUITE}" ${TEST_RUNNER} ${QUIET} -c ${RUNFILE} -i ${STF_SUITE} diff --git a/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh b/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh index 0bbb77ce51..afcbfde027 100755 --- a/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh +++ b/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh @@ -331,7 +331,7 @@ function scan_state { #state-file if [[ $op == "-" ]]; then log_note "No operation specified" else - export __ZFS_POOL_RESTRICT="$TESTPOOL" + export __ZFS_POOL_RESTRICT="TESTPOOL" log_must $ZFS unmount -a unset __ZFS_POOL_RESTRICT