mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 02:44:41 +03:00
Detect and prevent mixed raw and non-raw sends
Currently, there is an issue in the raw receive code where raw receives are allowed to happen on top of previously non-raw received datasets. This is a problem because the source-side dataset doesn't know about how the blocks on the destination were encrypted. As a result, any MAC in the objset's checksum-of-MACs tree that is a parent of both blocks encrypted on the source and blocks encrypted by the destination will be incorrect. This will result in authentication errors when we decrypt the dataset. This patch fixes this issue by adding a new check to the raw receive code. The code now maintains an "IVset guid", which acts as an identifier for the set of IVs used to encrypt a given snapshot. When a snapshot is raw received, the destination snapshot will take this value from the DRR_BEGIN payload. Non-raw receives and normal "zfs snap" operations will cause ZFS to generate a new IVset guid. When a raw incremental stream is received, ZFS will check that the "from" IVset guid in the stream matches that of the "from" destination snapshot. If they do not match, the code will error out the receive, preventing the problem. This patch requires an on-disk format change to add the IVset guids to snapshots and bookmarks. As a result, this patch has errata handling and a tunable to help affected users resolve the issue with as little interruption as possible. Reviewed-by: Paul Dagnelie <pcd@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Matt Ahrens <mahrens@delphix.com> Signed-off-by: Tom Caputi <tcaputi@datto.com> Closes #8308
This commit is contained in:
committed by
Brian Behlendorf
parent
579ce7c5ae
commit
f00ab3f22c
@@ -51,7 +51,9 @@ typedef struct dmu_recv_cookie {
|
||||
struct avl_tree *drc_guid_to_ds_map;
|
||||
nvlist_t *drc_keynvl;
|
||||
zio_cksum_t drc_cksum;
|
||||
uint64_t drc_fromsnapobj;
|
||||
uint64_t drc_newsnapobj;
|
||||
uint64_t drc_ivset_guid;
|
||||
void *drc_owner;
|
||||
cred_t *drc_cred;
|
||||
} dmu_recv_cookie_t;
|
||||
|
||||
@@ -189,12 +189,13 @@ void key_mapping_rele(spa_t *spa, dsl_key_mapping_t *km, void *tag);
|
||||
int spa_keystore_lookup_key(spa_t *spa, uint64_t dsobj, void *tag,
|
||||
dsl_crypto_key_t **dck_out);
|
||||
|
||||
int dsl_crypto_populate_key_nvlist(struct dsl_dataset *ds, nvlist_t **nvl_out);
|
||||
int dsl_crypto_populate_key_nvlist(struct dsl_dataset *ds,
|
||||
uint64_t from_ivset_guid, nvlist_t **nvl_out);
|
||||
int dsl_crypto_recv_raw_key_check(struct dsl_dataset *ds,
|
||||
nvlist_t *nvl, dmu_tx_t *tx);
|
||||
void dsl_crypto_recv_raw_key_sync(struct dsl_dataset *ds,
|
||||
nvlist_t *nvl, dmu_tx_t *tx);
|
||||
int dsl_crypto_recv_raw(const char *poolname, uint64_t dsobj,
|
||||
int dsl_crypto_recv_raw(const char *poolname, uint64_t dsobj, uint64_t fromobj,
|
||||
dmu_objset_type_t ostype, nvlist_t *nvl, boolean_t do_key);
|
||||
|
||||
int spa_keystore_change_key(const char *dsname, dsl_crypto_params_t *dcp);
|
||||
|
||||
@@ -114,6 +114,12 @@ struct dsl_key_mapping;
|
||||
*/
|
||||
#define DS_FIELD_REMAP_DEADLIST "com.delphix:remap_deadlist"
|
||||
|
||||
/*
|
||||
* This field is set to the ivset guid for encrypted snapshots. This is used
|
||||
* for validating raw receives.
|
||||
*/
|
||||
#define DS_FIELD_IVSET_GUID "com.datto:ivset_guid"
|
||||
|
||||
/*
|
||||
* DS_FLAG_CI_DATASET is set if the dataset contains a file system whose
|
||||
* name lookups should be performed case-insensitively.
|
||||
|
||||
@@ -183,6 +183,7 @@ typedef enum {
|
||||
ZFS_PROP_KEYSTATUS,
|
||||
ZFS_PROP_REMAPTXG, /* not exposed to the user */
|
||||
ZFS_PROP_SPECIAL_SMALL_BLOCKS,
|
||||
ZFS_PROP_IVSET_GUID, /* not exposed to the user */
|
||||
ZFS_NUM_PROPS
|
||||
} zfs_prop_t;
|
||||
|
||||
@@ -975,6 +976,7 @@ typedef enum zpool_errata {
|
||||
ZPOOL_ERRATA_ZOL_2094_SCRUB,
|
||||
ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY,
|
||||
ZPOOL_ERRATA_ZOL_6845_ENCRYPTION,
|
||||
ZPOOL_ERRATA_ZOL_8308_ENCRYPTION,
|
||||
} zpool_errata_t;
|
||||
|
||||
/*
|
||||
@@ -1264,6 +1266,8 @@ typedef enum {
|
||||
ZFS_ERR_IOC_ARG_REQUIRED,
|
||||
ZFS_ERR_IOC_ARG_BADTYPE,
|
||||
ZFS_ERR_WRONG_PARENT,
|
||||
ZFS_ERR_FROM_IVSET_GUID_MISSING,
|
||||
ZFS_ERR_FROM_IVSET_GUID_MISMATCH,
|
||||
} zfs_errno_t;
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user