mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
opal: do not always re-lock range on failed activation.
If activation fails due to already active dm mapping we must not automatically re-lock the OPAL range since it would break the original active device.
This commit is contained in:
committed by
Milan Broz
parent
31027b9240
commit
2e978c8776
@@ -279,7 +279,9 @@ static int opal_range_check_attributes_fd(struct crypt_device *cd,
|
||||
const uint64_t *check_offset_sectors,
|
||||
const uint64_t *check_length_sectors,
|
||||
bool *check_read_locked,
|
||||
bool *check_write_locked)
|
||||
bool *check_write_locked,
|
||||
bool *ret_read_locked,
|
||||
bool *ret_write_locked)
|
||||
{
|
||||
int r;
|
||||
struct opal_lr_status *lrs;
|
||||
@@ -291,15 +293,15 @@ static int opal_range_check_attributes_fd(struct crypt_device *cd,
|
||||
assert(cd);
|
||||
assert(vk);
|
||||
|
||||
r = opal_geometry_fd(cd, fd, NULL, &opal_block_bytes, NULL, NULL);
|
||||
if (r != OPAL_STATUS_SUCCESS)
|
||||
return -EINVAL;
|
||||
if (check_offset_sectors || check_length_sectors) {
|
||||
r = opal_geometry_fd(cd, fd, NULL, &opal_block_bytes, NULL, NULL);
|
||||
if (r != OPAL_STATUS_SUCCESS)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
lrs = crypt_safe_alloc(sizeof(*lrs));
|
||||
if (!lrs) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!lrs)
|
||||
return -ENOMEM;
|
||||
|
||||
*lrs = (struct opal_lr_status) {
|
||||
.session = {
|
||||
@@ -322,18 +324,22 @@ static int opal_range_check_attributes_fd(struct crypt_device *cd,
|
||||
|
||||
r = 0;
|
||||
|
||||
offset = lrs->range_start * opal_block_bytes / SECTOR_SIZE;
|
||||
if (check_offset_sectors && (offset != *check_offset_sectors)) {
|
||||
log_err(cd, _("OPAL range %d offset %" PRIu64 " does not match expected values %" PRIu64 "."),
|
||||
segment_number, offset, *check_offset_sectors);
|
||||
r = -EINVAL;
|
||||
if (check_offset_sectors) {
|
||||
offset = lrs->range_start * opal_block_bytes / SECTOR_SIZE;
|
||||
if (offset != *check_offset_sectors) {
|
||||
log_err(cd, _("OPAL range %d offset %" PRIu64 " does not match expected values %" PRIu64 "."),
|
||||
segment_number, offset, *check_offset_sectors);
|
||||
r = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
length = lrs->range_length * opal_block_bytes / SECTOR_SIZE;
|
||||
if (check_length_sectors && (length != *check_length_sectors)) {
|
||||
log_err(cd, _("OPAL range %d length %" PRIu64" does not match device length %" PRIu64 "."),
|
||||
segment_number, length, *check_length_sectors);
|
||||
r = -EINVAL;
|
||||
if (check_length_sectors) {
|
||||
length = lrs->range_length * opal_block_bytes / SECTOR_SIZE;
|
||||
if (length != *check_length_sectors) {
|
||||
log_err(cd, _("OPAL range %d length %" PRIu64" does not match device length %" PRIu64 "."),
|
||||
segment_number, length, *check_length_sectors);
|
||||
r = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!lrs->RLE || !lrs->WLE) {
|
||||
@@ -357,6 +363,11 @@ static int opal_range_check_attributes_fd(struct crypt_device *cd,
|
||||
log_err(cd, _("Unexpected OPAL range %d lock state."), segment_number);
|
||||
r = -EINVAL;
|
||||
}
|
||||
|
||||
if (ret_read_locked)
|
||||
*ret_read_locked = read_locked;
|
||||
if (ret_write_locked)
|
||||
*ret_write_locked = write_locked;
|
||||
out:
|
||||
crypt_safe_free(lrs);
|
||||
|
||||
@@ -642,7 +653,8 @@ int opal_setup_ranges(struct crypt_device *cd,
|
||||
|
||||
/* Double check the locking range is locked and the ranges are set up as configured */
|
||||
r = opal_range_check_attributes_fd(cd, fd, segment_number, vk, &range_start,
|
||||
&range_length, &(bool) {true}, &(bool){true});
|
||||
&range_length, &(bool) {true}, &(bool){true},
|
||||
NULL, NULL);
|
||||
out:
|
||||
crypt_safe_free(activate);
|
||||
crypt_safe_free(user_session);
|
||||
@@ -902,14 +914,14 @@ int opal_geometry(struct crypt_device *cd,
|
||||
ret_alignment_granularity_blocks, ret_lowest_lba_blocks);
|
||||
}
|
||||
|
||||
int opal_range_check_attributes(struct crypt_device *cd,
|
||||
int opal_range_check_attributes_and_get_lock_state(struct crypt_device *cd,
|
||||
struct device *dev,
|
||||
uint32_t segment_number,
|
||||
const struct volume_key *vk,
|
||||
const uint64_t *check_offset_sectors,
|
||||
const uint64_t *check_length_sectors,
|
||||
bool *check_read_locked,
|
||||
bool *check_write_locked)
|
||||
bool *ret_read_locked,
|
||||
bool *ret_write_locked)
|
||||
{
|
||||
int fd;
|
||||
|
||||
@@ -922,8 +934,8 @@ int opal_range_check_attributes(struct crypt_device *cd,
|
||||
return -EIO;
|
||||
|
||||
return opal_range_check_attributes_fd(cd, fd, segment_number, vk,
|
||||
check_offset_sectors, check_length_sectors, check_read_locked,
|
||||
check_write_locked);
|
||||
check_offset_sectors, check_length_sectors, NULL,
|
||||
NULL, ret_read_locked, ret_write_locked);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -986,14 +998,14 @@ int opal_geometry(struct crypt_device *cd,
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int opal_range_check_attributes(struct crypt_device *cd,
|
||||
struct device *dev,
|
||||
uint32_t segment_number,
|
||||
const struct volume_key *vk,
|
||||
const uint64_t *check_offset_sectors,
|
||||
const uint64_t *check_length_sectors,
|
||||
bool *check_read_locked,
|
||||
bool *check_write_locked)
|
||||
int opal_range_check_attributes_and_get_lock_state(struct crypt_device *cd,
|
||||
struct device *dev,
|
||||
uint32_t segment_number,
|
||||
const struct volume_key *vk,
|
||||
const uint64_t *check_offset_sectors,
|
||||
const uint64_t *check_length_sectors,
|
||||
bool *ret_read_locked,
|
||||
bool *ret_write_locked)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
@@ -53,13 +53,13 @@ int opal_geometry(struct crypt_device *cd,
|
||||
uint32_t *ret_block_size,
|
||||
uint64_t *ret_alignment_granularity_blocks,
|
||||
uint64_t *ret_lowest_lba_blocks);
|
||||
int opal_range_check_attributes(struct crypt_device *cd,
|
||||
int opal_range_check_attributes_and_get_lock_state(struct crypt_device *cd,
|
||||
struct device *dev,
|
||||
uint32_t segment_number,
|
||||
const struct volume_key *vk,
|
||||
const uint64_t *check_offset_sectors,
|
||||
const uint64_t *check_length_sectors,
|
||||
bool *check_read_locked,
|
||||
bool *check_write_locked);
|
||||
bool *ret_read_locked,
|
||||
bool *ret_write_locked);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2644,7 +2644,7 @@ int LUKS2_activate(struct crypt_device *cd,
|
||||
uint32_t flags)
|
||||
{
|
||||
int r;
|
||||
bool dynamic;
|
||||
bool dynamic, read_lock, write_lock, opal_lock_on_error = false;
|
||||
uint32_t opal_segment_number;
|
||||
uint64_t range_offset_sectors, range_length_sectors, device_length_bytes;
|
||||
struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
|
||||
@@ -2697,12 +2697,17 @@ int LUKS2_activate(struct crypt_device *cd,
|
||||
}
|
||||
|
||||
range_offset_sectors = crypt_get_data_offset(cd) + crypt_dev_partition_offset(device_path(crypt_data_device(cd)));
|
||||
r = opal_range_check_attributes(cd, crypt_data_device(cd), opal_segment_number,
|
||||
r = opal_range_check_attributes_and_get_lock_state(cd, crypt_data_device(cd), opal_segment_number,
|
||||
opal_key, &range_offset_sectors, &range_length_sectors,
|
||||
NULL /* read locked */, NULL /* write locked */);
|
||||
&read_lock, &write_lock);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
opal_lock_on_error = read_lock && write_lock;
|
||||
if (!opal_lock_on_error && !(flags & CRYPT_ACTIVATE_REFRESH))
|
||||
log_std(cd, _("OPAL device is %s already unlocked!\n"),
|
||||
device_path(crypt_data_device(cd)));
|
||||
|
||||
r = opal_unlock(cd, crypt_data_device(cd), opal_segment_number, opal_key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -2771,7 +2776,7 @@ int LUKS2_activate(struct crypt_device *cd,
|
||||
dm_targets_free(cd, &dmd);
|
||||
dm_targets_free(cd, &dmdi);
|
||||
out:
|
||||
if (r < 0 && opal_key)
|
||||
if (r < 0 && opal_lock_on_error)
|
||||
opal_lock(cd, crypt_data_device(cd), opal_segment_number);
|
||||
|
||||
return r;
|
||||
|
||||
Reference in New Issue
Block a user