Allow unencrypted children of encrypted datasets

When encryption was first added to ZFS, we made a decision to
prevent users from creating unencrypted children of encrypted
datasets. The idea was to prevent users from inadvertently
leaving some of their data unencrypted. However, since the
release of 0.8.0, some legitimate reasons have been brought up
for this behavior to be allowed. This patch simply removes this
limitation from all code paths that had checks for it and updates
the tests accordingly.

Reviewed-by: Jason King <jason.king@joyent.com>
Reviewed-by: Sean Eric Fagan <sef@ixsystems.com>
Reviewed-by: Richard Laager <rlaager@wiktel.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tom Caputi <tcaputi@datto.com>
Closes #8737 
Closes #8870
This commit is contained in:
Tom Caputi
2019-06-20 15:29:51 -04:00
committed by Brian Behlendorf
parent 84b4201f32
commit da68988708
10 changed files with 63 additions and 163 deletions
-7
View File
@@ -1349,13 +1349,6 @@ dmu_objset_clone_check(void *arg, dmu_tx_t *tx)
return (SET_ERROR(EINVAL));
}
error = dmu_objset_clone_crypt_check(pdd, origin->ds_dir);
if (error != 0) {
dsl_dataset_rele(origin, FTAG);
dsl_dir_rele(pdd, FTAG);
return (error);
}
dsl_dataset_rele(origin, FTAG);
dsl_dir_rele(pdd, FTAG);
+12 -12
View File
@@ -624,7 +624,7 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
/* Open the parent of tofs */
ASSERT3U(strlen(tofs), <, sizeof (buf));
(void) strlcpy(buf, tofs, strrchr(tofs, '/') - tofs + 1);
error = dsl_dataset_hold_flags(dp, buf, dsflags, FTAG, &ds);
error = dsl_dataset_hold(dp, buf, FTAG, &ds);
if (error != 0)
return (error);
@@ -642,13 +642,13 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
error = dmu_objset_create_crypt_check(ds->ds_dir,
drba->drba_dcp, &will_encrypt);
if (error != 0) {
dsl_dataset_rele_flags(ds, dsflags, FTAG);
dsl_dataset_rele(ds, FTAG);
return (error);
}
if (will_encrypt &&
(featureflags & DMU_BACKUP_FEATURE_EMBED_DATA)) {
dsl_dataset_rele_flags(ds, dsflags, FTAG);
dsl_dataset_rele(ds, FTAG);
return (SET_ERROR(EINVAL));
}
}
@@ -661,25 +661,25 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
error = dsl_fs_ss_limit_check(ds->ds_dir, 1,
ZFS_PROP_FILESYSTEM_LIMIT, NULL, drba->drba_cred);
if (error != 0) {
dsl_dataset_rele_flags(ds, dsflags, FTAG);
dsl_dataset_rele(ds, FTAG);
return (error);
}
error = dsl_fs_ss_limit_check(ds->ds_dir, 1,
ZFS_PROP_SNAPSHOT_LIMIT, NULL, drba->drba_cred);
if (error != 0) {
dsl_dataset_rele_flags(ds, dsflags, FTAG);
dsl_dataset_rele(ds, FTAG);
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);
dsl_dataset_rele(ds, FTAG);
return (error);
}
if (dmu_objset_type(os) != DMU_OST_ZFS) {
dsl_dataset_rele_flags(ds, dsflags, FTAG);
dsl_dataset_rele(ds, FTAG);
return (SET_ERROR(ZFS_ERR_WRONG_PARENT));
}
@@ -688,25 +688,25 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx)
error = dsl_dataset_hold_flags(dp, drba->drba_origin,
dsflags, FTAG, &origin);
if (error != 0) {
dsl_dataset_rele_flags(ds, dsflags, FTAG);
dsl_dataset_rele(ds, FTAG);
return (error);
}
if (!origin->ds_is_snapshot) {
dsl_dataset_rele_flags(origin, dsflags, FTAG);
dsl_dataset_rele_flags(ds, dsflags, FTAG);
dsl_dataset_rele(ds, FTAG);
return (SET_ERROR(EINVAL));
}
if (dsl_dataset_phys(origin)->ds_guid != fromguid &&
fromguid != 0) {
dsl_dataset_rele_flags(origin, dsflags, FTAG);
dsl_dataset_rele_flags(ds, dsflags, FTAG);
dsl_dataset_rele(ds, FTAG);
return (SET_ERROR(ENODEV));
}
if (origin->ds_dir->dd_crypto_obj != 0 &&
(featureflags & DMU_BACKUP_FEATURE_EMBED_DATA)) {
dsl_dataset_rele_flags(origin, dsflags, FTAG);
dsl_dataset_rele_flags(ds, dsflags, FTAG);
dsl_dataset_rele(ds, FTAG);
return (SET_ERROR(EINVAL));
}
@@ -729,7 +729,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);
dsl_dataset_rele(ds, FTAG);
error = 0;
}
return (error);
+1 -43
View File
@@ -1610,15 +1610,8 @@ dsl_dir_rename_crypt_check(dsl_dir_t *dd, dsl_dir_t *newparent)
int ret;
uint64_t curr_rddobj, parent_rddobj;
if (dd->dd_crypto_obj == 0) {
/* children of encrypted parents must be encrypted */
if (newparent->dd_crypto_obj != 0) {
ret = SET_ERROR(EACCES);
goto error;
}
if (dd->dd_crypto_obj == 0)
return (0);
}
ret = dsl_dir_get_encryption_root_ddobj(dd, &curr_rddobj);
if (ret != 0)
@@ -1747,34 +1740,6 @@ dsl_dataset_promote_crypt_sync(dsl_dir_t *target, dsl_dir_t *origin,
kmem_free(keylocation, ZAP_MAXVALUELEN);
}
int
dmu_objset_clone_crypt_check(dsl_dir_t *parentdd, dsl_dir_t *origindd)
{
int ret;
uint64_t pcrypt, crypt;
/*
* Check that we are not making an unencrypted child of an
* encrypted parent.
*/
ret = dsl_dir_get_crypt(parentdd, &pcrypt);
if (ret != 0)
return (ret);
ret = dsl_dir_get_crypt(origindd, &crypt);
if (ret != 0)
return (ret);
ASSERT3U(pcrypt, !=, ZIO_CRYPT_INHERIT);
ASSERT3U(crypt, !=, ZIO_CRYPT_INHERIT);
if (crypt == ZIO_CRYPT_OFF && pcrypt != ZIO_CRYPT_OFF)
return (SET_ERROR(EINVAL));
return (0);
}
int
dmu_objset_create_crypt_check(dsl_dir_t *parentdd, dsl_crypto_params_t *dcp,
boolean_t *will_encrypt)
@@ -1805,13 +1770,6 @@ dmu_objset_create_crypt_check(dsl_dir_t *parentdd, dsl_crypto_params_t *dcp,
ASSERT3U(pcrypt, !=, ZIO_CRYPT_INHERIT);
ASSERT3U(crypt, !=, ZIO_CRYPT_INHERIT);
/*
* We can't create an unencrypted child of an encrypted parent
* under any circumstances.
*/
if (crypt == ZIO_CRYPT_OFF && pcrypt != ZIO_CRYPT_OFF)
return (SET_ERROR(EINVAL));
/* check for valid dcp with no encryption (inherited or local) */
if (crypt == ZIO_CRYPT_OFF) {
/* Must not specify encryption params */