Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZFS Encryption #4329

Closed
wants to merge 10 commits into from
Closed
55 changes: 41 additions & 14 deletions cmd/zdb/zdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#include <sys/ddt.h>
#include <sys/zfeature.h>
#include <sys/abd.h>
#include <sys/dsl_crypt.h>
#include <zfs_comutil.h>
#include <libzfs.h>

Expand Down Expand Up @@ -1887,6 +1888,7 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
dmu_buf_t *db = NULL;
dmu_object_info_t doi;
dnode_t *dn;
boolean_t dnode_held = B_FALSE;
void *bonus = NULL;
size_t bsize = 0;
char iblk[32], dblk[32], lsize[32], asize[32], fill[32], dnsize[32];
Expand All @@ -1903,16 +1905,33 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)

if (object == 0) {
dn = DMU_META_DNODE(os);
dmu_object_info_from_dnode(dn, &doi);
} else {
error = dmu_bonus_hold(os, object, FTAG, &db);
/*
* Encrypted datasets will have sensitive bonus buffers
* encrypted. Therefore we cannot hold the bonus buffer and
* must get the dnode itself instead.
*/
error = dmu_object_info(os, object, &doi);
if (error)
fatal("dmu_bonus_hold(%llu) failed, errno %u",
object, error);
bonus = db->db_data;
bsize = db->db_size;
dn = DB_DNODE((dmu_buf_impl_t *)db);
fatal("dmu_object_info() failed, errno %u", error);

if (os->os_encrypted &&
DMU_OT_IS_ENCRYPTED(doi.doi_bonus_type)) {
error = dnode_hold(os, object, FTAG, &dn);
if (error)
fatal("dnode_hold() failed, errno %u", error);
dnode_held = B_TRUE;
} else {
error = dmu_bonus_hold(os, object, FTAG, &db);
if (error)
fatal("dmu_bonus_hold(%llu) failed, errno %u",
object, error);
bonus = db->db_data;
bsize = db->db_size;
dn = DB_DNODE((dmu_buf_impl_t *)db);
}
}
dmu_object_info_from_dnode(dn, &doi);

zdb_nicenum(doi.doi_metadata_block_size, iblk);
zdb_nicenum(doi.doi_data_block_size, dblk);
Expand Down Expand Up @@ -1959,8 +1978,13 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
(void) printf("\tdnode maxblkid: %llu\n",
(longlong_t)dn->dn_phys->dn_maxblkid);

object_viewer[ZDB_OT_TYPE(doi.doi_bonus_type)](os, object,
bonus, bsize);
if (!dnode_held) {
object_viewer[ZDB_OT_TYPE(doi.doi_bonus_type)](os,
object, bonus, bsize);
} else {
(void) printf("\t\t(bonus encrypted)\n");
}

object_viewer[ZDB_OT_TYPE(doi.doi_type)](os, object, NULL, 0);
*print_header = 1;
}
Expand Down Expand Up @@ -2003,6 +2027,8 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)

if (db != NULL)
dmu_buf_rele(db, FTAG);
if (dnode_held)
dnode_rele(dn, FTAG);
}

static char *objset_types[DMU_OST_NUMTYPES] = {
Expand Down Expand Up @@ -2299,7 +2325,7 @@ dump_one_dir(const char *dsname, void *arg)
objset_t *os;
spa_feature_t f;

error = dmu_objset_own(dsname, DMU_OST_ANY, B_TRUE, FTAG, &os);
error = dmu_objset_own(dsname, DMU_OST_ANY, B_TRUE, B_FALSE, FTAG, &os);
if (error) {
(void) printf("Could not open %s, error %d\n", dsname, error);
return (0);
Expand Down Expand Up @@ -2747,7 +2773,8 @@ dump_block_stats(spa_t *spa)
zdb_cb_t zcb;
zdb_blkstats_t *zb, *tzb;
uint64_t norm_alloc, norm_space, total_alloc, total_found;
int flags = TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA | TRAVERSE_HARD;
int flags = TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA |
TRAVERSE_NO_DECRYPT | TRAVERSE_HARD;
boolean_t leaks = B_FALSE;
int e, c;
bp_embedded_type_t i;
Expand Down Expand Up @@ -3052,8 +3079,8 @@ dump_simulated_ddt(spa_t *spa)

spa_config_enter(spa, SCL_CONFIG, FTAG, RW_READER);

(void) traverse_pool(spa, 0, TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA,
zdb_ddt_add_cb, &t);
(void) traverse_pool(spa, 0, TRAVERSE_PRE | TRAVERSE_PREFETCH_METADATA |
TRAVERSE_NO_DECRYPT, zdb_ddt_add_cb, &t);

spa_config_exit(spa, SCL_CONFIG, FTAG);

Expand Down Expand Up @@ -3875,7 +3902,7 @@ main(int argc, char **argv)
}
} else {
error = dmu_objset_own(target, DMU_OST_ANY,
B_TRUE, FTAG, &os);
B_TRUE, B_FALSE, FTAG, &os);
}
}
nvlist_free(policy);
Expand Down
11 changes: 8 additions & 3 deletions cmd/zdb/zdb_il.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,13 @@ print_log_record(zilog_t *zilog, lr_t *lr, void *arg, uint64_t claim_txg)
(u_longlong_t)lr->lrc_txg,
(u_longlong_t)lr->lrc_seq);

