diff options
author | Cedric Berger <cedric@cvs.openbsd.org> | 2003-03-14 12:36:41 +0000 |
---|---|---|
committer | Cedric Berger <cedric@cvs.openbsd.org> | 2003-03-14 12:36:41 +0000 |
commit | b1710f18c81eeb4883829ff431968bdcb9f9f74a (patch) | |
tree | 12f2a25cb439626606760487092bdbf25a8c8d98 /sys/net | |
parent | cc49397417497f37be1fb61c9372849290ecfc17 (diff) |
Correctly flag out radix_node entries with RNF_ROOT flag set: this is not
a match. Before that patch, an IP packet with source or dest address of
0.0.0.0 could corrupt the kernel. People filtering DHCP packets on their
firewall using tables should upgrade their kernel now.
Thanks to Chris Cappuccio for the good bug report.
Ok dhartmei@ henning@
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/pf_table.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c index 53eb865643c..36259af243f 100644 --- a/sys/net/pf_table.c +++ b/sys/net/pf_table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_table.c,v 1.29 2003/03/13 17:56:16 cedric Exp $ */ +/* $OpenBSD: pf_table.c,v 1.30 2003/03/14 12:36:40 cedric Exp $ */ /* * Copyright (c) 2002 Cedric Berger @@ -73,6 +73,8 @@ #define AF_BITS(af) (((af)==AF_INET)?32:128) #define ADDR_NETWORK(ad) ((ad)->pfra_net < AF_BITS((ad)->pfra_af)) #define KENTRY_NETWORK(ke) ((ke)->pfrke_net < AF_BITS((ke)->pfrke_af)) +#define KENTRY_RNF_ROOT(ke) \ + ((((struct radix_node *)(ke))->rn_flags & RNF_ROOT) != 0) #define NO_ADDRESSES (-1) #define ENQUEUE_UNMARKED_ONLY (1) @@ -715,8 +717,12 @@ pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact) s = splsoftnet(); /* rn_lookup makes use of globals */ ke = (struct pfr_kentry *)rn_lookup(&sa, &mask, head); splx(s); + if (ke && KENTRY_RNF_ROOT(ke)) + ke = NULL; } else { ke = (struct pfr_kentry *)rn_match(&sa, head); + if (ke && KENTRY_RNF_ROOT(ke)) + ke = NULL; if (exact && ke && KENTRY_NETWORK(ke)) ke = NULL; } @@ -1634,10 +1640,14 @@ pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af) case AF_INET: pfr_sin.sin_addr.s_addr = a->addr32[0]; ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4); + if (ke && KENTRY_RNF_ROOT(ke)) + ke = NULL; break; case AF_INET6: bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr)); ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6); + if (ke && KENTRY_RNF_ROOT(ke)) + ke = NULL; break; } match = (ke && !ke->pfrke_not); @@ -1658,10 +1668,14 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af, case AF_INET: pfr_sin.sin_addr.s_addr = a->addr32[0]; ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4); + if (ke && KENTRY_RNF_ROOT(ke)) + ke = NULL; break; case AF_INET6: bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr)); ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6); + if (ke && KENTRY_RNF_ROOT(ke)) + ke = NULL; break; } if (ke == NULL || ke->pfrke_not != notrule) { |