Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Jul 2012 14:23:58 GMT
From:      Daniel Hartmeier <daniel@benzedrine.cx>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   misc/169630: pf fragment reassembly of padded (undersized) fragments
Message-ID:  <201207031423.q63ENwQI028349@red.freebsd.org>
Resent-Message-ID: <201207031430.q63EU6DC056784@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         169630
>Category:       misc
>Synopsis:       pf fragment reassembly of padded (undersized) fragments
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jul 03 14:30:06 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator:     Daniel Hartmeier
>Release:        8.3-STABLE
>Organization:
>Environment:
8.3-STABLE i386
>Description:
Some systems produce IP fragments that are so small that the minimum ethernet frame size requires padding.

For example, a VOIP server may produce UDP SIP messages with 1516 bytes of UDP payload, using an MTU of 1500, creating a first fragment of 1472 bytes payload (+8 bytes UDP header, +20 bytes IP header, +14 bytes ethernet header), and a second fragment of 16 bytes (+20 bytes IP header, +14 bytes ethernet header, +10 bytes trailing ethernet padding).

When pf is reassembling the second fragment, it is seeing an mbuf with m_len == 46 (including the 10 bytes of ethernet padding). The reassembly code will produce a reassembled IP packet that wrongly includes the padding bytes (as invalid ethernet checksum), which causes the IP packet to be dropped (usually after re-fragmentation) on the destination (or intermediate hops).

>How-To-Repeat:
Use two hosts, each with two interfaces (em0 and em1). Configure the second host as a bridge filtering with pf doing fragment reassembly. Connect them so the second host bridges between the first host's two interfaces.

On the first host, send two fragments through the bridge. Expect the fragments to arrive at the bridge, get reassembled by pf, get re-fragmented, then arrive back at the first host.

Instead, the first fragment will either not make it back, or is corrupted.

#!/bin/sh

dd if=/dev/random bs=1 count=1472 | \
        dnet udp sport 5060 dport 5060 | \
        dnet ip tos 104 id 49430 off 0+ ttl 63 proto udp src 172.19.243.20 dst 172.19.241.49 | \
        dnet eth type ip src 00:50:56:9b:00:02 dst 00:50:56:9b:00:0b | \
        dnet send em0

dnet hex "nt-Length: 0\r\n\r\n" | \
        dnet ip tos 104 id 49430 off 1480 ttl 63 proto udp src 172.19.243.20 dst 172.19.241.49 | \
        dnet eth type ip src 00:50:56:9b:00:02 dst 00:50:56:9b:00:0b | \
        dnet send em0

>Fix:
Index: sys/contrib/pf/net/pf_norm.c
===================================================================
RCS file: /home/ncvs/src/sys/contrib/pf/net/pf_norm.c,v
retrieving revision 1.19.10.1
diff -u -r1.19.10.1 pf_norm.c
--- sys/contrib/pf/net/pf_norm.c        3 Aug 2009 08:13:06 -0000       1.19.10.1
+++ sys/contrib/pf/net/pf_norm.c        3 Jul 2012 10:57:25 -0000
@@ -413,6 +413,10 @@
        /* Strip off ip header */
        m->m_data += hlen;
        m->m_len -= hlen;
+       if (m->m_len > ip_len) {
+               DPFPRINTF(("truncating m_len %d -> %d\n", m->m_len, ip_len));
+               m->m_len = ip_len;
+       }

        /* Create a new reassembly queue for this packet */
        if (*frag == NULL) {


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207031423.q63ENwQI028349>