Enable userspace FEC decoding in veritysetup.

This commit is contained in:
Michal Virgovič
2018-03-19 10:13:23 +01:00
committed by Milan Broz
parent 5e0db46f17
commit dc58985ac6
4 changed files with 59 additions and 23 deletions

View File

@@ -1812,7 +1812,7 @@ static int _crypt_format_verity(struct crypt_device *cd,
r = VERITY_create(cd, &cd->u.verity.hdr,
cd->u.verity.root_hash, cd->u.verity.root_hash_size);
if (!r && params->fec_device)
r = VERITY_FEC_create(cd, &cd->u.verity.hdr, cd->u.verity.fec_device);
r = VERITY_FEC_process(cd, &cd->u.verity.hdr, cd->u.verity.fec_device, 0, NULL);
if (r)
goto err;
}

View File

@@ -242,6 +242,7 @@ int VERITY_activate(struct crypt_device *cd,
{
struct crypt_dm_active_device dmd;
uint32_t dmv_flags;
unsigned int fec_errors = 0;
int r;
log_dbg("Trying to activate VERITY device %s using hash %s.",
@@ -249,8 +250,18 @@ int VERITY_activate(struct crypt_device *cd,
if (verity_hdr->flags & CRYPT_VERITY_CHECK_HASH) {
log_dbg("Verification of data in userspace required.");
r = VERITY_verify(cd, verity_hdr,
root_hash, root_hash_size);
r = VERITY_verify(cd, verity_hdr, root_hash, root_hash_size);
if (r == -EPERM && fec_device) {
log_dbg("Verification failed, trying to repair with FEC device.");
r = VERITY_FEC_process(cd, verity_hdr, fec_device, 1, &fec_errors);
if (r < 0)
log_err(cd, _("Errors cannot be repaired with FEC device.\n"));
else if (fec_errors)
log_err(cd, _("Found %u repairable errors with FEC device.\n"),
fec_errors);
}
if (r < 0)
return r;
}

View File

@@ -59,9 +59,11 @@ int VERITY_create(struct crypt_device *cd,
char *root_hash,
size_t root_hash_size);
int VERITY_FEC_create(struct crypt_device *cd,
int VERITY_FEC_process(struct crypt_device *cd,
struct crypt_params_verity *params,
struct device *fec_device);
struct device *fec_device,
int check_fec,
unsigned int *errors);
uint64_t VERITY_hash_offset_block(struct crypt_params_verity *params);

View File

@@ -104,18 +104,18 @@ static int FEC_read_interleaved(struct fec_context *ctx, uint64_t i,
return -1;
}
/* encodes inputs to fd */
static int FEC_encode_inputs(struct crypt_device *cd,
struct crypt_params_verity *params,
struct fec_input_device *inputs,
size_t ninputs, int fd)
/* encodes/decode inputs to/from fd */
static int FEC_process_inputs(struct crypt_device *cd,
struct crypt_params_verity *params,
struct fec_input_device *inputs,
size_t ninputs, int fd,
int decode, unsigned int *errors)
{
int r = 0;
unsigned int i;
struct fec_context ctx;
uint32_t b;
uint64_t n;
uint8_t parity[params->fec_roots];
uint8_t rs_block[FEC_RSM];
uint8_t *buf = NULL;
void *rs;
@@ -149,7 +149,7 @@ static int FEC_encode_inputs(struct crypt_device *cd,
goto out;
}
/* encode input */
/* encode/decode input */
for (n = 0; n < ctx.rounds; ++n) {
for (i = 0; i < ctx.rsn; ++i) {
if (FEC_read_interleaved(&ctx, n * ctx.rsn * ctx.block_size + i,
@@ -164,24 +164,44 @@ static int FEC_encode_inputs(struct crypt_device *cd,
for (i = 0; i < ctx.rsn; ++i)
rs_block[i] = buf[i * ctx.block_size + b];
encode_rs_char(rs, rs_block, parity);
if (write_buffer(fd, parity, sizeof(parity)) != (ssize_t)sizeof(parity)) {
log_err(cd, _("Failed to write parity for RS block %" PRIu64 ".\n"), n);
r = -EIO;
goto out;
/* decoding from parity device */
if (decode) {
if (read_buffer(fd, &rs_block[ctx.rsn], ctx.roots) != ctx.roots) {
log_err(cd, _("Failed to read parity for RS block %" PRIu64 ".\n"), n);
r = -EIO;
goto out;
}
r = decode_rs_char(rs, rs_block);
if (r < 0) {
log_err(cd, _("Failed to repair parity for block %" PRIu64 ".\n"), n);
goto out;
}
/* return number of detected errors */
if (errors)
*errors += r;
r = 0;
} else {
/* encoding and writing parity data to fec device */
encode_rs_char(rs, rs_block, &rs_block[ctx.rsn]);
if (write_buffer(fd, &rs_block[ctx.rsn], ctx.roots) != ctx.roots) {
log_err(cd, _("Failed to write parity for RS block %" PRIu64 ".\n"), n);
r = -EIO;
goto out;
}
}
}
}
out:
free_rs_char(rs);
free(buf);
return r;
}
int VERITY_FEC_create(struct crypt_device *cd,
int VERITY_FEC_process(struct crypt_device *cd,
struct crypt_params_verity *params,
struct device *fec_device)
struct device *fec_device, int check_fec,
unsigned int *errors)
{
int r;
int fd = -1;
@@ -212,8 +232,11 @@ int VERITY_FEC_create(struct crypt_device *cd,
r = -EIO;
/* output device */
fd = open(device_path(fec_device), O_RDWR);
if (check_fec)
fd = open(device_path(fec_device), O_RDONLY);
else
fd = open(device_path(fec_device), O_RDWR);
if (fd == -1) {
log_err(cd, _("Cannot open device %s.\n"), device_path(fec_device));
goto out;
@@ -245,7 +268,7 @@ int VERITY_FEC_create(struct crypt_device *cd,
}
inputs[1].count -= inputs[1].start;
r = FEC_encode_inputs(cd, params, inputs, FEC_INPUT_DEVICES, fd);
r = FEC_process_inputs(cd, params, inputs, FEC_INPUT_DEVICES, fd, check_fec, errors);
out:
if (inputs[0].fd != -1)
close(inputs[0].fd);