aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/zio_crypt.c
diff options
context:
space:
mode:
authorTom Caputi <[email protected]>2018-02-20 12:41:07 -0500
committerBrian Behlendorf <[email protected]>2018-02-20 09:41:07 -0800
commit7b30ee6bafe91ebd3b34433ef3b943fd07a98cea (patch)
treedf1e0d46ed28d62cfb7efef1c38ce104228d30b3 /module/zfs/zio_crypt.c
parente921f6508b212c61fcedd0eeb2f9cf9da1abc4d1 (diff)
Project dnode should be protected by local MAC
This patch corrects a small security issue with 9c5167d1. When the project dnode was added to the objset_phys_t, it was not included in the local MAC for cryptographic protection, allowing an attacker to modify this data without the consent of the key holder. This patch does represent an on-disk format change for anyone using project dnodes on an encrypted dataset. Signed-off-by: Tom Caputi <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #7177
Diffstat (limited to 'module/zfs/zio_crypt.c')
-rw-r--r--module/zfs/zio_crypt.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/module/zfs/zio_crypt.c b/module/zfs/zio_crypt.c
index 823e6b8d6..155bce9fb 100644
--- a/module/zfs/zio_crypt.c
+++ b/module/zfs/zio_crypt.c
@@ -1095,9 +1095,9 @@ error:
/*
* objset_phys_t blocks introduce a number of exceptions to the normal
- * authentication process. objset_phys_t's contain 2 seperate HMACS for
+ * authentication process. objset_phys_t's contain 2 separate HMACS for
* protecting the integrity of their data. The portable_mac protects the
- * the metadnode. This MAC can be sent with a raw send and protects against
+ * metadnode. This MAC can be sent with a raw send and protects against
* reordering of data within the metadnode. The local_mac protects the user
* accounting objects which are not sent from one system to another.
*
@@ -1199,8 +1199,10 @@ zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
* The local MAC protects the user and group accounting. If these
* objects are not present, the local MAC is zeroed out.
*/
- if (osp->os_userused_dnode.dn_type == DMU_OT_NONE &&
- osp->os_groupused_dnode.dn_type == DMU_OT_NONE) {
+ if (datalen >= OBJSET_PHYS_SIZE_V2 &&
+ osp->os_userused_dnode.dn_type == DMU_OT_NONE &&
+ osp->os_groupused_dnode.dn_type == DMU_OT_NONE &&
+ osp->os_projectused_dnode.dn_type == DMU_OT_NONE) {
bzero(local_mac, ZIO_OBJSET_MAC_LEN);
return (0);
}
@@ -1231,15 +1233,27 @@ zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
}
/* add in fields from the user accounting dnodes */
- ret = zio_crypt_do_dnode_hmac_updates(ctx, key->zk_version,
- should_bswap, &osp->os_userused_dnode);
- if (ret)
- goto error;
+ if (osp->os_userused_dnode.dn_type != DMU_OT_NONE) {
+ ret = zio_crypt_do_dnode_hmac_updates(ctx, key->zk_version,
+ should_bswap, &osp->os_userused_dnode);
+ if (ret)
+ goto error;
+ }
- ret = zio_crypt_do_dnode_hmac_updates(ctx, key->zk_version,
- should_bswap, &osp->os_groupused_dnode);
- if (ret)
- goto error;
+ if (osp->os_groupused_dnode.dn_type != DMU_OT_NONE) {
+ ret = zio_crypt_do_dnode_hmac_updates(ctx, key->zk_version,
+ should_bswap, &osp->os_groupused_dnode);
+ if (ret)
+ goto error;
+ }
+
+ if (osp->os_projectused_dnode.dn_type != DMU_OT_NONE &&
+ datalen >= OBJSET_PHYS_SIZE_V3) {
+ ret = zio_crypt_do_dnode_hmac_updates(ctx, key->zk_version,
+ should_bswap, &osp->os_projectused_dnode);
+ if (ret)
+ goto error;
+ }
/* store the final digest in a temporary buffer and copy what we need */
cd.cd_length = SHA512_DIGEST_LENGTH;