DragonFlyBSD Kernel Audit
DF-0570 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/net/ipfw3_nat/ip_fw3_nat.c b/sys/net/ipfw3_nat/ip_fw3_nat.c
--- a/sys/net/ipfw3_nat/ip_fw3_nat.c
+++ b/sys/net/ipfw3_nat/ip_fw3_nat.c
@@ -179,6 +179,7 @@
 	struct ip *ip = mtod(m, struct ip *);
 	struct in_addr *old_addr = NULL, new_addr;
 	uint16_t *old_port = NULL, new_port;
+	uint16_t in_port = 0;
 	uint16_t *csum = NULL, dlen = 0;
 	uint8_t udp = 0;
 	boolean_t pseudo = FALSE, need_return_state = FALSE;
@@ -201,18 +202,29 @@
 		switch (ip->ip_p) {
 		case IPPROTO_TCP:
 			old_port = &L3HDR(struct tcphdr, ip)->th_dport;
-			s2 = alias->tcp_in[*old_port - ALIAS_BEGIN];
+			in_port = ntohs(*old_port);
+			if (in_port < ALIAS_BEGIN ||
+			    in_port >= ALIAS_BEGIN + ALIAS_RANGE)
+				goto oops;
+			s2 = alias->tcp_in[in_port - ALIAS_BEGIN];
 			csum = &L3HDR(struct tcphdr, ip)->th_sum;
 			break;
 		case IPPROTO_UDP:
 			old_port = &L3HDR(struct udphdr, ip)->uh_dport;
-			s2 = alias->udp_in[*old_port - ALIAS_BEGIN];
+			in_port = ntohs(*old_port);
+			if (in_port < ALIAS_BEGIN ||
+			    in_port >= ALIAS_BEGIN + ALIAS_RANGE)
+				goto oops;
+			s2 = alias->udp_in[in_port - ALIAS_BEGIN];
 			csum = &L3HDR(struct udphdr, ip)->uh_sum;
 			udp = 1;
 			break;
 		case IPPROTO_ICMP:
 			old_port = &L3HDR(struct icmp, ip)->icmp_id;
-			s2 = alias->icmp_in[*old_port];
+			in_port = ntohs(*old_port);
+			if (in_port >= ALIAS_RANGE)
+				goto oops;
+			s2 = alias->icmp_in[in_port];
 			csum = &L3HDR(struct icmp, ip)->icmp_cksum;
 			break;
 		default: