119 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
Index: sys/netinet/sctp_input.c
 | 
						|
===================================================================
 | 
						|
--- sys/netinet/sctp_input.c	(revision 277788)
 | 
						|
+++ sys/netinet/sctp_input.c	(working copy)
 | 
						|
@@ -3649,6 +3649,9 @@ sctp_handle_stream_reset_response(struct sctp_tcb
 | 
						|
 					/* huh ? */
 | 
						|
 					return (0);
 | 
						|
 				}
 | 
						|
+				if (ntohs(respin->ph.param_length) < sizeof(struct sctp_stream_reset_response_tsn)) {
 | 
						|
+					return (0);
 | 
						|
+				}
 | 
						|
 				if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
 | 
						|
 					resp = (struct sctp_stream_reset_response_tsn *)respin;
 | 
						|
 					asoc->stream_reset_outstanding--;
 | 
						|
@@ -4037,7 +4040,7 @@ __attribute__((noinline))
 | 
						|
 	    sctp_handle_stream_reset(struct sctp_tcb *stcb, struct mbuf *m, int offset,
 | 
						|
         struct sctp_chunkhdr *ch_req)
 | 
						|
 {
 | 
						|
-	int chk_length, param_len, ptype;
 | 
						|
+	uint16_t remaining_length, param_len, ptype;
 | 
						|
 	struct sctp_paramhdr pstore;
 | 
						|
 	uint8_t cstore[SCTP_CHUNK_BUFFER_SIZE];
 | 
						|
 	uint32_t seq = 0;
 | 
						|
@@ -4050,7 +4053,7 @@ __attribute__((noinline))
 | 
						|
 	int num_param = 0;
 | 
						|
 
 | 
						|
 	/* now it may be a reset or a reset-response */
 | 
						|
-	chk_length = ntohs(ch_req->chunk_length);
 | 
						|
+	remaining_length = ntohs(ch_req->chunk_length) - sizeof(struct sctp_chunkhdr);
 | 
						|
 
 | 
						|
 	/* setup for adding the response */
 | 
						|
 	sctp_alloc_a_chunk(stcb, chk);
 | 
						|
@@ -4088,20 +4091,27 @@ strres_nochunk:
 | 
						|
 	ch->chunk_length = htons(chk->send_size);
 | 
						|
 	SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size);
 | 
						|
 	offset += sizeof(struct sctp_chunkhdr);
 | 
						|
-	while ((size_t)chk_length >= sizeof(struct sctp_stream_reset_tsn_request)) {
 | 
						|
+	while (remaining_length >= sizeof(struct sctp_paramhdr)) {
 | 
						|
 		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, sizeof(pstore), (uint8_t *) & pstore);
 | 
						|
-		if (ph == NULL)
 | 
						|
+		if (ph == NULL) {
 | 
						|
+			/* TSNH */
 | 
						|
 			break;
 | 
						|
+		}
 | 
						|
 		param_len = ntohs(ph->param_length);
 | 
						|
-		if (param_len < (int)sizeof(struct sctp_stream_reset_tsn_request)) {
 | 
						|
-			/* bad param */
 | 
						|
+		if ((param_len > remaining_length) ||
 | 
						|
+		    (param_len < (sizeof(struct sctp_paramhdr) + sizeof(uint32_t)))) {
 | 
						|
+			/* bad parameter length */
 | 
						|
 			break;
 | 
						|
 		}
 | 
						|
-		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, min(param_len, (int)sizeof(cstore)),
 | 
						|
+		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, min(param_len, sizeof(cstore)),
 | 
						|
 		    (uint8_t *) & cstore);
 | 
						|
+		if (ph == NULL) {
 | 
						|
+			/* TSNH */
 | 
						|
+			break;
 | 
						|
+		}
 | 
						|
 		ptype = ntohs(ph->param_type);
 | 
						|
 		num_param++;
 | 
						|
-		if (param_len > (int)sizeof(cstore)) {
 | 
						|
+		if (param_len > sizeof(cstore)) {
 | 
						|
 			trunc = 1;
 | 
						|
 		} else {
 | 
						|
 			trunc = 0;
 | 
						|
@@ -4113,6 +4123,9 @@ strres_nochunk:
 | 
						|
 		if (ptype == SCTP_STR_RESET_OUT_REQUEST) {
 | 
						|
 			struct sctp_stream_reset_out_request *req_out;
 | 
						|
 
 | 
						|
+			if (param_len < sizeof(struct sctp_stream_reset_out_request)) {
 | 
						|
+				break;
 | 
						|
+			}
 | 
						|
 			req_out = (struct sctp_stream_reset_out_request *)ph;
 | 
						|
 			num_req++;
 | 
						|
 			if (stcb->asoc.stream_reset_outstanding) {
 | 
						|
@@ -4126,6 +4139,9 @@ strres_nochunk:
 | 
						|
 		} else if (ptype == SCTP_STR_RESET_ADD_OUT_STREAMS) {
 | 
						|
 			struct sctp_stream_reset_add_strm *str_add;
 | 
						|
 
 | 
						|
+			if (param_len < sizeof(struct sctp_stream_reset_add_strm)) {
 | 
						|
+				break;
 | 
						|
+			}
 | 
						|
 			str_add = (struct sctp_stream_reset_add_strm *)ph;
 | 
						|
 			num_req++;
 | 
						|
 			sctp_handle_str_reset_add_strm(stcb, chk, str_add);
 | 
						|
@@ -4132,6 +4148,9 @@ strres_nochunk:
 | 
						|
 		} else if (ptype == SCTP_STR_RESET_ADD_IN_STREAMS) {
 | 
						|
 			struct sctp_stream_reset_add_strm *str_add;
 | 
						|
 
 | 
						|
+			if (param_len < sizeof(struct sctp_stream_reset_add_strm)) {
 | 
						|
+				break;
 | 
						|
+			}
 | 
						|
 			str_add = (struct sctp_stream_reset_add_strm *)ph;
 | 
						|
 			num_req++;
 | 
						|
 			sctp_handle_str_reset_add_out_strm(stcb, chk, str_add);
 | 
						|
@@ -4156,6 +4175,9 @@ strres_nochunk:
 | 
						|
 			struct sctp_stream_reset_response *resp;
 | 
						|
 			uint32_t result;
 | 
						|
 
 | 
						|
+			if (param_len < sizeof(struct sctp_stream_reset_response)) {
 | 
						|
+				break;
 | 
						|
+			}
 | 
						|
 			resp = (struct sctp_stream_reset_response *)ph;
 | 
						|
 			seq = ntohl(resp->response_seq);
 | 
						|
 			result = ntohl(resp->result);
 | 
						|
@@ -4167,7 +4189,11 @@ strres_nochunk:
 | 
						|
 			break;
 | 
						|
 		}
 | 
						|
 		offset += SCTP_SIZE32(param_len);
 | 
						|
-		chk_length -= SCTP_SIZE32(param_len);
 | 
						|
+		if (remaining_length >= SCTP_SIZE32(param_len)) {
 | 
						|
+			remaining_length -= SCTP_SIZE32(param_len);
 | 
						|
+		} else {
 | 
						|
+			remaining_length = 0;
 | 
						|
+		}
 | 
						|
 	}
 | 
						|
 	if (num_req == 0) {
 | 
						|
 		/* we have no response free the stuff */
 |