summaryrefslogtreecommitdiffstats
path: root/module/zfs/arc.c
diff options
context:
space:
mode:
authorTom Caputi <[email protected]>2018-03-31 14:12:51 -0400
committerBrian Behlendorf <[email protected]>2018-03-31 11:12:51 -0700
commita2c2ed1bd4c3dc6d52b6058b9c74245cad2ae331 (patch)
treede5ad1fd1bc04f0ee496316305871d0b0e26d74e /module/zfs/arc.c
parent4515b1d01c936b8cf156e20ba42cdb8916bca80b (diff)
Decryption error handling improvements
Currently, the decryption and block authentication code in the ZIO / ARC layers is a bit inconsistent with regards to the ereports that are produces and the error codes that are passed to calling functions. This patch ensures that all of these errors (which begin as ECKSUM) are converted to EIO before they leave the ZIO or ARC layer and that ereports are correctly generated on each decryption / authentication failure. In addition, this patch fixes a bug in zio_decrypt() where ECKSUM never gets written to zio->io_error. Reviewed by: Matt Ahrens <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Tom Caputi <[email protected]> Closes #7372
Diffstat (limited to 'module/zfs/arc.c')
-rw-r--r--module/zfs/arc.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/module/zfs/arc.c b/module/zfs/arc.c
index 81da36a42..893e42d31 100644
--- a/module/zfs/arc.c
+++ b/module/zfs/arc.c
@@ -2260,14 +2260,27 @@ byteswap:
* callers.
*/
int
-arc_untransform(arc_buf_t *buf, spa_t *spa, uint64_t dsobj, boolean_t in_place)
+arc_untransform(arc_buf_t *buf, spa_t *spa, const zbookmark_phys_t *zb,
+ boolean_t in_place)
{
+ int ret;
arc_fill_flags_t flags = 0;
if (in_place)
flags |= ARC_FILL_IN_PLACE;
- return (arc_buf_fill(buf, spa, dsobj, flags));
+ ret = arc_buf_fill(buf, spa, zb->zb_objset, flags);
+ if (ret == ECKSUM) {
+ /*
+ * Convert authentication and decryption errors to EIO
+ * (and generate an ereport) before leaving the ARC.
+ */
+ ret = SET_ERROR(EIO);
+ zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION,
+ spa, NULL, zb, NULL, 0, 0);
+ }
+
+ return (ret);
}
/*
@@ -5810,7 +5823,8 @@ arc_read_done(zio_t *zio)
* Assert non-speculative zios didn't fail because an
* encryption key wasn't loaded
*/
- ASSERT((zio->io_flags & ZIO_FLAG_SPECULATIVE) || error == 0);
+ ASSERT((zio->io_flags & ZIO_FLAG_SPECULATIVE) ||
+ error != ENOENT);
/*
* If we failed to decrypt, report an error now (as the zio
@@ -6033,12 +6047,24 @@ top:
rc = arc_buf_alloc_impl(hdr, spa, zb->zb_objset,
private, encrypted_read, compressed_read,
noauth_read, B_TRUE, &buf);
+ if (rc == ECKSUM) {
+ /*
+ * Convert authentication and decryption errors
+ * to EIO (and generate an ereport) before
+ * leaving the ARC.
+ */
+ rc = SET_ERROR(EIO);
+ zfs_ereport_post(FM_EREPORT_ZFS_AUTHENTICATION,
+ spa, NULL, zb, NULL, 0, 0);
+ }
if (rc != 0) {
arc_buf_destroy(buf, private);
buf = NULL;
}
- ASSERT((zio_flags & ZIO_FLAG_SPECULATIVE) || rc == 0);
+ /* assert any errors weren't due to unloaded keys */
+ ASSERT((zio_flags & ZIO_FLAG_SPECULATIVE) ||
+ rc != ENOENT);
} else if (*arc_flags & ARC_FLAG_PREFETCH &&
refcount_count(&hdr->b_l1hdr.b_refcnt) == 0) {
arc_hdr_set_flags(hdr, ARC_FLAG_PREFETCH);