if (txtype && verbose >= 3)
zil_rec_info[txtype].zri_print(zilog, txtype, lr);
if (txtype && verbose >= 3) {
if (!zilog->zl_os->os_encrypted) {
zil_rec_info[txtype].zri_print(zilog, txtype, lr);
} else {
(void) printf("%s(encrypted)\n", prefix);
}
}

zil_rec_info[txtype].zri_count++;
zil_rec_info[0].zri_count++;
Expand Down Expand Up @@ -399,7 +404,7 @@ dump_intent_log(zilog_t *zilog)
if (verbose >= 2) {
(void) printf("\n");
(void) zil_parse(zilog, print_log_block, print_log_record, NULL,
zh->zh_claim_txg);
zh->zh_claim_txg, B_FALSE);
print_log_stats(verbose);
}
}
2 changes: 1 addition & 1 deletion cmd/zed/agents/zfs_mod.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ zfs_enable_ds(void *arg)

assert(pool->uap_enable_tid = pthread_self());

(void) zpool_enable_datasets(pool->uap_zhp, NULL, 0);
(void) zpool_enable_datasets(pool->uap_zhp, NULL, 0, B_FALSE);
zpool_close(pool->uap_zhp);
pool->uap_zhp = NULL;

Expand Down
119 changes: 118 additions & 1 deletion cmd/zfs/zfs_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ static int zfs_do_holds(int argc, char **argv);
static int zfs_do_release(int argc, char **argv);
static int zfs_do_diff(int argc, char **argv);
static int zfs_do_bookmark(int argc, char **argv);
static int zfs_do_key(int argc, char **argv);

