File iscsitarget-isns-bounds-checking of Package iscsitarget

From a1fba2354c505aaba8ad01953f2a5669d66da5c9 Mon Sep 17 00:00:00 2001
From: rswwalker <rswwalker@48a34bb2-7106-0410-bc49-8aa7273d22a1>
Date: Thu, 1 Jul 2010 21:17:35 +0000
Subject: [PATCH] This patch fixes the iSNS code's bounds checking on SCN packets.

Fixes a couple buffer overflow scenarios per CVE-2010-2221.

Also fixes a memory leak with initiator ACLs.

Signed-off-by: Ross Walker

git-svn-id: https://iscsitarget.svn.sourceforge.net/svnroot/iscsitarget/trunk@367 48a34bb2-7106-0410-bc49-8aa7273d22a1

diff --git a/usr/isns.c b/usr/isns.c
index b2d038e..3c0525d 100644
--- a/usr/isns.c
+++ b/usr/isns.c
@@ -442,6 +442,7 @@ static void free_all_acl(struct target *target)
 	while (!list_empty(&target->isns_head)) {
 		ini = list_entry(target->isns_head.q_forw, typeof(*ini), ilist);
 		remque(&ini->ilist);
+		free(ini);
 	}
 }
 
@@ -595,18 +596,36 @@ static char *print_scn_pdu(struct isns_hdr *hdr)
 	while (length) {
 		uint32_t vlen = ntohl(tlv->length);
 
+		if (vlen + sizeof(*tlv) > length)
+			vlen = length - sizeof(*tlv);
+
 		switch (ntohl(tlv->tag)) {
 		case ISNS_ATTR_ISCSI_NAME:
-			log_error("scn name: %u, %s", vlen, (char *) tlv->value);
-			if (!name)
-				name = (char *) tlv->value;
+			if (vlen) {
+				size_t slen = vlen - 1;
+
+				if (slen > ISCSI_NAME_LEN)
+					slen = ISCSI_NAME_LEN;
+
+				*((char *) tlv->value + slen) = 0;
+
+				log_error("scn name: %u, %s", vlen,
+					  (char *) tlv->value);
+
+				if (!name)
+					name = (char *) tlv->value;
+			}
 			break;
 		case ISNS_ATTR_TIMESTAMP:
-/* 			log_error("%u : %u : %" PRIx64, ntohl(tlv->tag), vlen, */
-/* 				  *((uint64_t *) tlv->value)); */
+/*			if (vlen == 8)
+				log_error("%u : %u : %" PRIx64, ntohl(tlv->tag),
+					  vlen, *((uint64_t *) tlv->value));
+*/
 			break;
 		case ISNS_ATTR_ISCSI_SCN_BITMAP:
-			log_error("scn bitmap : %x", *((uint32_t *) tlv->value));
+			if (vlen == 4)
+				log_error("scn bitmap : %x",
+					  *((uint32_t *) tlv->value));
 			break;
 		}
 
@@ -666,24 +685,45 @@ found:
 
 	/* skip status */
 	tlv = (struct isns_tlv *) ((char *) hdr->pdu + 4);
+
+	if (length < 4)
+		goto free_qry_mgmt;
+
 	length -= 4;
 
 	while (length) {
 		uint32_t vlen = ntohl(tlv->length);
 
+		if (vlen + sizeof(*tlv) > length)
+			vlen = length - sizeof(*tlv);
+
 		switch (ntohl(tlv->tag)) {
 		case ISNS_ATTR_ISCSI_NAME:
-			name = (char *) tlv->value;
+			if (vlen) {
+				size_t slen = vlen - 1;
+
+				if (slen > ISCSI_NAME_LEN)
+					slen = ISCSI_NAME_LEN;
+
+				*((char *) tlv->value + slen) = 0;
+
+				name = (char *) tlv->value;
+			} else
+				name = NULL;
 			break;
 		case ISNS_ATTR_ISCSI_NODE_TYPE:
-			if (ntohl(*(tlv->value)) == ISNS_NODE_INITIATOR && name) {
+			if (vlen == 4 && name &&
+			    ntohl(*(tlv->value)) == ISNS_NODE_INITIATOR) {
 				log_error("%s %d: %s", __FUNCTION__, __LINE__,
 					  (char *) name);
+
 				ini = malloc(sizeof(*ini));
 				if (!ini)
 					goto free_qry_mgmt;
+
 				snprintf(ini->name, sizeof(ini->name), "%s",
 					 name);
+
 				insque(&ini->ilist, &target->isns_head);
 			} else
 				name = NULL;
openSUSE Build Service is sponsored by