diff options
Diffstat (limited to 'module')
-rw-r--r-- | module/zfs/dmu_objset.c | 26 | ||||
-rw-r--r-- | module/zfs/dmu_recv.c | 24 | ||||
-rw-r--r-- | module/zfs/dsl_dir.c | 26 | ||||
-rw-r--r-- | module/zfs/zfs_ioctl.c | 11 |
4 files changed, 80 insertions, 7 deletions
diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c index a8304c18d..fa80e3a61 100644 --- a/module/zfs/dmu_objset.c +++ b/module/zfs/dmu_objset.c @@ -29,6 +29,7 @@ * Copyright (c) 2016 Actifio, Inc. All rights reserved. * Copyright 2017 Nexenta Systems, Inc. * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. + * Copyright (c) 2018, loli10K <[email protected]>. All rights reserved. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -1118,6 +1119,8 @@ dmu_objset_create_check(void *arg, dmu_tx_t *tx) dmu_objset_create_arg_t *doca = arg; dsl_pool_t *dp = dmu_tx_pool(tx); dsl_dir_t *pdd; + dsl_dataset_t *parentds; + objset_t *parentos; const char *tail; int error; @@ -1146,7 +1149,30 @@ dmu_objset_create_check(void *arg, dmu_tx_t *tx) error = dsl_fs_ss_limit_check(pdd, 1, ZFS_PROP_FILESYSTEM_LIMIT, NULL, doca->doca_cred); + if (error != 0) { + dsl_dir_rele(pdd, FTAG); + return (error); + } + /* can't create below anything but filesystems (eg. no ZVOLs) */ + error = dsl_dataset_hold_obj(pdd->dd_pool, + dsl_dir_phys(pdd)->dd_head_dataset_obj, FTAG, &parentds); + if (error != 0) { + dsl_dir_rele(pdd, FTAG); + return (error); + } + error = dmu_objset_from_ds(parentds, &parentos); + if (error != 0) { + dsl_dataset_rele(parentds, FTAG); + dsl_dir_rele(pdd, FTAG); + return (error); + } + if (dmu_objset_type(parentos) != DMU_OST_ZFS) { + dsl_dataset_rele(parentds, FTAG); + dsl_dir_rele(pdd, FTAG); + return (SET_ERROR(ZFS_ERR_WRONG_PARENT)); + } + dsl_dataset_rele(parentds, FTAG); dsl_dir_rele(pdd, FTAG); return (error); diff --git a/module/zfs/dmu_recv.c b/module/zfs/dmu_recv.c index 4ac6f2f17..e05b5ad82 100644 --- a/module/zfs/dmu_recv.c +++ b/module/zfs/dmu_recv.c @@ -26,6 +26,7 @@ * Copyright 2014 HybridCluster. All rights reserved. * Copyright 2016 RackTop Systems. * Copyright (c) 2016 Actifio, Inc. All rights reserved. + * Copyright (c) 2018, loli10K <[email protected]>. All rights reserved. */ #include <sys/dmu.h> @@ -79,6 +80,7 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds, uint64_t fromguid, uint64_t featureflags) { uint64_t val; + uint64_t children; int error; dsl_pool_t *dp = ds->ds_dir->dd_pool; boolean_t encrypted = ds->ds_dir->dd_crypto_obj != 0; @@ -99,6 +101,15 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds, if (error != ENOENT) return (error == 0 ? EEXIST : error); + /* must not have children if receiving a ZVOL */ + error = zap_count(dp->dp_meta_objset, + dsl_dir_phys(ds->ds_dir)->dd_child_dir_zapobj, &children); + if (error != 0) + return (error); + if (drba->drba_cookie->drc_drrb->drr_type != DMU_OST_ZFS && + children > 0) + return (SET_ERROR(ZFS_ERR_WRONG_PARENT)); + /* * Check snapshot limit before receiving. We'll recheck again at the * end, but might as well abort before receiving if we're already over @@ -283,6 +294,7 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx) } else if (error == ENOENT) { /* target fs does not exist; must be a full backup or clone */ char buf[ZFS_MAX_DATASET_NAME_LEN]; + objset_t *os; /* * If it's a non-clone incremental, we are missing the @@ -352,6 +364,17 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx) return (error); } + /* can't recv below anything but filesystems (eg. no ZVOLs) */ + error = dmu_objset_from_ds(ds, &os); + if (error != 0) { + dsl_dataset_rele_flags(ds, dsflags, FTAG); + return (error); + } + if (dmu_objset_type(os) != DMU_OST_ZFS) { + dsl_dataset_rele_flags(ds, dsflags, FTAG); + return (SET_ERROR(ZFS_ERR_WRONG_PARENT)); + } + if (drba->drba_origin != NULL) { dsl_dataset_t *origin; @@ -381,6 +404,7 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx) dsl_dataset_rele_flags(origin, dsflags, FTAG); } + dsl_dataset_rele_flags(ds, dsflags, FTAG); error = 0; } diff --git a/module/zfs/dsl_dir.c b/module/zfs/dsl_dir.c index 5b6ce0420..b3b677fb8 100644 --- a/module/zfs/dsl_dir.c +++ b/module/zfs/dsl_dir.c @@ -25,6 +25,7 @@ * Copyright (c) 2014 Joyent, Inc. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. * Copyright (c) 2016 Actifio, Inc. All rights reserved. + * Copyright (c) 2018, loli10K <[email protected]>. All rights reserved. */ #include <sys/dmu.h> @@ -1888,6 +1889,8 @@ dsl_dir_rename_check(void *arg, dmu_tx_t *tx) dsl_pool_t *dp = dmu_tx_pool(tx); dsl_dir_t *dd, *newparent; dsl_valid_rename_arg_t dvra; + dsl_dataset_t *parentds; + objset_t *parentos; const char *mynewname; int error; @@ -1918,6 +1921,29 @@ dsl_dir_rename_check(void *arg, dmu_tx_t *tx) return (SET_ERROR(EEXIST)); } + /* can't rename below anything but filesystems (eg. no ZVOLs) */ + error = dsl_dataset_hold_obj(newparent->dd_pool, + dsl_dir_phys(newparent)->dd_head_dataset_obj, FTAG, &parentds); + if (error != 0) { + dsl_dir_rele(newparent, FTAG); + dsl_dir_rele(dd, FTAG); + return (error); + } + error = dmu_objset_from_ds(parentds, &parentos); + if (error != 0) { + dsl_dataset_rele(parentds, FTAG); + dsl_dir_rele(newparent, FTAG); + dsl_dir_rele(dd, FTAG); + return (error); + } + if (dmu_objset_type(parentos) != DMU_OST_ZFS) { + dsl_dataset_rele(parentds, FTAG); + dsl_dir_rele(newparent, FTAG); + dsl_dir_rele(dd, FTAG); + return (SET_ERROR(ZFS_ERR_WRONG_PARENT)); + } + dsl_dataset_rele(parentds, FTAG); + ASSERT3U(strnlen(ddra->ddra_newname, ZFS_MAX_DATASET_NAME_LEN), <, ZFS_MAX_DATASET_NAME_LEN); ASSERT3U(strnlen(ddra->ddra_oldname, ZFS_MAX_DATASET_NAME_LEN), diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index 0dfa01684..f4aea57d4 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -33,7 +33,7 @@ * Copyright (c) 2014 Integros [integros.com] * Copyright 2016 Toomas Soome <[email protected]> * Copyright (c) 2016 Actifio, Inc. All rights reserved. - * Copyright (c) 2017, loli10K <[email protected]>. All rights reserved. + * Copyright (c) 2018, loli10K <[email protected]>. All rights reserved. * Copyright (c) 2017 Datto Inc. All rights reserved. * Copyright 2017 RackTop Systems. * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. @@ -3082,8 +3082,9 @@ zfs_fill_zplprops_impl(objset_t *os, uint64_t zplver, ASSERT(zplprops != NULL); + /* parent dataset must be a filesystem */ if (os != NULL && os->os_phys->os_type != DMU_OST_ZFS) - return (SET_ERROR(EINVAL)); + return (SET_ERROR(ZFS_ERR_WRONG_PARENT)); /* * Pull out creator prop choices, if any. @@ -3162,15 +3163,11 @@ zfs_fill_zplprops(const char *dataset, nvlist_t *createprops, uint64_t zplver = ZPL_VERSION; objset_t *os = NULL; char parentname[ZFS_MAX_DATASET_NAME_LEN]; - char *cp; spa_t *spa; uint64_t spa_vers; int error; - (void) strlcpy(parentname, dataset, sizeof (parentname)); - cp = strrchr(parentname, '/'); - ASSERT(cp != NULL); - cp[0] = '\0'; + zfs_get_parent(dataset, parentname, sizeof (parentname)); if ((error = spa_open(dataset, &spa, FTAG)) != 0) return (error); |