sed-opal: allow using IOC_OPAL_SAVE for locking too

Usually when closing a crypto device (eg: dm-crypt with LUKS) the
volume key is not required, as it requires root privileges anyway, and
root can deny access to a disk in many ways regardless. Requiring the
volume key to lock the device is a peculiarity of the OPAL
specification.

Given we might already have saved the key if the user requested it via
the 'IOC_OPAL_SAVE' ioctl, we can use that key to lock the device if no
key was provided here and the locking range matches, and the user sets
the appropriate flag with 'IOC_OPAL_SAVE'. This allows integrating OPAL
with tools and libraries that are used to the common behaviour and do
not ask for the volume key when closing a device.

Callers can always pass a non-zero key and it will be used regardless,
as before.

Suggested-by: Štěpán Horáček <stepan.horacek@gmail.com>
Signed-off-by: Luca Boccassi <bluca@debian.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Christian Brauner <brauner@kernel.org>
Link: https://lore.kernel.org/r/20221206092913.4625-1-luca.boccassi@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Luca Boccassi 2022-12-06 09:29:13 +00:00 committed by Jens Axboe
parent 37754595e9
commit c1f480b2d0
2 changed files with 46 additions and 1 deletions

View File

@ -2437,6 +2437,44 @@ static int __opal_set_mbr_done(struct opal_dev *dev, struct opal_key *key)
return execute_steps(dev, mbrdone_step, ARRAY_SIZE(mbrdone_step));
}
static void opal_lock_check_for_saved_key(struct opal_dev *dev,
struct opal_lock_unlock *lk_unlk)
{
struct opal_suspend_data *iter;
if (lk_unlk->l_state != OPAL_LK ||
lk_unlk->session.opal_key.key_len > 0)
return;
/*
* Usually when closing a crypto device (eg: dm-crypt with LUKS) the
* volume key is not required, as it requires root privileges anyway,
* and root can deny access to a disk in many ways regardless.
* Requiring the volume key to lock the device is a peculiarity of the
* OPAL specification. Given we might already have saved the key if
* the user requested it via the 'IOC_OPAL_SAVE' ioctl, we can use
* that key to lock the device if no key was provided here, the
* locking range matches and the appropriate flag was passed with
* 'IOC_OPAL_SAVE'.
* This allows integrating OPAL with tools and libraries that are used
* to the common behaviour and do not ask for the volume key when
* closing a device.
*/
setup_opal_dev(dev);
list_for_each_entry(iter, &dev->unlk_lst, node) {
if ((iter->unlk.flags & OPAL_SAVE_FOR_LOCK) &&
iter->lr == lk_unlk->session.opal_key.lr &&
iter->unlk.session.opal_key.key_len > 0) {
lk_unlk->session.opal_key.key_len =
iter->unlk.session.opal_key.key_len;
memcpy(lk_unlk->session.opal_key.key,
iter->unlk.session.opal_key.key,
iter->unlk.session.opal_key.key_len);
break;
}
}
}
static int opal_lock_unlock(struct opal_dev *dev,
struct opal_lock_unlock *lk_unlk)
{
@ -2446,6 +2484,7 @@ static int opal_lock_unlock(struct opal_dev *dev,
return -EINVAL;
mutex_lock(&dev->dev_lock);
opal_lock_check_for_saved_key(dev, lk_unlk);
ret = __opal_lock_unlock(dev, lk_unlk);
mutex_unlock(&dev->dev_lock);

View File

@ -44,6 +44,11 @@ enum opal_lock_state {
OPAL_LK = 0x04, /* 0100 */
};
enum opal_lock_flags {
/* IOC_OPAL_SAVE will also store the provided key for locking */
OPAL_SAVE_FOR_LOCK = 0x01,
};
struct opal_key {
__u8 lr;
__u8 key_len;
@ -76,7 +81,8 @@ struct opal_user_lr_setup {
struct opal_lock_unlock {
struct opal_session_info session;
__u32 l_state;
__u8 __align[4];
__u16 flags;
__u8 __align[2];
};
struct opal_new_pw {