Date: Fri, 24 Jun 2011 20:22:19 +1200 From: Matthew Luckie <mjl@luckie.org.nz> To: freebsd-bugs@FreeBSD.org Subject: Re: kern/145733: [patch] ipfw flaws with ipv6 fragments Message-ID: <4E04493B.8030203@luckie.org.nz>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------070209090203080600040202 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit On world IPv6 day I was asked by bz@ to re-spin the patch supplied in the PR with the second and third IPv6 fragment issues listed in the PR fixed, but not the first (discarding IPv6 packets with a fragment header but not fragmented). Attached is the revised patch, against 8.2R --------------070209090203080600040202 Content-Type: text/plain; name="patch-ipfw2-ip6frag" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="patch-ipfw2-ip6frag" --- ip_fw_log.c.orig 2011-06-24 19:46:44.000000000 +1200 +++ ip_fw_log.c 2011-06-24 20:14:55.724751000 +1200 @@ -168,6 +168,7 @@ ipfw_log(struct ip_fw *f, u_int hlen, st char *action; int limit_reached = 0; char action2[40], proto[128], fragment[32]; + u_short mf = 0; if (V_fw_verbose == 0) { #ifndef WITHOUT_BPF @@ -337,6 +338,8 @@ ipfw_log(struct ip_fw *f, u_int hlen, st snprintf(dst, sizeof(dst), "[%s]", ip6_sprintf(ip6buf, &args->f_id.dst_ip6)); + mf = offset & IP6F_MORE_FRAG; + offset &= IP6F_OFF_MASK; ip6 = (struct ip6_hdr *)ip; tcp = (struct tcphdr *)(((char *)ip) + hlen); udp = (struct udphdr *)(((char *)ip) + hlen); @@ -406,13 +409,13 @@ ipfw_log(struct ip_fw *f, u_int hlen, st #ifdef INET6 if (IS_IP6_FLOW_ID(&(args->f_id))) { - if (offset & (IP6F_OFF_MASK | IP6F_MORE_FRAG)) + if (offset || mf) snprintf(SNPARGS(fragment, 0), " (frag %08x:%d@%d%s)", args->f_id.extra, ntohs(ip6->ip6_plen) - hlen, - ntohs(offset & IP6F_OFF_MASK) << 3, - (offset & IP6F_MORE_FRAG) ? "+" : ""); + ntohs(offset) << 3, + mf ? "+" : ""); } else #endif { --- ip_fw2.c.orig 2011-06-24 19:31:28.000000000 +1200 +++ ip_fw2.c 2011-06-24 20:14:55.724751000 +1200 @@ -838,16 +838,13 @@ ipfw_chk(struct ip_fw_args *args) /* * offset The offset of a fragment. offset != 0 means that - * we have a fragment at this offset of an IPv4 packet. - * offset == 0 means that (if this is an IPv4 packet) - * this is the first or only fragment. - * For IPv6 offset == 0 means there is no Fragment Header. - * If offset != 0 for IPv6 always use correct mask to - * get the correct offset because we add IP6F_MORE_FRAG - * to be able to dectect the first fragment which would - * otherwise have offset = 0. + * we have a fragment at this offset. + * offset == 0 means that this is the first or only fragment. + * + * mf The MF bit masked out of IPv6 packets. */ u_short offset = 0; + u_short mf = 0; /* * Local copies of addresses. They are only valid if we have @@ -940,7 +937,7 @@ do { \ proto = ip6->ip6_nxt; /* Search extension headers to find upper layer protocols */ - while (ulp == NULL) { + while (ulp == NULL && offset == 0) { switch (proto) { case IPPROTO_ICMPV6: PULLUP_TO(hlen, ulp, struct icmp6_hdr); @@ -1005,11 +1002,9 @@ do { \ proto = ((struct ip6_frag *)ulp)->ip6f_nxt; offset = ((struct ip6_frag *)ulp)->ip6f_offlg & IP6F_OFF_MASK; - /* Add IP6F_MORE_FRAG for offset of first - * fragment to be != 0. */ - offset |= ((struct ip6_frag *)ulp)->ip6f_offlg & + mf = ((struct ip6_frag *)ulp)->ip6f_offlg & IP6F_MORE_FRAG; - if (offset == 0) { + if (offset == 0 && mf == 0) { printf("IPFW2: IPV6 - Invalid Fragment " "Header\n"); if (V_fw_deny_unknown_exthdrs) @@ -1650,7 +1645,7 @@ do { \ case O_LOG: ipfw_log(f, hlen, args, m, - oif, offset, tablearg, ip); + oif, offset|mf, tablearg, ip); match = 1; break; --------------070209090203080600040202--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4E04493B.8030203>