From: Luca Boccassi <bluca@xxxxxxxxxx> 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@xxxxxxxxx> Signed-off-by: Luca Boccassi <bluca@xxxxxxxxxx> --- v2: break on 80chr for optimal rendering on 1970s green monochrome monitors make the new functionality dependent on a new flag that has to be passed to IOC_OPAL_SAVE, using reserved bits in its ioctl struct block/sed-opal.c | 32 ++++++++++++++++++++++++++++++++ include/uapi/linux/sed-opal.h | 3 ++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/block/sed-opal.c b/block/sed-opal.c index 9bdb833e5817..3a81754a0fdf 100644 --- a/block/sed-opal.c +++ b/block/sed-opal.c @@ -2470,6 +2470,38 @@ static int opal_lock_unlock(struct opal_dev *dev, return -EINVAL; mutex_lock(&dev->dev_lock); + + /* + * 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. + */ + if (lk_unlk->l_state == OPAL_LK && + lk_unlk->session.opal_key.key_len == 0) { + struct opal_suspend_data *iter; + + setup_opal_dev(dev); + list_for_each_entry(iter, &dev->unlk_lst, node) { + if (iter->unlk.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; + } + } + } + ret = __opal_lock_unlock(dev, lk_unlk); mutex_unlock(&dev->dev_lock); diff --git a/include/uapi/linux/sed-opal.h b/include/uapi/linux/sed-opal.h index 2573772e2fb3..fa604fb07f50 100644 --- a/include/uapi/linux/sed-opal.h +++ b/include/uapi/linux/sed-opal.h @@ -76,7 +76,8 @@ struct opal_user_lr_setup { struct opal_lock_unlock { struct opal_session_info session; __u32 l_state; - __u8 __align[4]; + __u8 save_for_lock:1; /* if in IOC_OPAL_SAVE will also use key to lock */ + __u8 __align[3]; }; struct opal_new_pw { -- 2.35.1