Skip to content

Commit

Permalink
Upstream: Add crypto errata1 for projectquota-less datasets
Browse files Browse the repository at this point in the history
There was a short Windows of 2.0 releases before rc4 where a crypto
dataset would enable projectquota but fail to start it. Add
a work-around for that issue. It is expected this commit will
be remote in the near future.

datasets with crypto will generate the proper local_mac, and will not
be able to be imported with the broken 2.0 version.

Fixed dataset should work on other platforms again.

Signed-off-by: Jorgen Lundman <[email protected]>
  • Loading branch information
lundman committed Jun 22, 2021
1 parent 8cc02de commit 490ff77
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 9 deletions.
5 changes: 5 additions & 0 deletions include/sys/zio_crypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ int zio_crypt_do_hmac(zio_crypt_key_t *key, uint8_t *data, uint_t datalen,
uint8_t *digestbuf, uint_t digestlen);
int zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
boolean_t byteswap, uint8_t *portable_mac, uint8_t *local_mac);
#ifdef __APPLE__
int zio_crypt_do_objset_hmacs_errata1(zio_crypt_key_t *key, void *data,
uint_t datalen, boolean_t should_bswap, uint8_t *portable_mac,
uint8_t *local_mac);
#endif
int zio_do_crypt_data(boolean_t encrypt, zio_crypt_key_t *key,
dmu_object_type_t ot, boolean_t byteswap, uint8_t *salt, uint8_t *iv,
uint8_t *mac, uint_t datalen, uint8_t *plainbuf, uint8_t *cipherbuf,
Expand Down
45 changes: 36 additions & 9 deletions module/os/macos/zfs/zio_crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1119,9 +1119,10 @@ zio_crypt_do_dnode_hmac_updates(crypto_context_t ctx, uint64_t version,
* and le_bswap indicates whether a byteswap is needed to get this block
* into little endian format.
*/
int
zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
boolean_t should_bswap, uint8_t *portable_mac, uint8_t *local_mac)
static int
zio_crypt_do_objset_hmacs_impl(zio_crypt_key_t *key, void *data,
uint_t datalen, boolean_t should_bswap, uint8_t *portable_mac,
uint8_t *local_mac, boolean_t skip_projectquota)
{
int ret;
crypto_mechanism_t mech;
Expand Down Expand Up @@ -1266,12 +1267,20 @@ zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
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;
/*
* Unfortunate side-effect of macOS port getting crypto before
* projectquota. Luckily, if we just let it mount, by generating the
* old style local_mac, "generate" calls will upgrade to "proper".
*/
if (!skip_projectquota) {
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 */
Expand All @@ -1295,6 +1304,24 @@ zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
return (ret);
}

int
zio_crypt_do_objset_hmacs(zio_crypt_key_t *key, void *data, uint_t datalen,
boolean_t should_bswap, uint8_t *portable_mac, uint8_t *local_mac)
{
return (zio_crypt_do_objset_hmacs_impl(key, data, datalen, should_bswap,
portable_mac, local_mac, FALSE));
}

int
zio_crypt_do_objset_hmacs_errata1(zio_crypt_key_t *key, void *data,
uint_t datalen, boolean_t should_bswap, uint8_t *portable_mac,
uint8_t *local_mac)
{
dprintf("trying errata1 work-around\n");
return (zio_crypt_do_objset_hmacs_impl(key, data, datalen, should_bswap,
portable_mac, local_mac, TRUE));
}

static void
zio_crypt_destroy_uio(zfs_uio_t *uio)
{
Expand Down
12 changes: 12 additions & 0 deletions module/zfs/dsl_crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2701,6 +2701,18 @@ spa_do_crypt_objset_mac_abd(boolean_t generate, spa_t *spa, uint64_t dsobj,
return (0);
}

#ifdef __APPLE__
/*
* Unfortunate errata case, see module/os/macos/zfs/zio_crypt.c
* If portable is GOOD, but local_mac is BAD - recompute
*/
if (bcmp(portable_mac, osp->os_portable_mac, ZIO_OBJSET_MAC_LEN) == 0 &&
bcmp(local_mac, osp->os_local_mac, ZIO_OBJSET_MAC_LEN) != 0) {
ret = zio_crypt_do_objset_hmacs_errata1(&dck->dck_key, buf,
datalen, byteswap, portable_mac, local_mac);
}
#endif

if (bcmp(portable_mac, osp->os_portable_mac, ZIO_OBJSET_MAC_LEN) != 0 ||
bcmp(local_mac, osp->os_local_mac, ZIO_OBJSET_MAC_LEN) != 0) {
abd_return_buf(abd, buf, datalen);
Expand Down

0 comments on commit 490ff77

Please sign in to comment.