Skip to content
This repository has been archived by the owner on Nov 7, 2019. It is now read-only.

Commit

Permalink
8727 Native data and metadata encryption for zfs
Browse files Browse the repository at this point in the history
    This change incorporates three major pieces:

    The first change is a keystore that manages wrapping
    and encryption keys for encrypted datasets. These
    commands mostly involve manipulating the new
    DSL Crypto Key ZAP Objects that live in the MOS. Each
    encrypted dataset has its own DSL Crypto Key that is
    protected with a user's key. This level of indirection
    allows users to change their keys without re-encrypting
    their entire datasets. The change implements the new
    subcommands "zfs load-key", "zfs unload-key" and
    "zfs change-key" which allow the user to manage their
    encryption keys and settings. In addition, several new
    flags and properties have been added to allow dataset
    creation and to make mounting and unmounting more
    convenient.

    The second piece of this patch provides the ability to
    encrypt, decyrpt, and authenticate protected datasets.
    Each object set maintains a Merkel tree of Message
    Authentication Codes that protect the lower layers,
    similarly to how checksums are maintained. This part
    impacts the zio layer, which handles the actual
    encryption and generation of MACs, as well as the ARC
    and DMU, which need to be able to handle encrypted
    buffers and protected data.

    The last addition is the ability to do raw, encrypted
    sends and receives. The idea here is to send raw
    encrypted and compressed data and receive it exactly
    as is on a backup system. This means that the dataset
    on the receiving system is protected using the same
    user key that is in use on the sending side. By doing
    so, datasets can be efficiently backed up to an
    untrusted system without fear of data being
    compromised.

    Reviewed by: Matthew Ahrens <mahrens@delphix.com>
    Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
    Reviewed-by: Jorgen Lundman <lundman@lundman.net>
    Signed-off-by: Tom Caputi <tcaputi@datto.com>

Send / Recv Fixes following b52563

    This patch fixes several issues discovered after
    the encryption patch was merged:

    Fixed a bug where encrypted datasets could attempt
    to receive embedded data records.

    Fixed a bug where dirty records created by the recv
    code wasn't properly setting the dr_raw flag.

    Fixed a typo where a dmu_tx_commit() was changed to
    dmu_tx_abort()

    Fixed a few error handling bugs unrelated to the
    encryption patch in dmu_recv_stream()

    Signed-off-by: Tom Caputi <tcaputi@datto.com>

Encryption patch follow-up

* HKDF implementation moved to its own file and tests added to ensure
correctness.

* Ztest can now create and test encrypted datasets. This is currently
disabled until issue ZOL #6526 is resolved, but otherwise functions as
advertised.

* Several small bug fixes discovered after enabling ztest to run on
encrypted datasets.

* Fixed coverity defects added by the encryption patch.

* Updated man pages for encrypted send / receive behavior.

* Fixed a bug where encrypted datasets could receive
  DRR_WRITE_EMBEDDED records.

* Minor code cleanups / consolidation.

Disable crypto tests in ztest

* Includes fix in dmu_free_long_object_impl

Unless permission is given to compile the crypto framework in userland
the crypto tests in ztest are disabled on IllumOS.
  • Loading branch information
Tom Caputi authored and lundman committed Oct 24, 2017
1 parent 843abe1 commit 9bb6c76
Show file tree
Hide file tree
Showing 165 changed files with 17,172 additions and 1,381 deletions.
21 changes: 17 additions & 4 deletions usr/src/cmd/mdb/common/modules/zfs/zfs.c
Expand Up @@ -66,6 +66,10 @@ enum spa_flags {
SPA_FLAG_HISTOGRAMS = 1 << 5
};


const dmu_object_type_info_t dmu_ot[DMU_OT_NUMTYPES] = {0};


/*
* If any of these flags are set, call spa_vdevs in spa_print
*/
Expand Down Expand Up @@ -424,7 +428,7 @@ zfs_params(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
static int
blkptr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
char type[80], checksum[80], compress[80];
char type[80], checksum[80], compress[80], *crypt_type;
blkptr_t blk, *bp = &blk;
char buf[BP_SPRINTF_LEN];

Expand All @@ -443,8 +447,19 @@ blkptr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_ERR);
}

if (BP_IS_ENCRYPTED(bp)) {
crypt_type = "encrypted";
/* LINTED E_SUSPICIOUS_COMPARISON */
} else if (BP_IS_AUTHENTICATED(bp)) {
crypt_type = "authenticated";
} else if (BP_HAS_INDIRECT_MAC_CKSUM(bp)) {
crypt_type = "indirect-MAC";
} else {
crypt_type = "unencrypted";
}

SNPRINTF_BLKPTR(mdb_snprintf, '\n', buf, sizeof (buf), bp, type,
checksum, compress);
checksum, crypt_type, compress);

mdb_printf("%s\n", buf);

