mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-03-14 06:16:17 +03:00
zdb: handle key load/derive failures a bit more gracefully
There's no real need to outright crash if key loading fails; we can just unwind nicely. Sponsored-by: TrueNAS Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Alexander Motin <alexander.motin@TrueNAS.com> Signed-off-by: Rob Norris <rob.norris@truenas.com> Closes #18230
This commit is contained in:
parent
9f874ad092
commit
d11c661544
@ -36,6 +36,7 @@
|
|||||||
* Copyright (c) 2021 Toomas Soome <tsoome@me.com>
|
* Copyright (c) 2021 Toomas Soome <tsoome@me.com>
|
||||||
* Copyright (c) 2023, 2024, Klara Inc.
|
* Copyright (c) 2023, 2024, Klara Inc.
|
||||||
* Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
|
* Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
|
||||||
|
* Copyright (c) 2026, TrueNAS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -3390,14 +3391,14 @@ zdb_derive_key(dsl_dir_t *dd, uint8_t *key_out)
|
|||||||
static char encroot[ZFS_MAX_DATASET_NAME_LEN];
|
static char encroot[ZFS_MAX_DATASET_NAME_LEN];
|
||||||
static boolean_t key_loaded = B_FALSE;
|
static boolean_t key_loaded = B_FALSE;
|
||||||
|
|
||||||
static void
|
static int
|
||||||
zdb_load_key(objset_t *os)
|
zdb_load_key(objset_t *os)
|
||||||
{
|
{
|
||||||
dsl_pool_t *dp;
|
dsl_pool_t *dp;
|
||||||
dsl_dir_t *dd, *rdd;
|
dsl_dir_t *dd, *rdd;
|
||||||
uint8_t key[WRAPPING_KEY_LEN];
|
uint8_t key[WRAPPING_KEY_LEN];
|
||||||
uint64_t rddobj;
|
uint64_t rddobj;
|
||||||
int err;
|
int err = 0;
|
||||||
|
|
||||||
dp = spa_get_dsl(os->os_spa);
|
dp = spa_get_dsl(os->os_spa);
|
||||||
dd = os->os_dsl_dataset->ds_dir;
|
dd = os->os_dsl_dataset->ds_dir;
|
||||||
@ -3410,10 +3411,14 @@ zdb_load_key(objset_t *os)
|
|||||||
dsl_dir_rele(rdd, FTAG);
|
dsl_dir_rele(rdd, FTAG);
|
||||||
|
|
||||||
if (!zdb_derive_key(dd, key))
|
if (!zdb_derive_key(dd, key))
|
||||||
fatal("couldn't derive encryption key");
|
err = EINVAL;
|
||||||
|
|
||||||
dsl_pool_config_exit(dp, FTAG);
|
dsl_pool_config_exit(dp, FTAG);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
fprintf(stderr, "couldn't derive encryption key\n");
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT3U(dsl_dataset_get_keystatus(dd), ==, ZFS_KEYSTATUS_UNAVAILABLE);
|
ASSERT3U(dsl_dataset_get_keystatus(dd), ==, ZFS_KEYSTATUS_UNAVAILABLE);
|
||||||
|
|
||||||
dsl_crypto_params_t *dcp;
|
dsl_crypto_params_t *dcp;
|
||||||
@ -3429,16 +3434,20 @@ zdb_load_key(objset_t *os)
|
|||||||
dsl_crypto_params_free(dcp, (err != 0));
|
dsl_crypto_params_free(dcp, (err != 0));
|
||||||
fnvlist_free(crypto_args);
|
fnvlist_free(crypto_args);
|
||||||
|
|
||||||
if (err != 0)
|
if (err != 0) {
|
||||||
fatal(
|
fprintf(stderr,
|
||||||
"couldn't load encryption key for %s: %s",
|
"couldn't load encryption key for %s: %s\n",
|
||||||
encroot, err == ZFS_ERR_CRYPTO_NOTSUP ?
|
encroot, err == ZFS_ERR_CRYPTO_NOTSUP ?
|
||||||
"crypto params not supported" : strerror(err));
|
"crypto params not supported" : strerror(err));
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT3U(dsl_dataset_get_keystatus(dd), ==, ZFS_KEYSTATUS_AVAILABLE);
|
ASSERT3U(dsl_dataset_get_keystatus(dd), ==, ZFS_KEYSTATUS_AVAILABLE);
|
||||||
|
|
||||||
printf("Unlocked encryption root: %s\n", encroot);
|
printf("Unlocked encryption root: %s\n", encroot);
|
||||||
key_loaded = B_TRUE;
|
key_loaded = B_TRUE;
|
||||||
|
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3492,12 +3501,16 @@ open_objset(const char *path, const void *tag, objset_t **osp)
|
|||||||
dsl_dataset_long_hold(dmu_objset_ds(*osp), tag);
|
dsl_dataset_long_hold(dmu_objset_ds(*osp), tag);
|
||||||
dsl_pool_rele(dmu_objset_pool(*osp), tag);
|
dsl_pool_rele(dmu_objset_pool(*osp), tag);
|
||||||
|
|
||||||
/* succeeds or dies */
|
err = zdb_load_key(*osp);
|
||||||
zdb_load_key(*osp);
|
|
||||||
|
|
||||||
/* release it all */
|
/* release it all */
|
||||||
dsl_dataset_long_rele(dmu_objset_ds(*osp), tag);
|
dsl_dataset_long_rele(dmu_objset_ds(*osp), tag);
|
||||||
dsl_dataset_rele(dmu_objset_ds(*osp), tag);
|
dsl_dataset_rele(dmu_objset_ds(*osp), tag);
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
*osp = NULL;
|
||||||
|
return (err);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dmu_objset_rele(*osp, tag);
|
dmu_objset_rele(*osp, tag);
|
||||||
}
|
}
|
||||||
@ -3509,6 +3522,7 @@ open_objset(const char *path, const void *tag, objset_t **osp)
|
|||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
(void) fprintf(stderr, "failed to hold dataset '%s': %s\n",
|
(void) fprintf(stderr, "failed to hold dataset '%s': %s\n",
|
||||||
path, strerror(err));
|
path, strerror(err));
|
||||||
|
*osp = NULL;
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
dsl_dataset_long_hold(dmu_objset_ds(*osp), tag);
|
dsl_dataset_long_hold(dmu_objset_ds(*osp), tag);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user