Commit 8ff2c64c authored by Ilya Dryomov's avatar Ilya Dryomov
Browse files

rbd: harden get_lock_owner_info() a bit



- 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: default avatarIlya Dryomov <idryomov@gmail.com>
Reviewed-by: default avatarDongsheng Yang <dongsheng.yang@easystack.cn>
parent f38cb9d9
Loading
Loading
Loading
Loading
+15 −6
Original line number Diff line number Diff line
@@ -3862,10 +3862,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);
@@ -3886,18 +3885,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);
+1 −0
Original line number Diff line number Diff line
@@ -1123,6 +1123,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)
{