>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:
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "[email protected]"

Reply via email to