Fix bug in minimal device size calculation for reencryption.

This commit is contained in:
Ondrej Kozina
2019-07-25 14:02:47 +02:00
parent 35068c2e6e
commit 1b82e70fc1
3 changed files with 24 additions and 8 deletions

View File

@@ -431,6 +431,7 @@ const char *LUKS2_reencrypt_protection_hash(struct luks2_hdr *hdr);
uint64_t LUKS2_reencrypt_data_shift(struct luks2_hdr *hdr);
const char *LUKS2_reencrypt_mode(struct luks2_hdr *hdr);
int LUKS2_reencrypt_direction(struct luks2_hdr *hdr, crypt_reencrypt_direction_info *di);
int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise);
/*
* Generic LUKS2 digest

View File

@@ -1965,13 +1965,7 @@ static int _prepare_multi_dmd(struct crypt_device *cd,
else
device_check = DEV_EXCL;
/* FIXME: replace == 0 with < LUKS2_header_size() */
data_offset = json_segments_get_minimal_offset(jobj_segments, 1);
if (data_offset == 0 &&
crypt_data_device(cd) == crypt_metadata_device(cd)) {
log_dbg(cd, "Internal error. Wrong data offset");
return -EINVAL;
}
data_offset = LUKS2_reencrypt_data_offset(hdr, true);
r = device_block_adjust(cd, crypt_data_device(cd), device_check,
data_offset, &dmd->size, &dmd->flags);

View File

@@ -3262,6 +3262,21 @@ err:
return r;
}
/*
* use only for calculation of minimal data device size.
* The real data offset is taken directly from segments!
*/
int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise)
{
crypt_reencrypt_direction_info di;
uint64_t data_offset = LUKS2_get_data_offset(hdr);
if (!LUKS2_reencrypt_direction(hdr, &di) && (di == CRYPT_REENCRYPT_FORWARD))
data_offset += LUKS2_reencrypt_data_shift(hdr) >> SECTOR_SHIFT;
return blockwise ? data_offset : data_offset << SECTOR_SHIFT;
}
/* internal only */
int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint64_t check_size, uint64_t *dev_size, bool activation, bool dynamic)
{
@@ -3277,7 +3292,7 @@ int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint
if (r)
return r;
data_offset = crypt_get_data_offset(cd) << SECTOR_SHIFT;
data_offset = LUKS2_reencrypt_data_offset(hdr, false);
r = device_check_size(cd, crypt_data_device(cd), data_offset, 1);
if (r)
@@ -3287,6 +3302,12 @@ int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint
if (r)
return r;
log_dbg(cd, "Required minimal device size: %" PRIu64 " (%" PRIu64 " sectors)"
", real device size: %" PRIu64 " (%" PRIu64 " sectors)\n"
"calculated device size: %" PRIu64 " (%" PRIu64 " sectors)",
check_size, check_size >> SECTOR_SHIFT, real_size, real_size >> SECTOR_SHIFT,
real_size - data_offset, (real_size - data_offset) >> SECTOR_SHIFT);
if (real_size < data_offset || (check_size && (real_size - data_offset) < check_size)) {
log_err(cd, _("Device %s is too small."), device_path(crypt_data_device(cd)));
return -EINVAL;