Skip to content

Commit ea74cde

Browse files
authored
Fix 2 bugs in non-raw send with encryption
Bisecting identified the redacted send/receive as the source of the bug for issue #12014. Specifically the call to dsl_dataset_hold_obj(&fromds) has been replaced by dsl_dataset_hold_obj_flags() which passes a DECRYPT flag and creates a key mapping. A subsequent dsl_dataset_rele_flag(&fromds) is missing and the key mapping is not cleared. This may be inadvertedly used, which results in arc_untransform failing with ECKSUM in: arc_untransform+0x96/0xb0 [zfs] dbuf_read_verify_dnode_crypt+0x196/0x350 [zfs] dbuf_read+0x56/0x770 [zfs] dmu_buf_hold_by_dnode+0x4a/0x80 [zfs] zap_lockdir+0x87/0xf0 [zfs] zap_lookup_norm+0x5c/0xd0 [zfs] zap_lookup+0x16/0x20 [zfs] zfs_get_zplprop+0x8d/0x1d0 [zfs] setup_featureflags+0x267/0x2e0 [zfs] dmu_send_impl+0xe7/0xcb0 [zfs] dmu_send_obj+0x265/0x360 [zfs] zfs_ioc_send+0x10c/0x280 [zfs] Fix this by restoring the call to dsl_dataset_hold_obj(). The same applies for to_ds: here replace dsl_dataset_rele(&to_ds) with dsl_dataset_rele_flags(). Both leaked key mappings will cause a panic when exporting the sending pool or unloading the zfs module after a non-raw send from an encrypted filesystem. Contributions-by: Hank Barta <[email protected]> Contributions-by: Paul Dagnelie <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Richard Yao <[email protected]> Reviewed-by: Rob Norris <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: George Amanakis <[email protected]> Closes #12014 Closes #17340
1 parent e55225b commit ea74cde

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

module/zfs/dmu_send.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2687,8 +2687,8 @@ dmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap,
26872687
}
26882688

26892689
if (fromsnap != 0) {
2690-
err = dsl_dataset_hold_obj_flags(dspp.dp, fromsnap, dsflags,
2691-
FTAG, &fromds);
2690+
err = dsl_dataset_hold_obj(dspp.dp, fromsnap, FTAG, &fromds);
2691+
26922692
if (err != 0) {
26932693
dsl_dataset_rele_flags(dspp.to_ds, dsflags, FTAG);
26942694
dsl_pool_rele(dspp.dp, FTAG);
@@ -2740,7 +2740,7 @@ dmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap,
27402740
kmem_free(dspp.fromredactsnaps,
27412741
dspp.numfromredactsnaps * sizeof (uint64_t));
27422742

2743-
dsl_dataset_rele(dspp.to_ds, FTAG);
2743+
dsl_dataset_rele_flags(dspp.to_ds, dsflags, FTAG);
27442744
return (err);
27452745
}
27462746

0 commit comments

Comments
 (0)