From 6d07be898ddc956171468f596bd36f9361d7632c Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Sat, 9 Jun 2012 18:28:00 +0200 Subject: [PATCH] Enhance status of active device. --- lib/libcryptsetup.h | 15 ++++++++ lib/libcryptsetup.sym | 1 + lib/libdevmapper.c | 14 +++++-- lib/setup.c | 27 ++++++++++++- lib/utils_dm.h | 2 +- src/Makefile.am | 4 +- src/veritysetup.c | 90 ++++++++++++++++++++++++++++++++++++++++--- 7 files changed, 140 insertions(+), 13 deletions(-) diff --git a/lib/libcryptsetup.h b/lib/libcryptsetup.h index f281a9bc..3c679743 100644 --- a/lib/libcryptsetup.h +++ b/lib/libcryptsetup.h @@ -370,6 +370,7 @@ struct crypt_params_loopaes { struct crypt_params_verity { const char *hash_name; /**< hash function */ const char *data_device; /**< data_device (CRYPT_VERITY_CREATE_HASH) */ + const char *hash_device; /**< hash_device (output only) */ const char *salt; /**< salt */ uint64_t salt_size; /**< salt size (in bytes) */ uint32_t data_block_size; /**< data block size (in bytes) */ @@ -672,6 +673,8 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot); #define CRYPT_ACTIVATE_ALLOW_DISCARDS (1 << 3) /** skip global udev rules in activation ("private device"), input only */ #define CRYPT_ACTIVATE_PRIVATE (1 << 4) +/** corruption detected (verity), output only */ +#define CRYPT_ACTIVATE_CORRUPTED (1 << 5) /** * Active device runtime attributes @@ -923,6 +926,18 @@ uint64_t crypt_get_iv_offset(struct crypt_device *cd); */ int crypt_get_volume_key_size(struct crypt_device *cd); +/** + * Get device paramaters for CRYPT_VERITY device + * + * @param cd crypt device handle + * @param vp verity device info + * + * @e 0 on success or negative errno value otherwise. + * + */ +int crypt_get_verity_info(struct crypt_device *cd, + struct crypt_params_verity *vp); + /** * @addtogroup keyslot * @{ diff --git a/lib/libcryptsetup.sym b/lib/libcryptsetup.sym index 88feb226..4f054f21 100644 --- a/lib/libcryptsetup.sym +++ b/lib/libcryptsetup.sym @@ -46,6 +46,7 @@ CRYPTSETUP_1.0 { crypt_get_iv_offset; crypt_get_volume_key_size; crypt_get_device_name; + crypt_get_verity_info; crypt_get_type; crypt_get_active_device; diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index c82c0f55..16a863dc 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -959,11 +959,19 @@ int dm_query_device(const char *name, uint32_t get_flags, if (!target_type || start != 0 || next) goto out; - if (!strcmp(target_type, DM_CRYPT_TARGET)) + if (!strcmp(target_type, DM_CRYPT_TARGET)) { r = _dm_query_crypt(get_flags, &dmi, params, dmd); - else if (!strcmp(target_type, DM_VERITY_TARGET)) + } else if (!strcmp(target_type, DM_VERITY_TARGET)) { r = _dm_query_verity(get_flags, &dmi, params, dmd); - else + if (r < 0) + goto out; + r = dm_status_verity_ok(name); + if (r < 0) + goto out; + if (r == 0) + dmd->flags |= CRYPT_ACTIVATE_CORRUPTED; + r = 0; + } else r = -EINVAL; if (r < 0) diff --git a/lib/setup.c b/lib/setup.c index 87afb6f3..9637acef 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -772,13 +772,16 @@ static int _init_by_name_verity(struct crypt_device *cd, const char *name) cd->verity_root_hash = NULL; cd->verity_hdr.hash_name = params.hash_name; cd->verity_hdr.data_device = NULL; + cd->verity_hdr.hash_device = NULL; cd->verity_hdr.data_block_size = params.data_block_size; cd->verity_hdr.hash_block_size = params.hash_block_size; - cd->verity_hdr.hash_area_offset = params.hash_area_offset; + cd->verity_hdr.hash_area_offset = dmd.u.verity.hash_offset; cd->verity_hdr.version = params.version; cd->verity_hdr.flags = params.flags; cd->verity_hdr.salt_size = params.salt_size; cd->verity_hdr.salt = params.salt; + if (!(cd->metadata_device = strdup(dmd.u.verity.hash_device))) + r = -ENOMEM; } out: free(CONST_CAST(void*)dmd.u.verity.hash_device); @@ -2397,6 +2400,26 @@ const char *crypt_get_type(struct crypt_device *cd) return cd->type; } +int crypt_get_verity_info(struct crypt_device *cd, + struct crypt_params_verity *vp) +{ + if (!isVERITY(cd->type) || !vp) + return -EINVAL; + + vp->data_device = cd->device; + vp->hash_device = mdata_device(cd); + vp->hash_name = cd->verity_hdr.hash_name; + vp->salt = cd->verity_hdr.salt; + vp->salt_size = cd->verity_hdr.salt_size; + vp->data_block_size = cd->verity_hdr.data_block_size; + vp->hash_block_size = cd->verity_hdr.hash_block_size; + vp->data_size = cd->verity_hdr.data_size; + vp->hash_area_offset = cd->verity_hdr.hash_area_offset; + vp->version = cd->verity_hdr.version; + vp->flags = cd->verity_hdr.flags & CRYPT_VERITY_NO_HEADER; + return 0; +} + int crypt_get_active_device(struct crypt_device *cd __attribute__((unused)), const char *name, struct crypt_active_device *cad) @@ -2408,7 +2431,7 @@ int crypt_get_active_device(struct crypt_device *cd __attribute__((unused)), if (r < 0) return r; - if (dmd.target != DM_CRYPT) + if (dmd.target != DM_CRYPT && dmd.target != DM_VERITY) return -ENOTSUP; cad->offset = dmd.u.crypt.offset; diff --git a/lib/utils_dm.h b/lib/utils_dm.h index 5a0756ef..ea64b9ed 100644 --- a/lib/utils_dm.h +++ b/lib/utils_dm.h @@ -72,7 +72,7 @@ struct crypt_dm_active_device { const char *root_hash; uint32_t root_hash_size; - uint64_t hash_offset; /* hash offset (not header) */ + uint64_t hash_offset; /* hash offset in blocks (not header) */ struct crypt_params_verity *vp; } verity; } u; diff --git a/src/Makefile.am b/src/Makefile.am index c35a5d17..473120ca 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,7 +41,9 @@ endif if VERITYSETUP veritysetup_SOURCES = \ - veritysetup.c + $(top_builddir)/lib/utils_loop.c \ + veritysetup.c \ + cryptsetup.h veritysetup_LDADD = \ $(top_builddir)/lib/libcryptsetup.la \ diff --git a/src/veritysetup.c b/src/veritysetup.c index e6725375..591c181e 100644 --- a/src/veritysetup.c +++ b/src/veritysetup.c @@ -28,8 +28,10 @@ #include #include #include +#include #include #include +#include #include "cryptsetup.h" @@ -212,8 +214,6 @@ static int _activate(const char *dm_device, crypt_get_volume_key_size(cd), activate_flags); out: - if (!r) - crypt_dump(cd); crypt_free(cd); return r; } @@ -250,13 +250,91 @@ static int action_remove(int arg) static int action_status(int arg) { + crypt_status_info ci; + struct crypt_active_device cad; + struct crypt_params_verity vp = {}; struct crypt_device *cd = NULL; - int r; + struct stat st; + char *backing_file; + int i, path = 0, r = 0; - r = crypt_init_by_name_and_header(&cd, action_argv[0], NULL); - if (!r) - r = crypt_dump(cd); + /* perhaps a path, not a dm device name */ + if (strchr(action_argv[0], '/') && !stat(action_argv[0], &st)) + path = 1; + + ci = crypt_status(NULL, action_argv[0]); + switch (ci) { + case CRYPT_INVALID: + r = -EINVAL; + break; + case CRYPT_INACTIVE: + if (path) + log_std("%s is inactive.\n", action_argv[0]); + else + log_std("%s/%s is inactive.\n", crypt_get_dir(), action_argv[0]); + r = -ENODEV; + break; + case CRYPT_ACTIVE: + case CRYPT_BUSY: + if (path) + log_std("%s is active%s.\n", action_argv[0], + ci == CRYPT_BUSY ? " and is in use" : ""); + else + log_std("%s/%s is active%s.\n", crypt_get_dir(), action_argv[0], + ci == CRYPT_BUSY ? " and is in use" : ""); + + r = crypt_init_by_name_and_header(&cd, action_argv[0], NULL); + if (r < 0 || !crypt_get_type(cd)) + goto out; + + log_std(" type: %s\n", crypt_get_type(cd)); + + r = crypt_get_active_device(cd, action_argv[0], &cad); + if (r < 0) + goto out; + + log_std(" status: %s\n", + cad.flags & CRYPT_ACTIVATE_CORRUPTED ? "corrupted" : "verified"); + + r = crypt_get_verity_info(cd, &vp); + if (r < 0) + goto out; + + log_std(" version: %u\n", vp.version); + log_std(" data block: %u\n", vp.data_block_size); + log_std(" hash block: %u\n", vp.hash_block_size); + log_std(" hash name: %s\n", vp.hash_name); + log_std(" salt: "); + if (vp.salt_size) + for(i = 0; i < vp.salt_size; i++) + log_std("%02hhx", (const char)vp.salt[i]); + else + log_std("-"); + log_std("\n"); + + log_std(" data device: %s\n", vp.data_device); + if (crypt_loop_device(vp.data_device)) { + backing_file = crypt_loop_backing_file(vp.data_device); + log_std(" data loop: %s\n", backing_file); + free(backing_file); + } + log_std(" size: %" PRIu64 " sectors\n", cad.size); + log_std(" mode: %s\n", cad.flags & CRYPT_ACTIVATE_READONLY ? + "readonly" : "read/write"); + + log_std(" hash device: %s\n", vp.hash_device); + if (crypt_loop_device(vp.hash_device)) { + backing_file = crypt_loop_backing_file(vp.hash_device); + log_std(" hash loop: %s\n", backing_file); + free(backing_file); + } + log_std(" hash offset: %" PRIu64 " sectors\n", + vp.hash_area_offset * vp.hash_block_size / 512); + } +out: crypt_free(cd); + if (r == -ENOTSUP) + r = 0; return r; }