Page MenuHomeFreeBSD

D50657.id.diff
No OneTemporary

D50657.id.diff

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -372,6 +372,7 @@
int, u_int16_t);
static int pf_check_proto_cksum(struct mbuf *, int, int,
u_int8_t, sa_family_t);
+static int pf_walk_header(struct pf_pdesc *, struct ip *, u_short *);
static int pf_walk_option6(struct pf_pdesc *, struct ip6_hdr *,
int, int, u_short *);
static int pf_walk_header6(struct pf_pdesc *, struct ip6_hdr *,
@@ -7911,9 +7912,10 @@
}
/* offset of protocol header that follows h2 */
- pd2.off = ipoff2 + (h2.ip_hl << 2);
+ pd2.off = ipoff2;
+ if (pf_walk_header(&pd2, &h2, reason) != PF_PASS)
+ return (PF_DROP);
- pd2.proto = h2.ip_p;
pd2.tot_len = ntohs(h2.ip_len);
pd2.src = (struct pf_addr *)&h2.ip_src;
pd2.dst = (struct pf_addr *)&h2.ip_dst;
@@ -9689,6 +9691,44 @@
return (0);
}
+static int
+pf_walk_header(struct pf_pdesc *pd, struct ip *h, u_short *reason)
+{
+ struct ip6_ext ext;
+ u_int32_t hlen, end;
+
+ hlen = h->ip_hl << 2;
+ if (hlen < sizeof(struct ip) || hlen > ntohs(h->ip_len)) {
+ REASON_SET(reason, PFRES_SHORT);
+ return (PF_DROP);
+ }
+ end = pd->off + ntohs(h->ip_len);
+ pd->off += hlen;
+ pd->proto = h->ip_p;
+ /* stop walking over non initial fragments */
+ if ((h->ip_off & htons(IP_OFFMASK)) != 0)
+ return (PF_PASS);
+ for (;;) {
+ switch (pd->proto) {
+ case IPPROTO_AH:
+ /* fragments may be short */
+ if ((h->ip_off & htons(IP_MF | IP_OFFMASK)) != 0 &&
+ end < pd->off + sizeof(ext))
+ return (PF_PASS);
+ if (!pf_pull_hdr(pd->m, pd->off, &ext, sizeof(ext),
+ NULL, reason, AF_INET)) {
+ DPFPRINTF(PF_DEBUG_MISC, ("IP short exthdr"));
+ return (PF_DROP);
+ }
+ pd->off += (ext.ip6e_len + 2) * 4;
+ pd->proto = ext.ip6e_nxt;
+ break;
+ default:
+ return (PF_PASS);
+ }
+ }
+}
+
#ifdef INET6
static int
pf_walk_option6(struct pf_pdesc *pd, struct ip6_hdr *h, int off, int end,
@@ -9936,18 +9976,22 @@
*m0 = pd->m;
h = mtod(pd->m, struct ip *);
- pd->off = h->ip_hl << 2;
- if (pd->off < (int)sizeof(*h)) {
+ if (pd->m->m_pkthdr.len < ntohs(h->ip_len)) {
*action = PF_DROP;
REASON_SET(reason, PFRES_SHORT);
return (-1);
}
+
+ if (pf_walk_header(pd, h, reason) != PF_PASS) {
+ *action = PF_DROP;
+ return (-1);
+ }
+
pd->src = (struct pf_addr *)&h->ip_src;
pd->dst = (struct pf_addr *)&h->ip_dst;
PF_ACPY(&pd->osrc, pd->src, af);
PF_ACPY(&pd->odst, pd->dst, af);
pd->ip_sum = &h->ip_sum;
- pd->virtual_proto = pd->proto = h->ip_p;
pd->tos = h->ip_tos & ~IPTOS_ECN_MASK;
pd->ttl = h->ip_ttl;
pd->tot_len = ntohs(h->ip_len);
@@ -9957,8 +10001,8 @@
if (h->ip_hl > 5) /* has options */
pd->badopts++;
- if (h->ip_off & htons(IP_MF | IP_OFFMASK))
- pd->virtual_proto = PF_VPROTO_FRAGMENT;
+ pd->virtual_proto = (h->ip_off & htons(IP_MF | IP_OFFMASK)) ?
+ PF_VPROTO_FRAGMENT : pd->proto;
break;
}
@@ -9978,7 +10022,7 @@
}
h = mtod(pd->m, struct ip6_hdr *);
- pd->off = 0;
+
if (pf_walk_header6(pd, h, reason) != PF_PASS) {
*action = PF_DROP;
return (-1);
@@ -9993,11 +10037,10 @@
pd->tos = IPV6_DSCP(h);
pd->ttl = h->ip6_hlim;
pd->tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr);
- pd->virtual_proto = pd->proto = h->ip6_nxt;
pd->act.rtableid = -1;
- if (pd->fragoff != 0)
- pd->virtual_proto = PF_VPROTO_FRAGMENT;
+ pd->virtual_proto = (pd->fragoff != 0) ?
+ PF_VPROTO_FRAGMENT : pd->proto;
/*
* we do not support jumbogram. if we keep going, zero ip6_plen

File Metadata

Mime Type
text/plain
Expires
Thu, Apr 16, 2:33 AM (6 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31572087
Default Alt Text
D50657.id.diff (3 KB)

Event Timeline