Skip to content

Commit bb5884a

Browse files
committed
Fix raw sends on encrypted datasets when copying back snapshots
When sending raw encrypted datasets the user space accounting is present when it's not expected to be. This leads to the subsequent mount failure due a checksum error when verifying the local mac. Fix this by clearing the OBJSET_FLAG_USERACCOUNTING_COMPLETE and reset the local mac. This allows the user accounting to be correctly updated on first mount using the normal upgrade process. Closes #10523. Signed-off-by: George Amanakis <[email protected]>
1 parent 85703f6 commit bb5884a

File tree

3 files changed

+31
-27
lines changed

3 files changed

+31
-27
lines changed

module/os/freebsd/zfs/zio_crypt.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,19 @@ zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
10701070

10711071
bcopy(raw_portable_mac, portable_mac, ZIO_OBJSET_MAC_LEN);
10721072

1073+
/*
1074+
* Add in the non-portable os_flags. This is necessary here as we check
1075+
* whether OBJSET_FLAG_USERACCOUNTING_COMPLETE is set in order to
1076+
* decide if the local_mac should be zeroed out.
1077+
*/
1078+
intval = osp->os_flags;
1079+
if (should_bswap)
1080+
intval = BSWAP_64(intval);
1081+
intval &= ~OBJSET_CRYPT_PORTABLE_FLAGS_MASK;
1082+
/* CONSTCOND */
1083+
if (!ZFS_HOST_BYTEORDER)
1084+
intval = BSWAP_64(intval);
1085+
10731086
/*
10741087
* The local MAC protects the user, group and project accounting.
10751088
* If these objects are not present, the local MAC is zeroed out.
@@ -1081,23 +1094,15 @@ zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
10811094
(datalen >= OBJSET_PHYS_SIZE_V2 &&
10821095
osp->os_userused_dnode.dn_type == DMU_OT_NONE &&
10831096
osp->os_groupused_dnode.dn_type == DMU_OT_NONE) ||
1084-
(datalen <= OBJSET_PHYS_SIZE_V1)) {
1097+
(datalen <= OBJSET_PHYS_SIZE_V1) ||
1098+
(intval & OBJSET_FLAG_USERACCOUNTING_COMPLETE) == 0) {
10851099
bzero(local_mac, ZIO_OBJSET_MAC_LEN);
10861100
return (0);
10871101
}
10881102

10891103
/* calculate the local MAC from the userused and groupused dnodes */
10901104
crypto_mac_init(ctx, &key->zk_hmac_key);
10911105

1092-
/* add in the non-portable os_flags */
1093-
intval = osp->os_flags;
1094-
if (should_bswap)
1095-
intval = BSWAP_64(intval);
1096-
intval &= ~OBJSET_CRYPT_PORTABLE_FLAGS_MASK;
1097-
/* CONSTCOND */
1098-
if (!ZFS_HOST_BYTEORDER)
1099-
intval = BSWAP_64(intval);
1100-
11011106
crypto_mac_update(ctx, &intval, sizeof (uint64_t));
11021107

11031108
/* XXX check dnode type ... */

module/os/linux/zfs/zio_crypt.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,6 +1197,18 @@ zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
11971197

11981198
bcopy(raw_portable_mac, portable_mac, ZIO_OBJSET_MAC_LEN);
11991199

1200+
/*
1201+
* Add in the non-portable os_flags. This is necessary here as we check
1202+
* whether OBJSET_FLAG_USERACCOUNTING_COMPLETE is set in order to
1203+
* decide if the local_mac should be zeroed out.
1204+
*/
1205+
intval = osp->os_flags;
1206+
if (should_bswap)
1207+
intval = BSWAP_64(intval);
1208+
intval &= ~OBJSET_CRYPT_PORTABLE_FLAGS_MASK;
1209+
if (!ZFS_HOST_BYTEORDER)
1210+
intval = BSWAP_64(intval);
1211+
12001212
/*
12011213
* The local MAC protects the user, group and project accounting.
12021214
* If these objects are not present, the local MAC is zeroed out.
@@ -1208,7 +1220,8 @@ zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
12081220
(datalen >= OBJSET_PHYS_SIZE_V2 &&
12091221
osp->os_userused_dnode.dn_type == DMU_OT_NONE &&
12101222
osp->os_groupused_dnode.dn_type == DMU_OT_NONE) ||
1211-
(datalen <= OBJSET_PHYS_SIZE_V1)) {
1223+
(datalen <= OBJSET_PHYS_SIZE_V1) ||
1224+
(intval & OBJSET_FLAG_USERACCOUNTING_COMPLETE) == 0) {
12121225
bzero(local_mac, ZIO_OBJSET_MAC_LEN);
12131226
return (0);
12141227
}
@@ -1220,14 +1233,6 @@ zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
12201233
goto error;
12211234
}
12221235

1223-
/* add in the non-portable os_flags */
1224-
intval = osp->os_flags;
1225-
if (should_bswap)
1226-
intval = BSWAP_64(intval);
1227-
intval &= ~OBJSET_CRYPT_PORTABLE_FLAGS_MASK;
1228-
if (!ZFS_HOST_BYTEORDER)
1229-
intval = BSWAP_64(intval);
1230-
12311236
cd.cd_length = sizeof (uint64_t);
12321237
cd.cd_raw.iov_base = (char *)&intval;
12331238
cd.cd_raw.iov_len = cd.cd_length;

module/zfs/dsl_crypt.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,14 +2007,6 @@ dsl_crypto_recv_raw_objset_check(dsl_dataset_t *ds, dsl_dataset_t *fromds,
20072007
if (ret != 0)
20082008
return (ret);
20092009

2010-
/*
2011-
* Useraccounting is not portable and must be done with the keys loaded.
2012-
* Therefore, whenever we do any kind of receive the useraccounting
2013-
* must not be present.
2014-
*/
2015-
ASSERT0(os->os_flags & OBJSET_FLAG_USERACCOUNTING_COMPLETE);
2016-
ASSERT0(os->os_flags & OBJSET_FLAG_USEROBJACCOUNTING_COMPLETE);
2017-
20182010
mdn = DMU_META_DNODE(os);
20192011

20202012
/*
@@ -2105,6 +2097,8 @@ dsl_crypto_recv_raw_objset_sync(dsl_dataset_t *ds, dmu_objset_type_t ostype,
21052097
*/
21062098
arc_release(os->os_phys_buf, &os->os_phys_buf);
21072099
bcopy(portable_mac, os->os_phys->os_portable_mac, ZIO_OBJSET_MAC_LEN);
2100+
os->os_phys->os_flags &= ~OBJSET_FLAG_USERACCOUNTING_COMPLETE;
2101+
os->os_flags = os->os_phys->os_flags;
21082102
bzero(os->os_phys->os_local_mac, ZIO_OBJSET_MAC_LEN);
21092103
os->os_next_write_raw[tx->tx_txg & TXG_MASK] = B_TRUE;
21102104

0 commit comments

Comments
 (0)