Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b7fc7f37 authored by Roland Dreier's avatar Roland Dreier Committed by Nicholas Bellinger
Browse files

target: Fix possible integer underflow in UNMAP emulation



It's possible for an initiator to send us an UNMAP command with a
descriptor that is less than 8 bytes; in that case it's really bad for
us to set an unsigned int to that value, subtract 8 from it, and then
use that as a limit for our loop (since the value will wrap around to
a huge positive value).

Fix this by making size be signed and only looping if size >= 16 (ie
if we have at least a full descriptor available).

Also remove offset as an obfuscated name for the constant 8.

Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 1a5fa457
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -325,24 +325,24 @@ static int iblock_execute_unmap(struct se_cmd *cmd)
	struct iblock_dev *ibd = dev->dev_ptr;
	unsigned char *buf, *ptr = NULL;
	sector_t lba;
	unsigned int size = cmd->data_length, range;
	int ret = 0, offset;
	unsigned short dl, bd_dl;

	/* First UNMAP block descriptor starts at 8 byte offset */
	offset = 8;
	size -= 8;
	int size = cmd->data_length;
	u32 range;
	int ret = 0;
	int dl, bd_dl;

	buf = transport_kmap_data_sg(cmd);

	dl = get_unaligned_be16(&buf[0]);
	bd_dl = get_unaligned_be16(&buf[2]);

	ptr = &buf[offset];
	pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
	size = min(size - 8, bd_dl);

	/* First UNMAP block descriptor starts at 8 byte offset */
	ptr = &buf[8];
	pr_debug("UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u"
		" ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr);

	while (size) {
	while (size >= 16) {
		lba = get_unaligned_be64(&ptr[0]);
		range = get_unaligned_be32(&ptr[8]);
		pr_debug("UNMAP: Using lba: %llu and range: %u\n",