/*
* Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
Expand Down Expand Up @@ -150,6 +151,7 @@ typedef enum {
HELP_RELEASE,
HELP_DIFF,
HELP_BOOKMARK,
HELP_KEY,
} zfs_help_t;

typedef struct zfs_command {
Expand Down Expand Up @@ -203,6 +205,7 @@ static zfs_command_t command_table[] = {
{ "holds", zfs_do_holds, HELP_HOLDS },
{ "release", zfs_do_release, HELP_RELEASE },
{ "diff", zfs_do_diff, HELP_DIFF },
{ "key", zfs_do_key, HELP_KEY },
};

#define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
Expand Down Expand Up @@ -321,6 +324,10 @@ get_usage(zfs_help_t idx)
"[snapshot|filesystem]\n"));
case HELP_BOOKMARK:
return (gettext("\tbookmark <snapshot> <bookmark>\n"));
case HELP_KEY:
return (gettext("\tkey [-lu] <filesystem|volume>\n"
"\tkey -c [-o keysource=<value>] [-o pbkfd2iters=<value>] "
"<filesystem|volume>\n"));
}

abort();
Expand Down Expand Up @@ -874,7 +881,7 @@ zfs_do_create(int argc, char **argv)
(void) snprintf(msg, sizeof (msg),
gettext("cannot create '%s'"), argv[0]);
if (props && (real_props = zfs_valid_proplist(g_zfs, type,
props, 0, NULL, zpool_handle, msg)) == NULL) {
props, 0, NULL, zpool_handle, B_TRUE, msg)) == NULL) {
zpool_close(zpool_handle);
goto error;
}
Expand Down Expand Up @@ -4145,6 +4152,8 @@ zfs_do_receive(int argc, char **argv)
#define ZFS_DELEG_PERM_RELEASE "release"
#define ZFS_DELEG_PERM_DIFF "diff"
#define ZFS_DELEG_PERM_BOOKMARK "bookmark"
#define ZFS_DELEG_PERM_LOAD_KEY "keyuse"
#define ZFS_DELEG_PERM_CHANGE_KEY "keychange"

#define ZFS_NUM_DELEG_NOTES ZFS_DELEG_NOTE_NONE

Expand All @@ -4165,6 +4174,8 @@ static zfs_deleg_perm_tab_t zfs_deleg_perm_tbl[] = {
{ ZFS_DELEG_PERM_SHARE, ZFS_DELEG_NOTE_SHARE },
{ ZFS_DELEG_PERM_SNAPSHOT, ZFS_DELEG_NOTE_SNAPSHOT },
{ ZFS_DELEG_PERM_BOOKMARK, ZFS_DELEG_NOTE_BOOKMARK },
{ ZFS_DELEG_PERM_LOAD_KEY, ZFS_DELEG_NOTE_LOAD_KEY },
{ ZFS_DELEG_PERM_CHANGE_KEY, ZFS_DELEG_NOTE_CHANGE_KEY },

{ ZFS_DELEG_PERM_GROUPQUOTA, ZFS_DELEG_NOTE_GROUPQUOTA },
{ ZFS_DELEG_PERM_GROUPUSED, ZFS_DELEG_NOTE_GROUPUSED },
Expand Down Expand Up @@ -4738,6 +4749,12 @@ deleg_perm_comment(zfs_deleg_note_t note)
case ZFS_DELEG_NOTE_SNAPSHOT:
str = gettext("");
break;
case ZFS_DELEG_NOTE_LOAD_KEY:
str = gettext("Allows loading or unloading an encryption key");
break;
case ZFS_DELEG_NOTE_CHANGE_KEY:
str = gettext("Allows changing or adding an encryption key");
break;
/*
* case ZFS_DELEG_NOTE_VSCAN:
* str = gettext("");
Expand Down Expand Up @@ -6914,6 +6931,106 @@ zfs_do_bookmark(int argc, char **argv)
return (-1);
}

static int
zfs_do_key(int argc, char **argv)
{
int c, ret = -1;
boolean_t load = B_FALSE, unload = B_FALSE, rewrap = B_FALSE;
zfs_handle_t *zhp = NULL;
nvlist_t *props = fnvlist_alloc();

while ((c = getopt(argc, argv, "ulco:")) != -1) {
switch (c) {
case 'u':
if (ret == 0) {
(void) fprintf(stderr, gettext(
"multiple actions specified\n"));
usage(B_FALSE);
}
unload = B_TRUE;
ret = 0;
break;
case 'l':
if (ret == 0) {
(void) fprintf(stderr, gettext(
"multiple actions specified\n"));
usage(B_FALSE);
}
load = B_TRUE;
ret = 0;
break;
case 'c':
if (ret == 0) {
(void) fprintf(stderr, gettext(
"multiple actions specified\n"));
usage(B_FALSE);
}
rewrap = B_TRUE;
ret = 0;
break;
case 'o':
if (parseprop(props, optarg) != 0)
return (1);
break;
default:
(void) fprintf(stderr,
gettext("invalid option '%c'\n"), optopt);
usage(B_FALSE);
}
}

if (ret) {
(void) fprintf(stderr,
gettext("No action specified\n"));
usage(B_FALSE);
}

if (!rewrap && !nvlist_empty(props)) {
(void) fprintf(stderr,
gettext("Properties not allowed for specified command\n"));
usage(B_FALSE);
}

argc -= optind;
argv += optind;

if (argc < 1) {
(void) fprintf(stderr, gettext("Missing dataset argument\n"));
usage(B_FALSE);
}

if (argc > 1) {
(void) fprintf(stderr, gettext("Too many arguments\n"));
usage(B_FALSE);
}

zhp = zfs_open(g_zfs, argv[argc - 1],
ZFS_TYPE_FILESYSTEM|ZFS_TYPE_VOLUME);
if (zhp == NULL)
usage(B_FALSE);

if (load)
ret = zfs_crypto_load_key(zhp);
else if (unload)
ret = zfs_crypto_unload_key(zhp);
else
ret = zfs_crypto_rewrap(zhp, props);

if (ret)
goto error;

nvlist_free(props);
zfs_close(zhp);
return (0);

error:
if (props)
nvlist_free(props);
if (zhp)
zfs_close(zhp);
return (-1);
}

int
main(int argc, char **argv)
{
Expand Down
4 changes: 2 additions & 2 deletions cmd/zinject/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ object_from_path(const char *dataset, const char *path, struct stat64 *statbuf,
*/
sync();

err = dmu_objset_own(dataset, DMU_OST_ZFS, B_TRUE, FTAG, &os);
err = dmu_objset_own(dataset, DMU_OST_ZFS, B_TRUE, B_TRUE, FTAG, &os);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that we actually need any decrypted data here. If we do require it to be decrypted, how does zinject get the keys?

Copy link
Contributor Author

@tcaputi tcaputi Jan 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to err on the side of caution here, and so anything I wasn't sure of required the keys be loaded. I will change this to B_FALSE. (same with the other instance in zinject).

if (err != 0) {
(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
dataset, strerror(err));
Expand Down Expand Up @@ -267,7 +267,7 @@ calculate_range(const char *dataset, err_type_t type, int level, char *range,
* size.
*/
if ((err = dmu_objset_own(dataset, DMU_OST_ANY,
B_TRUE, FTAG, &os)) != 0) {
B_TRUE, B_TRUE, FTAG, &os)) != 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that we actually need any decrypted data here. If we do require it to be decrypted, how does zinject get the keys?

(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
dataset, strerror(err));
goto out;
Expand Down
Loading