mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-24 03:08:51 +03:00
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 <pcd@delphix.com> Reviewed-by: Matt Ahrens <mahrens@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Tom Caputi <tcaputi@datto.com> Signed-off-by: loli10K <ezomori.nozomu@gmail.com>
This commit is contained in:
@@ -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 <ezomori.nozomu@gmail.com>. 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),
|
||||
|
||||
Reference in New Issue
Block a user