From 322170ab72e48b661407bc3c8028db0ad05f7d1a Mon Sep 17 00:00:00 2001 From: Alex Wilson Date: Mon, 18 Mar 2019 21:45:34 +0000 Subject: Allow child datasets to be created w/o encryption --- usr/src/lib/libzfs/common/libzfs.h | 4 ++-- usr/src/lib/libzfs/common/libzfs_crypto.c | 8 +++++--- usr/src/lib/libzfs/common/libzfs_dataset.c | 2 +- usr/src/lib/libzfs/common/libzfs_pool.c | 4 ++-- usr/src/uts/common/fs/zfs/dmu_objset.c | 3 ++- usr/src/uts/common/fs/zfs/dmu_send.c | 4 +++- usr/src/uts/common/fs/zfs/dsl_crypt.c | 9 ++++++--- usr/src/uts/common/fs/zfs/spa.c | 2 +- usr/src/uts/common/fs/zfs/sys/dsl_crypt.h | 2 +- usr/src/uts/common/fs/zfs/zio_crypt.c | 4 ++++ 10 files changed, 27 insertions(+), 15 deletions(-) diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h index b72bc6029a..b44e876ac0 100644 --- a/usr/src/lib/libzfs/common/libzfs.h +++ b/usr/src/lib/libzfs/common/libzfs.h @@ -496,8 +496,8 @@ extern nvlist_t *zfs_get_clones_nvl(zfs_handle_t *); * zfs encryption management */ extern int zfs_crypto_get_encryption_root(zfs_handle_t *, boolean_t *, char *); -extern int zfs_crypto_create(libzfs_handle_t *, char *, nvlist_t *, nvlist_t *, - uint8_t **, uint_t *); +extern int zfs_crypto_create(libzfs_handle_t *, char *, zfs_type_t, nvlist_t *, + nvlist_t *, uint8_t **, uint_t *); extern int zfs_crypto_clone_check(libzfs_handle_t *, zfs_handle_t *, char *, nvlist_t *); extern int zfs_crypto_attempt_load_keys(libzfs_handle_t *, char *); diff --git a/usr/src/lib/libzfs/common/libzfs_crypto.c b/usr/src/lib/libzfs/common/libzfs_crypto.c index 0c87346b37..f2f9dba216 100644 --- a/usr/src/lib/libzfs/common/libzfs_crypto.c +++ b/usr/src/lib/libzfs/common/libzfs_crypto.c @@ -718,8 +718,9 @@ zfs_crypto_get_encryption_root(zfs_handle_t *zhp, boolean_t *is_encroot, } int -zfs_crypto_create(libzfs_handle_t *hdl, char *parent_name, nvlist_t *props, - nvlist_t *pool_props, uint8_t **wkeydata_out, uint_t *wkeylen_out) +zfs_crypto_create(libzfs_handle_t *hdl, char *parent_name, zfs_type_t type, + nvlist_t *props, nvlist_t *pool_props, uint8_t **wkeydata_out, + uint_t *wkeylen_out) { int ret; char errbuf[1024]; @@ -792,7 +793,8 @@ zfs_crypto_create(libzfs_handle_t *hdl, char *parent_name, nvlist_t *props, } /* Check for encryption being explicitly truned off */ - if (crypt == ZIO_CRYPT_OFF && pcrypt != ZIO_CRYPT_OFF) { + if (crypt == ZIO_CRYPT_OFF && pcrypt != ZIO_CRYPT_OFF && + type != ZFS_TYPE_VOLUME) { ret = EINVAL; zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "Invalid encryption value. Dataset must be encrypted.")); diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c index d7b5f5fe54..d1c19f748d 100644 --- a/usr/src/lib/libzfs/common/libzfs_dataset.c +++ b/usr/src/lib/libzfs/common/libzfs_dataset.c @@ -3664,7 +3664,7 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type, } (void) parent_name(path, parent, sizeof (parent)); - if (zfs_crypto_create(hdl, parent, props, NULL, &wkeydata, + if (zfs_crypto_create(hdl, parent, type, props, NULL, &wkeydata, &wkeylen) != 0) { nvlist_free(props); return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf)); diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c index 5dae959248..0bf7497c10 100644 --- a/usr/src/lib/libzfs/common/libzfs_pool.c +++ b/usr/src/lib/libzfs/common/libzfs_pool.c @@ -1169,8 +1169,8 @@ zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot, (nvlist_alloc(&zc_props, NV_UNIQUE_NAME, 0) != 0)) { goto create_failed; } - if (zfs_crypto_create(hdl, NULL, zc_fsprops, props, - &wkeydata, &wkeylen) != 0) { + if (zfs_crypto_create(hdl, NULL, ZFS_TYPE_FILESYSTEM, + zc_fsprops, props, &wkeydata, &wkeylen) != 0) { (void) zfs_error(hdl, EZFS_CRYPTOFAILED, msg); goto create_failed; } diff --git a/usr/src/uts/common/fs/zfs/dmu_objset.c b/usr/src/uts/common/fs/zfs/dmu_objset.c index ff1bc972a4..06641a3e5b 100644 --- a/usr/src/uts/common/fs/zfs/dmu_objset.c +++ b/usr/src/uts/common/fs/zfs/dmu_objset.c @@ -1056,7 +1056,8 @@ dmu_objset_create_check(void *arg, dmu_tx_t *tx) return (SET_ERROR(EEXIST)); } - error = dmu_objset_create_crypt_check(pdd, doca->doca_dcp, NULL); + error = dmu_objset_create_crypt_check(pdd, doca->doca_dcp, + doca->doca_type, NULL); if (error != 0) { dsl_dir_rele(pdd, FTAG); return (error); diff --git a/usr/src/uts/common/fs/zfs/dmu_send.c b/usr/src/uts/common/fs/zfs/dmu_send.c index b2ba3ac597..54e0526e5d 100644 --- a/usr/src/uts/common/fs/zfs/dmu_send.c +++ b/usr/src/uts/common/fs/zfs/dmu_send.c @@ -1612,6 +1612,7 @@ recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds, error = dmu_objset_create_crypt_check( ds->ds_dir->dd_parent, drba->drba_dcp, + ds->ds_objset->os_phys->os_type, &will_encrypt); if (error != 0) return (error); @@ -1750,7 +1751,8 @@ dmu_recv_begin_check(void *arg, dmu_tx_t *tx) * embedded data. */ error = dmu_objset_create_crypt_check(ds->ds_dir, - drba->drba_dcp, &will_encrypt); + drba->drba_dcp, ds->ds_objset->os_phys->os_type, + &will_encrypt); if (error != 0) { dsl_dataset_rele_flags(ds, dsflags, FTAG); return (error); diff --git a/usr/src/uts/common/fs/zfs/dsl_crypt.c b/usr/src/uts/common/fs/zfs/dsl_crypt.c index 5e0b09cc3b..d11e3ff741 100644 --- a/usr/src/uts/common/fs/zfs/dsl_crypt.c +++ b/usr/src/uts/common/fs/zfs/dsl_crypt.c @@ -1755,7 +1755,7 @@ dmu_objset_clone_crypt_check(dsl_dir_t *parentdd, dsl_dir_t *origindd) int dmu_objset_create_crypt_check(dsl_dir_t *parentdd, dsl_crypto_params_t *dcp, - boolean_t *will_encrypt) + dmu_objset_type_t type, boolean_t *will_encrypt) { int ret; uint64_t pcrypt, crypt; @@ -1785,9 +1785,12 @@ dmu_objset_create_crypt_check(dsl_dir_t *parentdd, dsl_crypto_params_t *dcp, /* * We can't create an unencrypted child of an encrypted parent - * under any circumstances. + * except when it's a zvol. We allow this to support dump zvols + * on pools with encryption set at the top, until there is proper + * support for encrypted dump zvols. */ - if (crypt == ZIO_CRYPT_OFF && pcrypt != ZIO_CRYPT_OFF) + if (crypt == ZIO_CRYPT_OFF && pcrypt != ZIO_CRYPT_OFF && + type != DMU_OST_ZVOL) return (SET_ERROR(EINVAL)); /* check for valid dcp with no encryption (inherited or local) */ diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c index 89afe2511d..5ad58ba294 100644 --- a/usr/src/uts/common/fs/zfs/spa.c +++ b/usr/src/uts/common/fs/zfs/spa.c @@ -4622,7 +4622,7 @@ spa_create_check_encryption_params(dsl_crypto_params_t *dcp, !has_encryption) return (SET_ERROR(ENOTSUP)); - return (dmu_objset_create_crypt_check(NULL, dcp, NULL)); + return (dmu_objset_create_crypt_check(NULL, dcp, DMU_OST_META, NULL)); } /* diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_crypt.h b/usr/src/uts/common/fs/zfs/sys/dsl_crypt.h index 360a69b329..7502b6ce66 100644 --- a/usr/src/uts/common/fs/zfs/sys/dsl_crypt.h +++ b/usr/src/uts/common/fs/zfs/sys/dsl_crypt.h @@ -204,7 +204,7 @@ int dsl_dataset_promote_crypt_check(dsl_dir_t *target, dsl_dir_t *origin); void dsl_dataset_promote_crypt_sync(dsl_dir_t *target, dsl_dir_t *origin, dmu_tx_t *tx); int dmu_objset_create_crypt_check(dsl_dir_t *parentdd, - dsl_crypto_params_t *dcp, boolean_t *will_encrypt); + dsl_crypto_params_t *dcp, dmu_objset_type_t type, boolean_t *will_encrypt); void dsl_dataset_create_crypt_sync(uint64_t dsobj, dsl_dir_t *dd, struct dsl_dataset *origin, dsl_crypto_params_t *dcp, dmu_tx_t *tx); uint64_t dsl_crypto_key_create_sync(uint64_t crypt, dsl_wrapping_key_t *wkey, diff --git a/usr/src/uts/common/fs/zfs/zio_crypt.c b/usr/src/uts/common/fs/zfs/zio_crypt.c index 55d2f682cc..be718d4ae0 100644 --- a/usr/src/uts/common/fs/zfs/zio_crypt.c +++ b/usr/src/uts/common/fs/zfs/zio_crypt.c @@ -1531,6 +1531,7 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf, } *no_crypt = (nr_iovecs == 0); + VERIFY(*no_crypt || total_len > 0); *enc_len = total_len; *authbuf = aadbuf; *auth_len = aad_len; @@ -1564,6 +1565,7 @@ error: puio->uio_iovcnt = 0; cuio->uio_iov = NULL; cuio->uio_iovcnt = 0; + VERIFY3S(ret, !=, 0); return (ret); } @@ -1924,6 +1926,8 @@ zio_do_crypt_data(boolean_t encrypt, zio_crypt_key_t *key, /* perform the encryption / decryption */ ret = zio_do_crypt_uio(encrypt, key->zk_crypt, ckey, tmpl, iv, enc_len, &puio, &cuio, authbuf, auth_len); + if (ret != 0 && no_crypt) + ret = 0; if (ret != 0) goto error; -- cgit v1.2.3