Expand Down Expand Up @@ -2672,8 +2687,6 @@ zfs_blkstats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
dmu_object_type_t t;
zfs_blkstat_t *tzb;
uint64_t ditto;
dmu_object_type_info_t dmu_ot[DMU_OT_NUMTYPES + 10];
/* +10 in case it grew */

if (mdb_readvar(&dmu_ot, "dmu_ot") == -1) {
mdb_warn("failed to read 'dmu_ot'");
Expand Down
3 changes: 2 additions & 1 deletion usr/src/cmd/mdb/intel/amd64/libzpool/Makefile
Expand Up @@ -39,7 +39,8 @@ MODSRCS_DIR = ../../../common/modules/zfs
GENUNIX_DIR = ../../../common/modules/genunix

CPPFLAGS += -I../../../../../lib/libzpool/common \
-I../../../../../uts/common/fs/zfs
-I../../../../../uts/common/fs/zfs \
-I../../../../../common/zfs

C99MODE= -xc99=%all
C99LMODE= -Xc99=%all
Expand Down
1 change: 1 addition & 0 deletions usr/src/cmd/mdb/intel/amd64/zfs/Makefile
Expand Up @@ -39,6 +39,7 @@ include ../../../common/modules/zfs/Makefile.zfs

CPPFLAGS += -I../../../../../uts/common/fs/zfs
CPPFLAGS += -I../../../../../uts/common/fs/zfs/lua
CPPFLAGS += -I../../../../../common/zfs

C99MODE= -xc99=%all
C99LMODE= -Xc99=%all
Expand Down
3 changes: 2 additions & 1 deletion usr/src/cmd/mdb/intel/ia32/libzpool/Makefile
Expand Up @@ -41,7 +41,8 @@ GENUNIX_DIR = ../../../common/modules/genunix

CPPFLAGS += -I../../../../../lib/libzpool/common \
-I../../../../../uts/common/fs/zfs \
-I../../../../../uts/common/fs/zfs/lua
-I../../../../../uts/common/fs/zfs/lua \
-I../../../../../common/zfs

C99MODE= -xc99=%all
C99LMODE= -Xc99=%all
Expand Down
1 change: 1 addition & 0 deletions usr/src/cmd/mdb/intel/ia32/zfs/Makefile
Expand Up @@ -38,6 +38,7 @@ include ../../../common/modules/zfs/Makefile.zfs

CPPFLAGS += -I../../../../../uts/common/fs/zfs
CPPFLAGS += -I../../../../../uts/common/fs/zfs/lua
CPPFLAGS += -I../../../../../common/zfs

C99MODE= -xc99=%all
C99LMODE= -Xc99=%all
Expand Down
3 changes: 2 additions & 1 deletion usr/src/cmd/mdb/sparc/v7/libzpool/Makefile
Expand Up @@ -41,7 +41,8 @@ GENUNIX_DIR = ../../../common/modules/genunix

CPPFLAGS += -I../../../../../lib/libzpool/common \
-I../../../../../uts/common/fs/zfs \
-I../../../../../uts/common/fs/zfs/lua
-I../../../../../uts/common/fs/zfs/lua \
-I../../../../../common/zfs

C99MODE= -xc99=%all
C99LMODE= -Xc99=%all
Expand Down
3 changes: 2 additions & 1 deletion usr/src/cmd/mdb/sparc/v9/libzpool/Makefile
Expand Up @@ -42,7 +42,8 @@ GENUNIX_DIR = ../../../common/modules/genunix

CPPFLAGS += -I../../../../../lib/libzpool/common \
-I../../../../../uts/common/fs/zfs \
-I../../../../../uts/common/fs/zfs/lua
-I../../../../../uts/common/fs/zfs/lua \
-I../../../../../common/zfs

C99MODE= -xc99=%all
C99LMODE= -Xc99=%all
Expand Down
3 changes: 3 additions & 0 deletions usr/src/cmd/zdb/Makefile.com
Expand Up @@ -62,6 +62,9 @@ LINTFLAGS64 += -xerroff=E_NAME_DEF_NOT_USED2
LINTFLAGS += -erroff=E_STATIC_UNUSED
LINTFLAGS64 += -erroff=E_STATIC_UNUSED

LINTFLAGS += -erroff=E_BAD_PTR_CAST_ALIGN
LINTFLAGS64 += -erroff=E_BAD_PTR_CAST_ALIGN

.KEEP_STATE:

all: $(PROG)
Expand Down
74 changes: 54 additions & 20 deletions usr/src/cmd/zdb/zdb.c
Expand Up @@ -62,6 +62,7 @@
#include <sys/zfeature.h>
#include <sys/abd.h>
#include <sys/blkptr.h>
#include <sys/dsl_crypt.h>
#include <zfs_comutil.h>
#include <libcmdutils.h>
#undef verify
Expand Down Expand Up @@ -1200,7 +1201,7 @@ static void
snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp)
{
const dva_t *dva = bp->blk_dva;
int ndvas = dump_opt['d'] > 5 ? BP_GET_NDVAS(bp) : 1;
unsigned int ndvas = dump_opt['d'] > 5 ? BP_GET_NDVAS(bp) : 1;

if (dump_opt['b'] >= 6) {
snprintf_blkptr(blkbuf, buflen, bp);
Expand All @@ -1218,7 +1219,7 @@ snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp)
}

