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:
Tom Caputi
2019-02-04 14:24:55 -05:00
committed by Brian Behlendorf
parent 579ce7c5ae
commit f00ab3f22c
27 changed files with 607 additions and 53 deletions
+25
View File
@@ -3845,6 +3845,31 @@ parameters with the
.Fl o
options.
.Pp
The added security provided by raw sends adds some restrictions to the send
and receive process. ZFS will not allow a mix of raw receives and non-raw
receives. Specifically, any raw incremental receives that are attempted after
a non-raw receive will fail. Non-raw receives do not have this restriction and,
therefore, are always possible. Because of this, it is best practice to always
use either raw sends for their security benefits or non-raw sends for their
flexibility when working with encrypted datasets, but not a combination.
.Pp
The reason for this restriction stems from the inherent restrictions of the
AEAD ciphers that ZFS uses to encrypt data. When using ZFS native encryption,
each block of data is encrypted against a randomly generated number known as
the "initialization vector" (IV), which is stored in the filesystem metadata.
This number is required by the encryption algorithms whenever the data is to
be decrypted. Together, all of the IVs provided for all of the blocks in a
given snapshot are collectively called an "IV set". When ZFS performs a raw
send, the IV set is transferred from the source to the destination in the send
stream. When ZFS performs a non-raw send, the data is decrypted by the source
system and re-encrypted by the destination system, creating a snapshot with
effectively the same data, but a different IV set. In order for decryption to
work after a raw send, ZFS must ensure that the IV set used on both the source
and destination side match. When an incremental raw receive is performed on
top of an existing snapshot, ZFS will check to confirm that the "from"
snapshot on both the source and destination were using the same IV set,
ensuring the new IV set is consistent.
.Pp
The name of the snapshot
.Pq and file system, if a full stream is received
that this subcommand creates depends on the argument type and the use of the