From add927f8c8d101e16c23eb9cd270be4fd7edf7d5 Mon Sep 17 00:00:00 2001 From: loli10K Date: Wed, 3 Jan 2018 17:11:28 +0100 Subject: [PATCH] 8942 zfs promote .../%recv should be an error Reviewed by: Paul Dagnelie Reviewed by: Matthew Ahrens Approved by: Dan McDonald --- usr/src/lib/libzfs/common/libzfs_dataset.c | 7 +++++ usr/src/test/zfs-tests/include/libtest.shlib | 35 ++++++++++++++++++++++ .../cli_root/zfs_promote/zfs_promote_006_neg.ksh | 13 ++++++-- .../functional/cli_root/zfs_rename/zfs_rename.cfg | 1 + .../cli_root/zfs_rename/zfs_rename.kshlib | 5 ++++ .../cli_root/zfs_rename/zfs_rename_004_neg.ksh | 4 +-- usr/src/uts/common/fs/zfs/zfs_ioctl.c | 12 ++++++-- 7 files changed, 70 insertions(+), 7 deletions(-) diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c index 31c8b60f41..23e689cb9f 100644 --- a/usr/src/lib/libzfs/common/libzfs_dataset.c +++ b/usr/src/lib/libzfs/common/libzfs_dataset.c @@ -3737,6 +3737,9 @@ zfs_promote(zfs_handle_t *zhp) return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); } + if (!zfs_validate_name(hdl, zhp->zfs_name, zhp->zfs_type, B_TRUE)) + return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); + ret = lzc_promote(zhp->zfs_name, snapname, sizeof (snapname)); if (ret != 0) { @@ -4094,6 +4097,10 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive, (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, "cannot rename to '%s'"), target); + /* make sure source name is valid */ + if (!zfs_validate_name(hdl, zhp->zfs_name, zhp->zfs_type, B_TRUE)) + return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); + /* * Make sure the target name is valid */ diff --git a/usr/src/test/zfs-tests/include/libtest.shlib b/usr/src/test/zfs-tests/include/libtest.shlib index 60fba37146..d77b04baa0 100644 --- a/usr/src/test/zfs-tests/include/libtest.shlib +++ b/usr/src/test/zfs-tests/include/libtest.shlib @@ -264,6 +264,41 @@ function create_bookmark log_must zfs bookmark $fs_vol@$snap $fs_vol#$bkmark } +# +# Create a temporary clone result of an interrupted resumable 'zfs receive' +# $1 Destination filesystem name. Must not exist, will be created as the result +# of this function along with its %recv temporary clone +# $2 Source filesystem name. Must not exist, will be created and destroyed +# +function create_recv_clone +{ + typeset recvfs="$1" + typeset sendfs="${2:-$TESTPOOL/create_recv_clone}" + typeset snap="$sendfs@snap1" + typeset incr="$sendfs@snap2" + typeset mountpoint="$TESTDIR/create_recv_clone" + typeset sendfile="$TESTDIR/create_recv_clone.zsnap" + + [[ -z $recvfs ]] && log_fail "Recv filesystem's name is undefined." + + datasetexists $recvfs && log_fail "Recv filesystem must not exist." + datasetexists $sendfs && log_fail "Send filesystem must not exist." + + log_must zfs create -o mountpoint="$mountpoint" $sendfs + log_must zfs snapshot $snap + log_must eval "zfs send $snap | zfs recv -u $recvfs" + log_must mkfile 1m "$mountpoint/data" + log_must zfs snapshot $incr + log_must eval "zfs send -i $snap $incr | dd bs=10k count=1 > $sendfile" + log_mustnot eval "zfs recv -su $recvfs < $sendfile" + log_must zfs destroy -r $sendfs + log_must rm -f "$sendfile" + + if [[ $(get_prop 'inconsistent' "$recvfs/%recv") -ne 1 ]]; then + log_fail "Error creating temporary $recvfs/%recv clone" + fi +} + function default_mirror_setup { default_mirror_setup_noexit $1 $2 $3 diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh index cedfa676a1..af61f071cd 100644 --- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_promote/zfs_promote_006_neg.ksh @@ -40,6 +40,7 @@ # pool, fs, snapshot,volume # (4) too many arguments. # (5) invalid options +# (6) temporary %recv datasets # # STRATEGY: # 1. Create an array of invalid arguments @@ -50,11 +51,14 @@ verify_runnable "both" snap=$TESTPOOL/$TESTFS@$TESTSNAP +clone=$TESTPOOL/$TESTCLONE +recvfs=$TESTPOOL/recvfs set -A args "" \ "$TESTPOOL/blah" \ "$TESTPOOL" "$TESTPOOL/$TESTFS" "$snap" \ "$TESTPOOL/$TESTVOL" "$TESTPOOL $TESTPOOL/$TESTFS" \ - "$clone $TESTPOOL/$TESTFS" "- $clone" "-? $clone" + "$clone $TESTPOOL/$TESTFS" "- $clone" "-? $clone" \ + "$recvfs/%recv" function cleanup { @@ -62,6 +66,10 @@ function cleanup log_must zfs destroy $clone fi + if datasetexists $recvfs; then + log_must zfs destroy -r $recvfs + fi + if snapexists $snap; then destroy_snapshot $snap fi @@ -70,10 +78,9 @@ function cleanup log_assert "'zfs promote' will fail with invalid arguments. " log_onexit cleanup -snap=$TESTPOOL/$TESTFS@$TESTSNAP -clone=$TESTPOOL/$TESTCLONE log_must zfs snapshot $snap log_must zfs clone $snap $clone +create_recv_clone $recvfs typeset -i i=0 while (( i < ${#args[*]} )); do diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg index 26ff69b1bb..bf3a39363e 100644 --- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg @@ -36,3 +36,4 @@ export BS=512 export CNT=2048 export VOL_R_PATH=/dev/zvol/rdsk/$TESTPOOL/$TESTVOL export VOLDATA=$TESTDIR2/voldata.rename +export RECVFS=recvfs diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib index bb40bc1989..a60d7cf0f1 100644 --- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.kshlib @@ -63,6 +63,8 @@ function additional_setup log_must cp $DATA $(get_prop mountpoint $TESTPOOL/$TESTVOL)/$TESTFILE0 fi + # Create temporary %recv clone + create_recv_clone $TESTPOOL/$RECVFS } function rename_dataset # src dest @@ -109,6 +111,9 @@ function cleanup log_must zfs destroy -fR $TESTPOOL/$TESTFS@snapshot fi + if datasetexists $TESTPOOL/$RECVFS; then + log_must zfs destroy -r $TESTPOOL/$RECVFS + fi } function cmp_data #<$1 src data, $2 tgt data> diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh index cafa74366d..b1438e8663 100644 --- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename_004_neg.ksh @@ -77,8 +77,8 @@ set -A bad_dataset $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTCTR1 \ $TESTPOOL/$TESTFS1 $TESTPOOL/${TESTFS1}%x \ $TESTPOOL/$TESTFS1 $TESTPOOL/${TESTFS1}%p \ $TESTPOOL/$TESTFS1 $TESTPOOL/${TESTFS1}%s \ - $TESTPOOL/$TESTFS@snapshot \ - $TESTPOOL/$TESTFS@snapshot/fs + $TESTPOOL/$TESTFS@snapshot $TESTPOOL/$TESTFS@snapshot/fs \ + $TESTPOOL/$RECVFS/%recv $TESTPOOL/renamed.$$ # # cleanup defined in zfs_rename.kshlib diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c index ac344f78d7..4d9556ccaf 100644 --- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c +++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c @@ -3758,9 +3758,12 @@ zfs_ioc_rename(zfs_cmd_t *zc) boolean_t recursive = zc->zc_cookie & 1; char *at; + /* "zfs rename" from and to ...%recv datasets should both fail */ + zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; zc->zc_value[sizeof (zc->zc_value) - 1] = '\0'; - if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || - strchr(zc->zc_value, '%')) + if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 || + dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || + strchr(zc->zc_name, '%') || strchr(zc->zc_value, '%')) return (SET_ERROR(EINVAL)); at = strchr(zc->zc_name, '@'); @@ -4783,6 +4786,11 @@ zfs_ioc_promote(zfs_cmd_t *zc) char *cp; int error; + zc->zc_name[sizeof (zc->zc_name) - 1] = '\0'; + if (dataset_namecheck(zc->zc_name, NULL, NULL) != 0 || + strchr(zc->zc_name, '%')) + return (SET_ERROR(EINVAL)); + error = dsl_pool_hold(zc->zc_name, FTAG, &dp); if (error != 0) return (error); -- 2.11.4.GIT