Skip to content

Commit

Permalink
Native data and metadata encryption for zfs
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom Caputi committed Jan 6, 2017
1 parent 42b64e5 commit 89b4e7a
Show file tree
Hide file tree
Showing 103 changed files with 8,788 additions and 691 deletions.
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
111 changes: 110 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,98 @@ 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);
}

if (argc < 3) {
(void) fprintf(stderr, gettext("Too few 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);
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) {
(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
dataset, strerror(err));
goto out;
Expand Down
Loading

0 comments on commit 89b4e7a

Please sign in to comment.