summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorCedric Berger <cedric@cvs.openbsd.org>2003-03-14 12:36:41 +0000
committerCedric Berger <cedric@cvs.openbsd.org>2003-03-14 12:36:41 +0000
commitb1710f18c81eeb4883829ff431968bdcb9f9f74a (patch)
tree12f2a25cb439626606760487092bdbf25a8c8d98 /sys/net
parentcc49397417497f37be1fb61c9372849290ecfc17 (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.c16
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) {