diff options
Diffstat (limited to 'src/erasurecode.c')
-rw-r--r-- | src/erasurecode.c | 97 |
1 files changed, 70 insertions, 27 deletions
diff --git a/src/erasurecode.c b/src/erasurecode.c index 67ca393..73091fd 100644 --- a/src/erasurecode.c +++ b/src/erasurecode.c @@ -26,6 +26,7 @@ * vi: set noai tw=79 ts=4 sw=4: */ +#include "assert.h" #include "list.h" #include "erasurecode.h" #include "erasurecode_backend.h" @@ -578,10 +579,22 @@ int liberasurecode_decode(int desc, m = instance->args.uargs.m; if (num_fragments < k) { + log_error("Not enough fragments to decode, got %d, need %d!", + num_fragments, k); ret = -EINSUFFFRAGS; goto out; } + for (i = 0; i < num_fragments; ++i) { + /* Verify metadata checksum */ + if (is_invalid_fragment_header( + (fragment_header_t *) available_fragments[i])) { + log_error("Invalid fragment header information!"); + ret = -EBADHEADER; + goto out; + } + } + if (instance->common.id != EC_BACKEND_SHSS) { /* shss (ntt_backend) must force to decode */ // TODO: Add a frag and function to handle whether the backend want to decode or not. @@ -783,6 +796,16 @@ int liberasurecode_reconstruct_fragment(int desc, k = instance->args.uargs.k; m = instance->args.uargs.m; + for (i = 0; i < num_fragments; i++) { + /* Verify metadata checksum */ + if (is_invalid_fragment_header( + (fragment_header_t *) available_fragments[i])) { + log_error("Invalid fragment header information!"); + ret = -EBADHEADER; + goto out; + } + } + /* * Allocate arrays for data, parity and missing_idxs */ @@ -1004,6 +1027,14 @@ int liberasurecode_get_fragment_metadata(char *fragment, goto out; } + /* Verify metadata checksum */ + if (is_invalid_fragment_header( + (fragment_header_t *) fragment)) { + log_error("Invalid fragment header information!"); + ret = -EBADHEADER; + goto out; + } + memcpy(fragment_metadata, fragment, sizeof(struct fragment_metadata)); fragment_hdr = (fragment_header_t *) fragment; if (LIBERASURECODE_FRAG_HEADER_MAGIC != fragment_hdr->magic) { @@ -1037,6 +1068,20 @@ out: return ret; } +int is_invalid_fragment_header(fragment_header_t *header) +{ + uint32_t *stored_csum = NULL, csum = 0; + assert (NULL != header); + if (header->libec_version < _VERSION(1,2,0)) + /* no metadata checksum support */ + return 0; + stored_csum = get_metadata_chksum((char *) header); + if (NULL == stored_csum) + return 1; /* can't verify, possibly crc32 call error */ + csum = crc32(0, &header->meta, sizeof(fragment_metadata_t)); + return (*stored_csum != csum); +} + int liberasurecode_verify_fragment_metadata(ec_backend_t be, fragment_metadata_t *md) { @@ -1054,6 +1099,27 @@ int liberasurecode_verify_fragment_metadata(ec_backend_t be, return 0; } +int is_invalid_fragment_metadata(int desc, fragment_metadata_t *fragment_metadata) +{ + ec_backend_t be = liberasurecode_backend_instance_get_by_desc(desc); + if (!be) { + log_error("Unable to verify fragment metadata: invalid backend id %d.", + desc); + return -EINVALIDPARAMS; + } + if (liberasurecode_verify_fragment_metadata(be, + fragment_metadata) != 0) { + return -EBADHEADER; + } + if (!be->common.ops->is_compatible_with(fragment_metadata->backend_version)) { + return -EBADHEADER; + } + if (fragment_metadata->chksum_mismatch == 1) { + return -EBADCHKSUM; + } + return 0; +} + int is_invalid_fragment(int desc, char *fragment) { uint32_t ver = 0; @@ -1069,41 +1135,18 @@ int is_invalid_fragment(int desc, char *fragment) return 1; } if (get_libec_version(fragment, &ver) != 0 || - ver != LIBERASURECODE_VERSION) { + ver > LIBERASURECODE_VERSION) { return 1; } - if (liberasurecode_get_fragment_metadata(fragment, - &fragment_metadata) != 0) { + if (liberasurecode_get_fragment_metadata(fragment, &fragment_metadata) != 0) { return 1; } - if (liberasurecode_verify_fragment_metadata(be, - &fragment_metadata) != 0) { + if (is_invalid_fragment_metadata(desc, &fragment_metadata) != 0) { return 1; } return 0; } -int is_valid_fragment_metadata(int desc, fragment_metadata_t *fragment_metadata) -{ - ec_backend_t be = liberasurecode_backend_instance_get_by_desc(desc); - if (!be) { - log_error("Unable to verify stripe metadata: invalid backend id %d.", - desc); - return -EINVALIDPARAMS; - } - if (liberasurecode_verify_fragment_metadata(be, - fragment_metadata) != 0) { - return -EBADHEADER; - } - if (!be->common.ops->is_compatible_with(fragment_metadata->backend_version)) { - return -EBADHEADER; - } - if (fragment_metadata->chksum_mismatch == 1) { - return -EBADCHKSUM; - } - return 0; -} - int liberasurecode_verify_stripe_metadata(int desc, char **fragments, int num_fragments) { @@ -1120,7 +1163,7 @@ int liberasurecode_verify_stripe_metadata(int desc, for (i = 0; i < num_fragments; i++) { fragment_metadata_t *fragment_metadata = (fragment_metadata_t*)fragments[i]; - int ret = is_valid_fragment_metadata(desc, fragment_metadata); + int ret = is_invalid_fragment_metadata(desc, fragment_metadata); if (ret < 0) { return ret; } |