mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-10-30 23:27:35 +00:00 
			
		
		
		
	pimd: harden MLD code loop boundaries
Coverity complains about these being tainted/untrusted loop boundaries. The way the code works, it's counting up groups/sources, but keeps checking against remaining data length in the packet - which is perfectly fine IMHO. Except Coverity doesn't understand it :( Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
		
							parent
							
								
									4dbef8567b
								
							
						
					
					
						commit
						ac4304d0fa
					
				| @ -594,7 +594,7 @@ static void gm_sg_expiry_cancel(struct gm_sg *sg) | |||||||
|  * everything else is thrown into pkt for creation of state in pass 2 |  * everything else is thrown into pkt for creation of state in pass 2 | ||||||
|  */ |  */ | ||||||
| static void gm_handle_v2_pass1(struct gm_packet_state *pkt, | static void gm_handle_v2_pass1(struct gm_packet_state *pkt, | ||||||
| 			       struct mld_v2_rec_hdr *rechdr) | 			       struct mld_v2_rec_hdr *rechdr, size_t n_src) | ||||||
| { | { | ||||||
| 	/* NB: pkt->subscriber can be NULL here if the subscriber was not
 | 	/* NB: pkt->subscriber can be NULL here if the subscriber was not
 | ||||||
| 	 * previously seen! | 	 * previously seen! | ||||||
| @ -603,7 +603,6 @@ static void gm_handle_v2_pass1(struct gm_packet_state *pkt, | |||||||
| 	struct gm_sg *grp; | 	struct gm_sg *grp; | ||||||
| 	struct gm_packet_sg *old_grp = NULL; | 	struct gm_packet_sg *old_grp = NULL; | ||||||
| 	struct gm_packet_sg *item; | 	struct gm_packet_sg *item; | ||||||
| 	size_t n_src = ntohs(rechdr->n_src); |  | ||||||
| 	size_t j; | 	size_t j; | ||||||
| 	bool is_excl = false; | 	bool is_excl = false; | ||||||
| 
 | 
 | ||||||
| @ -816,13 +815,24 @@ static void gm_handle_v2_report(struct gm_if *gm_ifp, | |||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* errors after this may at least partially process the packet */ |  | ||||||
| 	gm_ifp->stats.rx_new_report++; |  | ||||||
| 
 |  | ||||||
| 	hdr = (struct mld_v2_report_hdr *)data; | 	hdr = (struct mld_v2_report_hdr *)data; | ||||||
| 	data += sizeof(*hdr); | 	data += sizeof(*hdr); | ||||||
| 	len -= sizeof(*hdr); | 	len -= sizeof(*hdr); | ||||||
| 
 | 
 | ||||||
|  | 	n_records = ntohs(hdr->n_records); | ||||||
|  | 	if (n_records > len / sizeof(struct mld_v2_rec_hdr)) { | ||||||
|  | 		/* note this is only an upper bound, records with source lists
 | ||||||
|  | 		 * are larger.  This is mostly here to make coverity happy. | ||||||
|  | 		 */ | ||||||
|  | 		zlog_warn(log_pkt_src( | ||||||
|  | 			"malformed MLDv2 report (infeasible record count)")); | ||||||
|  | 		gm_ifp->stats.rx_drop_malformed++; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* errors after this may at least partially process the packet */ | ||||||
|  | 	gm_ifp->stats.rx_new_report++; | ||||||
|  | 
 | ||||||
| 	/* can't have more *,G and S,G items than there is space for ipv6
 | 	/* can't have more *,G and S,G items than there is space for ipv6
 | ||||||
| 	 * addresses, so just use this to allocate temporary buffer | 	 * addresses, so just use this to allocate temporary buffer | ||||||
| 	 */ | 	 */ | ||||||
| @ -833,8 +843,6 @@ static void gm_handle_v2_report(struct gm_if *gm_ifp, | |||||||
| 	pkt->iface = gm_ifp; | 	pkt->iface = gm_ifp; | ||||||
| 	pkt->subscriber = gm_subscriber_findref(gm_ifp, pkt_src->sin6_addr); | 	pkt->subscriber = gm_subscriber_findref(gm_ifp, pkt_src->sin6_addr); | ||||||
| 
 | 
 | ||||||
| 	n_records = ntohs(hdr->n_records); |  | ||||||
| 
 |  | ||||||
| 	/* validate & remove state in v2_pass1() */ | 	/* validate & remove state in v2_pass1() */ | ||||||
| 	for (i = 0; i < n_records; i++) { | 	for (i = 0; i < n_records; i++) { | ||||||
| 		struct mld_v2_rec_hdr *rechdr; | 		struct mld_v2_rec_hdr *rechdr; | ||||||
| @ -872,7 +880,7 @@ static void gm_handle_v2_report(struct gm_if *gm_ifp, | |||||||
| 		data += record_size; | 		data += record_size; | ||||||
| 		len -= record_size; | 		len -= record_size; | ||||||
| 
 | 
 | ||||||
| 		gm_handle_v2_pass1(pkt, rechdr); | 		gm_handle_v2_pass1(pkt, rechdr, n_src); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!pkt->n_active) { | 	if (!pkt->n_active) { | ||||||
| @ -1496,6 +1504,15 @@ static void gm_handle_query(struct gm_if *gm_ifp, | |||||||
| 		gm_handle_q_group(gm_ifp, &timers, hdr->grp); | 		gm_handle_q_group(gm_ifp, &timers, hdr->grp); | ||||||
| 		gm_ifp->stats.rx_query_new_group++; | 		gm_ifp->stats.rx_query_new_group++; | ||||||
| 	} else { | 	} else { | ||||||
|  | 		/* this is checked above:
 | ||||||
|  | 		 * if (len >= sizeof(struct mld_v2_query_hdr)) { | ||||||
|  | 		 *   size_t src_space = ntohs(hdr->n_src) * sizeof(pim_addr); | ||||||
|  | 		 *   if (len < sizeof(struct mld_v2_query_hdr) + src_space) { | ||||||
|  | 		 */ | ||||||
|  | 		assume(ntohs(hdr->n_src) <= | ||||||
|  | 		       (len - sizeof(struct mld_v2_query_hdr)) / | ||||||
|  | 			       sizeof(pim_addr)); | ||||||
|  | 
 | ||||||
| 		gm_handle_q_groupsrc(gm_ifp, &timers, hdr->grp, hdr->srcs, | 		gm_handle_q_groupsrc(gm_ifp, &timers, hdr->grp, hdr->srcs, | ||||||
| 				     ntohs(hdr->n_src)); | 				     ntohs(hdr->n_src)); | ||||||
| 		gm_ifp->stats.rx_query_new_groupsrc++; | 		gm_ifp->stats.rx_query_new_groupsrc++; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 David Lamparter
						David Lamparter