From owner-freebsd-bugs@FreeBSD.ORG Fri Jun 24 08:50:00 2011 Return-Path: Delivered-To: freebsd-bugs@freebsd.org Received: from mx1.freebsd.org (unknown [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 24A7C106564A for ; Fri, 24 Jun 2011 08:50:00 +0000 (UTC) (envelope-from mjl@luckie.org.nz) Received: from mailfilter3.ihug.co.nz (mailfilter3.ihug.co.nz [203.109.136.3]) by mx1.freebsd.org (Postfix) with ESMTP id C00128FC19 for ; Fri, 24 Jun 2011 08:49:59 +0000 (UTC) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Av0EAEtIBE52XDZi/2dsb2JhbABSpzN4rBGfHoYtBJF7jAWEIg X-IronPort-AV: E=Sophos;i="4.65,418,1304251200"; d="scan'208";a="161471529" Received: from 118-92-54-98.dsl.dyn.ihug.co.nz (HELO spandex.luckie.org.nz) ([118.92.54.98]) by cust.filter3.content.vf.net.nz with ESMTP/TLS/DHE-RSA-AES256-SHA; 24 Jun 2011 20:20:29 +1200 Received: from mylar.luckie.org.nz ([192.168.1.24]) by spandex.luckie.org.nz with esmtpsa (TLSv1:CAMELLIA256-SHA:256) (Exim 4.76 (FreeBSD)) (envelope-from ) id 1Qa1cr-000Phb-7M for freebsd-bugs@FreeBSD.org; Fri, 24 Jun 2011 20:20:29 +1200 Message-ID: <4E04493B.8030203@luckie.org.nz> Date: Fri, 24 Jun 2011 20:22:19 +1200 From: Matthew Luckie User-Agent: Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.9.2.18) Gecko/20110623 Thunderbird/3.1.11 MIME-Version: 1.0 To: freebsd-bugs@FreeBSD.org Content-Type: multipart/mixed; boundary="------------070209090203080600040202" Cc: Subject: Re: kern/145733: [patch] ipfw flaws with ipv6 fragments X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Jun 2011 08:50:00 -0000 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--