>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]"