summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2016-11-17 13:17:33 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2016-11-17 13:17:33 +0000
commit9eb3c57197fbc8fe5b811335782ab02226f498fb (patch)
tree178d549f5c3d98645de91f0fb98eb94868e2f3d7 /sys
parent349160d834fb53059253a80a923d945eb4b0afb3 (diff)
The pf fragment reassembly code accepted IPv6 hop-by-hop headers
after fragment headers. Add an extra check that the hop-by-hop header is always the first extension header after the IPv6 header. Found by Antonios Atlasis; OK sthen@ mpi@
Diffstat (limited to 'sys')
-rw-r--r--sys/net/pf.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 7406c95c873..b8e2a6fb7bf 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.998 2016/11/14 13:25:00 bluhm Exp $ */
+/* $OpenBSD: pf.c,v 1.999 2016/11/17 13:17:32 bluhm Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -6207,13 +6207,14 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
struct ip6_ext ext;
struct ip6_rthdr rthdr;
u_int32_t end;
- int fraghdr_cnt = 0, rthdr_cnt = 0;
+ int hdr_cnt = 0, fraghdr_cnt = 0, rthdr_cnt = 0;
pd->off += sizeof(struct ip6_hdr);
end = pd->off + ntohs(h->ip6_plen);
pd->fragoff = pd->extoff = pd->jumbolen = 0;
pd->proto = h->ip6_nxt;
for (;;) {
+ hdr_cnt++;
switch (pd->proto) {
case IPPROTO_FRAGMENT:
if (fraghdr_cnt++) {
@@ -6266,8 +6267,15 @@ pf_walk_header6(struct pf_pdesc *pd, struct ip6_hdr *h, u_short *reason)
return (PF_DROP);
}
/* FALLTHROUGH */
- case IPPROTO_AH:
case IPPROTO_HOPOPTS:
+ /* RFC2460 4.1: Hop-by-Hop only after IPv6 header */
+ if (pd->proto == IPPROTO_HOPOPTS && hdr_cnt > 1) {
+ DPFPRINTF(LOG_NOTICE, "IPv6 hopopts not first");
+ REASON_SET(reason, PFRES_IPOPTIONS);
+ return (PF_DROP);
+ }
+ /* FALLTHROUGH */
+ case IPPROTO_AH:
case IPPROTO_DSTOPTS:
/* fragments may be short */
if (pd->fragoff != 0 && end < pd->off + sizeof(ext)) {