Initialise init_addr in pf_map_addr() in the PF_POOL_ROUNDROBIN,

prevents a possible endless loop in pf_get_sport() with 'static-port'

ICMP state entries use the ICMP ID as port for the unique state key. When
checking for a usable key, construct the key in the same way. Otherwise,
a colliding key might be missed or a state insertion might be refused even
though it could be inserted. The second case triggers the endless loop,
possibly allowing a NATed LAN client to lock up the kernel.

PR:			kern/74930
Reported and tested by:	Hugo Silva, Srebrenko Sehic
MFC after:		3 days
This commit is contained in:
dhartmei 2004-12-19 19:43:04 +00:00
parent ae7f7772e5
commit b61c49cccc

View File

@ -2087,6 +2087,8 @@ pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
get_addr:
PF_ACPY(naddr, &rpool->counter, af);
if (init_addr != NULL && PF_AZERO(init_addr, af))
PF_ACPY(init_addr, naddr, af);
PF_AINC(&rpool->counter, af);
break;
}
@ -2129,7 +2131,7 @@ pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
* similar 2 portloop in in_pcbbind
*/
if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP)) {
key.gwy.port = 0;
key.gwy.port = dport;
if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
return (0);
} else if (low == 0 && high == 0) {
@ -3405,7 +3407,7 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
if (direction == PF_OUT) {
/* check outgoing packet for BINAT/NAT */
if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
saddr, icmpid, daddr, icmpid, &pd->naddr, NULL)) != NULL) {
PF_ACPY(&pd->baddr, saddr, af);
switch (af) {
#ifdef INET
@ -3429,7 +3431,7 @@ pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
} else {
/* check incoming packet for BINAT/RDR */
if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
saddr, icmpid, daddr, icmpid, &pd->naddr, NULL)) != NULL) {
PF_ACPY(&pd->baddr, daddr, af);
switch (af) {
#ifdef INET