rbd: harden get_lock_owner_info() a bit
authorIlya Dryomov <idryomov@gmail.com>
Sat, 8 Jul 2023 14:16:59 +0000 (16:16 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Aug 2023 08:24:17 +0000 (10:24 +0200)
commit 8ff2c64c9765446c3cef804fb99da04916603e27 upstream.

- we want the exclusive lock type, so test for it directly
- use sscanf() to actually parse the lock cookie and avoid admitting
  invalid handles
- bail if locker has a blank address

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Reviewed-by: Dongsheng Yang <dongsheng.yang@easystack.cn>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/block/rbd.c
net/ceph/messenger.c

index 523a903d6ae5f571734556944c29293bafab2904..2615ab99eb9aa01d34df890144d52396ef092628 100644 (file)
@@ -3863,10 +3863,9 @@ static struct ceph_locker *get_lock_owner_info(struct rbd_device *rbd_dev)
        u32 num_lockers;
        u8 lock_type;
        char *lock_tag;
+       u64 handle;
        int ret;
 
-       dout("%s rbd_dev %p\n", __func__, rbd_dev);
-
        ret = ceph_cls_lock_info(osdc, &rbd_dev->header_oid,
                                 &rbd_dev->header_oloc, RBD_LOCK_NAME,
                                 &lock_type, &lock_tag, &lockers, &num_lockers);
@@ -3887,18 +3886,28 @@ static struct ceph_locker *get_lock_owner_info(struct rbd_device *rbd_dev)
                goto err_busy;
        }
 
-       if (lock_type == CEPH_CLS_LOCK_SHARED) {
-               rbd_warn(rbd_dev, "shared lock type detected");
+       if (lock_type != CEPH_CLS_LOCK_EXCLUSIVE) {
+               rbd_warn(rbd_dev, "incompatible lock type detected");
                goto err_busy;
        }
 
        WARN_ON(num_lockers != 1);
-       if (strncmp(lockers[0].id.cookie, RBD_LOCK_COOKIE_PREFIX,
-                   strlen(RBD_LOCK_COOKIE_PREFIX))) {
+       ret = sscanf(lockers[0].id.cookie, RBD_LOCK_COOKIE_PREFIX " %llu",
+                    &handle);
+       if (ret != 1) {
                rbd_warn(rbd_dev, "locked by external mechanism, cookie %s",
                         lockers[0].id.cookie);
                goto err_busy;
        }
+       if (ceph_addr_is_blank(&lockers[0].info.addr)) {
+               rbd_warn(rbd_dev, "locker has a blank address");
+               goto err_busy;
+       }
+
+       dout("%s rbd_dev %p got locker %s%llu@%pISpc/%u handle %llu\n",
+            __func__, rbd_dev, ENTITY_NAME(lockers[0].id.name),
+            &lockers[0].info.addr.in_addr,
+            le32_to_cpu(lockers[0].info.addr.nonce), handle);
 
 out:
        kfree(lock_tag);
index dfa237fbd5a325ab96bce3bfe05ceb78b11eceac..09feb3f1fcaa3c313505c80ad88edeea3b251ef7 100644 (file)
@@ -1118,6 +1118,7 @@ bool ceph_addr_is_blank(const struct ceph_entity_addr *addr)
                return true;
        }
 }
+EXPORT_SYMBOL(ceph_addr_is_blank);
 
 int ceph_addr_port(const struct ceph_entity_addr *addr)
 {