aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/dmu_objset.c
diff options
context:
space:
mode:
authorloli10K <[email protected]>2019-02-09 00:44:15 +0100
committerMatthew Ahrens <[email protected]>2019-02-08 15:44:15 -0800
commitd8d418ff0cc90776182534bce10b01e9487b63e4 (patch)
treeb7db149cf6bfc701f7b3637359c192b2575c83c8 /module/zfs/dmu_objset.c
parent4417096956f7439322c65d9e70a4526df45ea8d0 (diff)
ZVOLs should not be allowed to have children
zfs create, receive and rename can bypass this hierarchy rule. Update both userland and kernel module to prevent this issue and use pyzfs unit tests to exercise the ioctls directly. Note: this commit slightly changes zfs_ioc_create() ABI. This allow to differentiate a generic error (EINVAL) from the specific case where we tried to create a dataset below a ZVOL (ZFS_ERR_WRONG_PARENT). Reviewed-by: Paul Dagnelie <[email protected]> Reviewed-by: Matt Ahrens <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Tom Caputi <[email protected]> Signed-off-by: loli10K <[email protected]>
Diffstat (limited to 'module/zfs/dmu_objset.c')
-rw-r--r--module/zfs/dmu_objset.c26
1 files changed, 26 insertions, 0 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);