sed-opal: allow using IOC_OPAL_SAVE for locking too
authorLuca Boccassi <bluca@debian.org>
Tue, 6 Dec 2022 09:29:13 +0000 (09:29 +0000)
committerJens Axboe <axboe@kernel.dk>
Thu, 8 Dec 2022 16:17:45 +0000 (09:17 -0700)
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>
block/sed-opal.c
include/uapi/linux/sed-opal.h

index 2c5327a0543a66889e3b5eb0c0ec0786e1845c19..1f926c0973f9f967d9c152597e2a7c0954059998 100644 (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);
 
index 2573772e2fb3e946dcc122da9a75f52b3b2b2fb9..1fed3c9294fc5ada17c4cd641ae62bf38845ab15 100644 (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 {