summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/zfs
diff options
context:
space:
mode:
authorTom Caputi <tcaputi@datto.com>2019-06-28 13:00:25 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2019-06-28 15:39:40 +0000
commita60ca23dc52059ace3f92bb9a63e723ac49e649b (patch)
tree3aafd723790eec7fb8371024a7e99e6a6e1b5474 /usr/src/uts/common/fs/zfs
parentb70e94852cee03960a3aed9ab79cbd643b648628 (diff)
downloadillumos-gate-a60ca23dc52059ace3f92bb9a63e723ac49e649b.tar.gz
11276 Allow unencrypted children of encrypted datasets
Portions contributed by: Jerry Jelinek <jerry.jelinek@joyent.com> 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: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed by: Kody Kantor <kody.kantor@joyent.com> Reviewed by: C Fraire <cfraire@me.com> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/uts/common/fs/zfs')
-rw-r--r--usr/src/uts/common/fs/zfs/arc.c45
-rw-r--r--usr/src/uts/common/fs/zfs/dbuf.c1
-rw-r--r--usr/src/uts/common/fs/zfs/dmu.c9
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_objset.c7
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_recv.c32
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_crypt.c44
-rw-r--r--usr/src/uts/common/fs/zfs/sys/dsl_crypt.h1
7 files changed, 37 insertions, 102 deletions
diff --git a/usr/src/uts/common/fs/zfs/arc.c b/usr/src/uts/common/fs/zfs/arc.c
index 90f5314d81..1cdd882872 100644
--- a/usr/src/uts/common/fs/zfs/arc.c
+++ b/usr/src/uts/common/fs/zfs/arc.c
@@ -1710,6 +1710,9 @@ arc_cksum_free(arc_buf_hdr_t *hdr)
static boolean_t
arc_hdr_has_uncompressed_buf(arc_buf_hdr_t *hdr)
{
+ ASSERT(hdr->b_l1hdr.b_state == arc_anon ||
+ MUTEX_HELD(HDR_LOCK(hdr)) || HDR_EMPTY(hdr));
+
for (arc_buf_t *b = hdr->b_l1hdr.b_buf; b != NULL; b = b->b_next) {
if (!ARC_BUF_COMPRESSED(b)) {
return (B_TRUE);
@@ -1732,15 +1735,13 @@ arc_cksum_verify(arc_buf_t *buf)
if (!(zfs_flags & ZFS_DEBUG_MODIFY))
return;
- if (ARC_BUF_COMPRESSED(buf)) {
- ASSERT(hdr->b_l1hdr.b_freeze_cksum == NULL ||
- arc_hdr_has_uncompressed_buf(hdr));
+ if (ARC_BUF_COMPRESSED(buf))
return;
- }
ASSERT(HDR_HAS_L1HDR(hdr));
mutex_enter(&hdr->b_l1hdr.b_freeze_lock);
+
if (hdr->b_l1hdr.b_freeze_cksum == NULL || HDR_IO_ERROR(hdr)) {
mutex_exit(&hdr->b_l1hdr.b_freeze_lock);
return;
@@ -1844,11 +1845,7 @@ arc_cksum_compute(arc_buf_t *buf)
ASSERT(HDR_HAS_L1HDR(hdr));
mutex_enter(&buf->b_hdr->b_l1hdr.b_freeze_lock);
- if (hdr->b_l1hdr.b_freeze_cksum != NULL) {
- ASSERT(arc_hdr_has_uncompressed_buf(hdr));
- mutex_exit(&hdr->b_l1hdr.b_freeze_lock);
- return;
- } else if (ARC_BUF_COMPRESSED(buf)) {
+ if (hdr->b_l1hdr.b_freeze_cksum != NULL || ARC_BUF_COMPRESSED(buf)) {
mutex_exit(&hdr->b_l1hdr.b_freeze_lock);
return;
}
@@ -1952,14 +1949,10 @@ arc_buf_thaw(arc_buf_t *buf)
arc_cksum_verify(buf);
/*
- * Compressed buffers do not manipulate the b_freeze_cksum or
- * allocate b_thawed.
+ * Compressed buffers do not manipulate the b_freeze_cksum.
*/
- if (ARC_BUF_COMPRESSED(buf)) {
- ASSERT(hdr->b_l1hdr.b_freeze_cksum == NULL ||
- arc_hdr_has_uncompressed_buf(hdr));
+ if (ARC_BUF_COMPRESSED(buf))
return;
- }
ASSERT(HDR_HAS_L1HDR(hdr));
arc_cksum_free(hdr);
@@ -1981,26 +1974,14 @@ arc_buf_thaw(arc_buf_t *buf)
void
arc_buf_freeze(arc_buf_t *buf)
{
- arc_buf_hdr_t *hdr = buf->b_hdr;
- kmutex_t *hash_lock;
-
if (!(zfs_flags & ZFS_DEBUG_MODIFY))
return;
- if (ARC_BUF_COMPRESSED(buf)) {
- ASSERT(hdr->b_l1hdr.b_freeze_cksum == NULL ||
- arc_hdr_has_uncompressed_buf(hdr));
+ if (ARC_BUF_COMPRESSED(buf))
return;
- }
-
- hash_lock = HDR_LOCK(hdr);
- mutex_enter(hash_lock);
- ASSERT(HDR_HAS_L1HDR(hdr));
- ASSERT(hdr->b_l1hdr.b_freeze_cksum != NULL ||
- hdr->b_l1hdr.b_state == arc_anon);
+ ASSERT(HDR_HAS_L1HDR(buf->b_hdr));
arc_cksum_compute(buf);
- mutex_exit(hash_lock);
}
/*
@@ -2128,7 +2109,7 @@ arc_hdr_authenticate(arc_buf_hdr_t *hdr, spa_t *spa, uint64_t dsobj)
void *tmpbuf = NULL;
abd_t *abd = hdr->b_l1hdr.b_pabd;
- ASSERT(HDR_LOCK(hdr) == NULL || MUTEX_HELD(HDR_LOCK(hdr)));
+ ASSERT(MUTEX_HELD(HDR_LOCK(hdr)) || HDR_EMPTY(hdr));
ASSERT(HDR_AUTHENTICATED(hdr));
ASSERT3P(hdr->b_l1hdr.b_pabd, !=, NULL);
@@ -2198,7 +2179,7 @@ arc_hdr_decrypt(arc_buf_hdr_t *hdr, spa_t *spa, const zbookmark_phys_t *zb)
boolean_t no_crypt = B_FALSE;
boolean_t bswap = (hdr->b_l1hdr.b_byteswap != DMU_BSWAP_NUMFUNCS);
- ASSERT(HDR_LOCK(hdr) == NULL || MUTEX_HELD(HDR_LOCK(hdr)));
+ ASSERT(MUTEX_HELD(HDR_LOCK(hdr)) || HDR_EMPTY(hdr));
ASSERT(HDR_ENCRYPTED(hdr));
arc_hdr_alloc_pabd(hdr, B_FALSE);
@@ -2318,7 +2299,7 @@ arc_buf_untransform_in_place(arc_buf_t *buf, kmutex_t *hash_lock)
ASSERT(HDR_ENCRYPTED(hdr));
ASSERT3U(hdr->b_crypt_hdr.b_ot, ==, DMU_OT_DNODE);
- ASSERT(HDR_LOCK(hdr) == NULL || MUTEX_HELD(HDR_LOCK(hdr)));
+ ASSERT(MUTEX_HELD(HDR_LOCK(hdr)) || HDR_EMPTY(hdr));
ASSERT3P(hdr->b_l1hdr.b_pabd, !=, NULL);
zio_crypt_copy_dnode_bonus(hdr->b_l1hdr.b_pabd, buf->b_data,
diff --git a/usr/src/uts/common/fs/zfs/dbuf.c b/usr/src/uts/common/fs/zfs/dbuf.c
index 9c7205bd0d..6a60ac7fdf 100644
--- a/usr/src/uts/common/fs/zfs/dbuf.c
+++ b/usr/src/uts/common/fs/zfs/dbuf.c
@@ -1037,7 +1037,6 @@ dbuf_read_verify_dnode_crypt(dmu_buf_impl_t *db, uint32_t flags)
!DMU_OT_IS_ENCRYPTED(dn->dn_bonustype))))
err = 0;
-
DB_DNODE_EXIT(db);
return (err);
diff --git a/usr/src/uts/common/fs/zfs/dmu.c b/usr/src/uts/common/fs/zfs/dmu.c
index 02bdfdfa12..d19c801c61 100644
--- a/usr/src/uts/common/fs/zfs/dmu.c
+++ b/usr/src/uts/common/fs/zfs/dmu.c
@@ -1711,6 +1711,7 @@ dmu_copy_from_buf(objset_t *os, uint64_t object, uint64_t offset,
dmu_buf_t *dst_handle;
dmu_buf_impl_t *dstdb;
dmu_buf_impl_t *srcdb = (dmu_buf_impl_t *)handle;
+ dmu_object_type_t type;
arc_buf_t *abuf;
uint64_t datalen;
boolean_t byteorder;
@@ -1726,11 +1727,15 @@ dmu_copy_from_buf(objset_t *os, uint64_t object, uint64_t offset,
dstdb = (dmu_buf_impl_t *)dst_handle;
datalen = arc_buf_size(srcdb->db_buf);
+ DB_DNODE_ENTER(dstdb);
+ type = DB_DNODE(dstdb)->dn_type;
+ DB_DNODE_EXIT(dstdb);
+
/* allocated an arc buffer that matches the type of srcdb->db_buf */
if (arc_is_encrypted(srcdb->db_buf)) {
arc_get_raw_params(srcdb->db_buf, &byteorder, salt, iv, mac);
abuf = arc_loan_raw_buf(os->os_spa, dmu_objset_id(os),
- byteorder, salt, iv, mac, DB_DNODE(dstdb)->dn_type,
+ byteorder, salt, iv, mac, type,
datalen, arc_buf_lsize(srcdb->db_buf),
arc_get_compression(srcdb->db_buf));
} else {
@@ -1738,7 +1743,7 @@ dmu_copy_from_buf(objset_t *os, uint64_t object, uint64_t offset,
ASSERT3U(arc_get_compression(srcdb->db_buf),
==, ZIO_COMPRESS_OFF);
abuf = arc_loan_buf(os->os_spa,
- DMU_OT_IS_METADATA(DB_DNODE(dstdb)->dn_type), datalen);
+ DMU_OT_IS_METADATA(type), datalen);
}
ASSERT3U(datalen, ==, arc_buf_size(abuf));
diff --git a/usr/src/uts/common/fs/zfs/dmu_objset.c b/usr/src/uts/common/fs/zfs/dmu_objset.c
index 4d0a5d2fd5..8174222826 100644
--- a/usr/src/uts/common/fs/zfs/dmu_objset.c
+++ b/usr/src/uts/common/fs/zfs/dmu_objset.c
@@ -1259,13 +1259,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);
diff --git a/usr/src/uts/common/fs/zfs/dmu_recv.c b/usr/src/uts/common/fs/zfs/dmu_recv.c
index b6f63e7e22..b72aa21922 100644
--- a/usr/src/uts/common/fs/zfs/dmu_recv.c
+++ b/usr/src/uts/common/fs/zfs/dmu_recv.c
@@ -306,7 +306,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);
@@ -324,13 +324,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));
}
}
@@ -343,46 +343,46 @@ 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);
}
if (drba->drba_origin != NULL) {
dsl_dataset_t *origin;
- error = dsl_dataset_hold_flags(dp, drba->drba_origin,
- dsflags, FTAG, &origin);
+ error = dsl_dataset_hold(dp, drba->drba_origin,
+ 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(origin, 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(origin, 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(origin, FTAG);
+ dsl_dataset_rele(ds, FTAG);
return (SET_ERROR(EINVAL));
}
- dsl_dataset_rele_flags(origin, dsflags, FTAG);
+ dsl_dataset_rele(origin, FTAG);
}
- dsl_dataset_rele_flags(ds, dsflags, FTAG);
+ dsl_dataset_rele(ds, FTAG);
error = 0;
}
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 3937d3cb51..3896efbc76 100644
--- a/usr/src/uts/common/fs/zfs/dsl_crypt.c
+++ b/usr/src/uts/common/fs/zfs/dsl_crypt.c
@@ -1588,15 +1588,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)
@@ -1726,34 +1719,6 @@ dsl_dataset_promote_crypt_sync(dsl_dir_t *target, dsl_dir_t *origin,
}
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)
{
@@ -1783,13 +1748,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 */
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..cf19665aae 100644
--- a/usr/src/uts/common/fs/zfs/sys/dsl_crypt.h
+++ b/usr/src/uts/common/fs/zfs/sys/dsl_crypt.h
@@ -209,7 +209,6 @@ 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,
dmu_tx_t *tx);
-int dmu_objset_clone_crypt_check(dsl_dir_t *parentdd, dsl_dir_t *origindd);
uint64_t dsl_crypto_key_clone_sync(dsl_dir_t *origindd, dmu_tx_t *tx);
void dsl_crypto_key_destroy_sync(uint64_t dckobj, dmu_tx_t *tx);