]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: check OPAL lock only when necessary
authorOldřich Jedlička <oldium.pro@gmail.com>
Sat, 30 Mar 2024 13:45:10 +0000 (14:45 +0100)
committerOldřich Jedlička <oldium.pro@gmail.com>
Sat, 30 Mar 2024 21:02:33 +0000 (22:02 +0100)
When the HW OPAL encryption is used, the LUKS2 subsystem field is "HW-OPAL"
(see also [1]). Finish the probe only in case LUKS2 is set to use HW OPAL
and the disk is locked.

[1] https://gitlab.com/cryptsetup/cryptsetup/-/issues/874#note_1838835551

Signed-off-by: Oldřich Jedlička <oldium.pro@gmail.com>
libblkid/src/blkidP.h
libblkid/src/probe.c
libblkid/src/superblocks/luks.c

index ea7d81b0c590cad694a2ff5f7b0c5cd040d8baf4..f71e13cb335e15ba6df2be83c451ceb4df143602 100644 (file)
@@ -241,6 +241,7 @@ struct blkid_struct_probe
 #define BLKID_FL_NOSCAN_DEV    (1 << 4)        /* do not scan this device */
 #define BLKID_FL_MODIF_BUFF    (1 << 5)        /* cached buffers has been modified */
 #define BLKID_FL_OPAL_LOCKED   (1 << 6)        /* OPAL device is locked (I/O errors) */
+#define BLKID_FL_OPAL_CHECKED  (1 << 7)        /* OPAL lock checked */
 
 /* private per-probing flags */
 #define BLKID_PROBE_FL_IGNORE_PT (1 << 1)      /* ignore partition table */
index 76905e1970fbbd4270190c2515611a6714fdc5fe..756c7354fe179fb0a987043742585bb7ae1fa63e 100644 (file)
@@ -603,20 +603,6 @@ static struct blkid_bufinfo *read_buffer(blkid_probe pr, uint64_t real_off, uint
                 * audio+data disks */
                if (ret >= 0 || blkid_probe_is_cdrom(pr) || blkdid_probe_is_opal_locked(pr))
                        errno = 0;
-#ifdef HAVE_OPAL_GET_STATUS
-               else {
-                       struct opal_status st = { };
-
-                       /* If the device is locked with OPAL, we'll fail to read with I/O
-                        * errors when probing deep into the block device. Do not return
-                        * an error, so that we can move on to different types of checks.*/
-                       ret = ioctl(pr->fd, IOC_OPAL_GET_STATUS, &st);
-                       if (ret == 0 && (st.flags & OPAL_FL_LOCKED)) {
-                               pr->flags |= BLKID_FL_OPAL_LOCKED;
-                               errno = 0;
-                       }
-               }
-#endif
 
                return NULL;
        }
@@ -911,6 +897,25 @@ int blkid_probe_is_cdrom(blkid_probe pr)
 
 int blkdid_probe_is_opal_locked(blkid_probe pr)
 {
+       if (!(pr->flags & BLKID_FL_OPAL_CHECKED)) {
+               pr->flags |= BLKID_FL_OPAL_CHECKED;
+
+#ifdef HAVE_OPAL_GET_STATUS
+               ssize_t ret;
+               struct opal_status st = { };
+               int errsv = errno;
+
+               /* If the device is locked with OPAL, we'll fail to read with I/O
+                * errors when probing deep into the block device. */
+               ret = ioctl(pr->fd, IOC_OPAL_GET_STATUS, &st);
+               if (ret == 0 && (st.flags & OPAL_FL_LOCKED)) {
+                       pr->flags |= BLKID_FL_OPAL_LOCKED;
+               }
+
+               errno = errsv;
+#endif
+       }
+
        return (pr->flags & BLKID_FL_OPAL_LOCKED);
 }
 
index 1c487f8ff3d4125b55435ad5eff4edf6166cf727..5ab7e73c90e66a5c8f32a6e612fa5fe9f89c851c 100644 (file)
@@ -34,6 +34,8 @@
 #define LUKS_MAGIC     "LUKS\xba\xbe"
 #define LUKS_MAGIC_2   "SKUL\xba\xbe"
 
+#define LUKS2_HW_OPAL_SUBSYSTEM        "HW-OPAL"
+
 /* Offsets for secondary header (for scan if primary header is corrupted). */
 #define LUKS2_HDR2_OFFSETS { 0x04000, 0x008000, 0x010000, 0x020000, \
                              0x40000, 0x080000, 0x100000, 0x200000, 0x400000 }
@@ -139,12 +141,31 @@ static int probe_luks(blkid_probe pr, const struct blkid_idmag *mag __attribute_
        return BLKID_PROBE_NONE;
 }
 
-static int probe_luks_opal(blkid_probe pr, const struct blkid_idmag *mag)
+static int probe_luks_opal(blkid_probe pr, const struct blkid_idmag *mag __attribute__((__unused__)))
 {
+       struct luks2_phdr *header;
+       int version;
+
+       header = (struct luks2_phdr *) blkid_probe_get_buffer(pr, 0, sizeof(struct luks2_phdr));
+       if (!header)
+               return errno ? -errno : BLKID_PROBE_NONE;
+
+       if (!luks_valid(header, LUKS_MAGIC, 0))
+               return BLKID_PROBE_NONE;
+
+       version = be16_to_cpu(header->version);
+
+       if (version != 2)
+               return BLKID_PROBE_NONE;
+
+       if (memcmp(header->subsystem, LUKS2_HW_OPAL_SUBSYSTEM, sizeof(LUKS2_HW_OPAL_SUBSYSTEM)) != 0)
+               return BLKID_PROBE_NONE;
+
        if (!blkdid_probe_is_opal_locked(pr))
                return BLKID_PROBE_NONE;
 
-       return probe_luks(pr, mag);
+       /* Locked drive with LUKS2 HW OPAL encryption, finish probe now */
+       return luks_attributes(pr, header, 0);
 }
 
 const struct blkid_idinfo luks_idinfo =