blkbuf[0] = '\0';
for (int i = 0; i < ndvas; i++)
for (unsigned int i = 0; i < ndvas; i++)
(void) snprintf(blkbuf + strlen(blkbuf),
buflen - strlen(blkbuf), "%llu:%llx:%llx ",
(u_longlong_t)DVA_GET_VDEV(&dva[i]),
Expand Down Expand Up @@ -1641,14 +1642,14 @@ open_objset(const char *path, dmu_objset_type_t type, void *tag, objset_t **osp)
uint64_t version = 0;

VERIFY3P(sa_os, ==, NULL);
err = dmu_objset_own(path, type, B_TRUE, tag, osp);
err = dmu_objset_own(path, type, B_TRUE, B_FALSE, tag, osp);
if (err != 0) {
(void) fprintf(stderr, "failed to own dataset '%s': %s\n", path,
strerror(err));
return (err);
}

if (dmu_objset_type(*osp) == DMU_OST_ZFS) {
if (dmu_objset_type(*osp) == DMU_OST_ZFS && !(*osp)->os_encrypted) {
(void) zap_lookup(*osp, MASTER_NODE_OBJ, ZPL_VERSION_STR,
8, 1, &version);
if (version >= ZPL_VERSION_SA) {
Expand All @@ -1660,7 +1661,7 @@ open_objset(const char *path, dmu_objset_type_t type, void *tag, objset_t **osp)
if (err != 0) {
(void) fprintf(stderr, "sa_setup failed: %s\n",
strerror(err));
dmu_objset_disown(*osp, tag);
dmu_objset_disown(*osp, B_FALSE, tag);
*osp = NULL;
}
}
Expand All @@ -1675,7 +1676,7 @@ close_objset(objset_t *os, void *tag)
VERIFY3P(os, ==, sa_os);
if (os->os_sa != NULL)
sa_tear_down(os);
dmu_objset_disown(os, tag);
dmu_objset_disown(os, B_FALSE, tag);
sa_attr_table = NULL;
sa_os = NULL;
}
Expand Down Expand Up @@ -1828,6 +1829,7 @@ dump_dmu_objset(objset_t *os, uint64_t object, void *data, size_t size)
{
}


static object_viewer_t *object_viewer[DMU_OT_NUMTYPES + 1] = {
dump_none, /* unallocated */
dump_zap, /* object directory */
Expand Down Expand Up @@ -1892,6 +1894,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];
Expand All @@ -1915,16 +1918,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 hold 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, sizeof (iblk));
zdb_nicenum(doi.doi_data_block_size, dblk, sizeof (dblk));
Expand Down Expand Up @@ -1968,9 +1988,20 @@ 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);
object_viewer[ZDB_OT_TYPE(doi.doi_type)](os, object, NULL, 0);
if (!dnode_held) {
object_viewer[ZDB_OT_TYPE(doi.doi_bonus_type)](os,
object, bonus, bsize);
} else {
(void) printf("\t\t(bonus encrypted)\n");
}

if (!os->os_encrypted || !DMU_OT_IS_ENCRYPTED(doi.doi_type)) {
object_viewer[ZDB_OT_TYPE(doi.doi_type)](os, object,
NULL, 0);
} else {
(void) printf("\t\t(object encrypted)\n");
}

*print_header = 1;
}

Expand Down Expand Up @@ -2014,6 +2045,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 const char *objset_types[DMU_OST_NUMTYPES] = {
Expand Down Expand Up @@ -2321,7 +2354,7 @@ dump_path(char *ds, char *path)
if (err != 0) {
(void) fprintf(stderr, "can't lookup root znode: %s\n",
strerror(err));
dmu_objset_disown(os, FTAG);
dmu_objset_disown(os, B_FALSE, FTAG);
return (EINVAL);
}

Expand Down Expand Up @@ -2898,7 +2931,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;

bzero(&zcb, sizeof (zcb));
Expand Down Expand Up @@ -3213,8 +3247,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
11 changes: 8 additions & 3 deletions usr/src/cmd/zdb/zdb_il.c
Expand Up @@ -322,8 +322,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", tab_prefix);
}
}

zil_rec_info[txtype].zri_count++;
zil_rec_info[0].zri_count++;
Expand Down Expand Up @@ -410,7 +415,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);
}
}

0 comments on commit 9bb6c76

Please sign in to comment.