[Bug 185633] [pf] scrubbing bug in transparent mode bug with bigger than MTU UDP packet

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Thu Sep 1 23:59:38 UTC 2016


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=185633

--- Comment #12 from Olivier Cochard <olivier at freebsd.org> ---
I've added some lines like:
if_printf(ifp,"[DEBUG] bridge_fragment() exiting, m_len: %d\n",m->m_len);

in the sys/net/if_bridge.c code.

Now, here is the behavior with pf-in-bridge-mode, BUT without scrub, when I
generate a "ping -c 1 -s 1500" (:

bridge0: [DEBUG] bridge_pfil() enter, dir: 1(IN:1/OUT:2), m_len: 1514
bridge0: [DEBUG] bridge_pfil() exit, dir: 1(IN:1/OUT:2), m_len: 1514
bridge0: [DEBUG] bridge_pfil() enter, dir: 2(IN:1/OUT:2), m_len: 1514
bridge0: [DEBUG] bridge_pfil() exit, dir: 2(IN:1/OUT:2), m_len: 1514
bridge0: [DEBUG] bridge_pfil() enter, dir: 1(IN:1/OUT:2), m_len: 62
bridge0: [DEBUG] bridge_pfil() exit, dir: 1(IN:1/OUT:2), m_len: 62
bridge0: [DEBUG] bridge_pfil() enter, dir: 2(IN:1/OUT:2), m_len: 62
bridge0: [DEBUG] bridge_pfil() exit, dir: 2(IN:1/OUT:2), m_len: 62
bridge0: [DEBUG] bridge_pfil() enter, dir: 1(IN:1/OUT:2), m_len: 1514
bridge0: [DEBUG] bridge_pfil() exit, dir: 1(IN:1/OUT:2), m_len: 1514
bridge0: [DEBUG] bridge_pfil() enter, dir: 2(IN:1/OUT:2), m_len: 1514
bridge0: [DEBUG] bridge_pfil() exit, dir: 2(IN:1/OUT:2), m_len: 1514
bridge0: [DEBUG] bridge_pfil() enter, dir: 1(IN:1/OUT:2), m_len: 62
bridge0: [DEBUG] bridge_pfil() exit, dir: 1(IN:1/OUT:2), m_len: 62
bridge0: [DEBUG] bridge_pfil() enter, dir: 2(IN:1/OUT:2), m_len: 62
bridge0: [DEBUG] bridge_pfil() exit, dir: 2(IN:1/OUT:2), m_len: 62

=> For each packet received, there are transmitted as-it.


Now, here is the behavior with pf-in-bridge-mode WITH scrub:

bridge0: [DEBUG] bridge_pfil() enter, dir: 1(IN:1/OUT:2), m_len: 1514
pf_normalize_ip: DEBUG branch frag: 0xfffff80003e73300(m_pkthrd.len:1500)
pf_normalize_ip: reass frag 45306 @ 0-1480
pf_fillup_fragment: reass frag 45306 @ 0-1480
bridge0: [DEBUG] bridge_pfil() enter, dir: 1(IN:1/OUT:2), m_len: 62
pf_normalize_ip: DEBUG branch frag: 0xfffff80003e73200(m_pkthrd.len:48)
pf_normalize_ip: reass frag 45306 @ 1480-1508
pf_fillup_fragment: reass frag 45306 @ 1480-1508
pf_isfull_fragment: 1508 < 1508?
pf_reassemble: complete: 0xfffff80003e73300(m_pkthrd.len:1528, p_len: 1528)
bridge0: [DEBUG] bridge_pfil() exit, dir: 1(IN:1/OUT:2), m_len: 1542
bridge0: [DEBUG] bridge_pfil() enter, dir: 2(IN:1/OUT:2), m_len: 1542
vtnet1: [DEBUG] bridge_fragment() entering, m_len: 1528
vtnet1: [DEBUG] bridge_fragment() exiting, m_len: 1500
panic: bridge_enqueue: no mbuf packet header!

=> There are 2 new functions called: pf_normalize and bridge_fragment.

Here is my interpretation in the scrub-and-bridge-mode:
1. bridge_pfil (IN) the first fragmented packet (mbuf_len of MTU max ethernet
frame = 1514)
2. pf_normalize (scrub) detect a fragment, and wait for the next fragment
3. bridge_pfil (IN) the second fragment packet (mbuf_len of 62 Bytes Ethernet
frame)
4. pf_normalize reassemble this 2 mbuf in one big mbuf of 1528 (=20 bytes for
IP header + 1508 bytes of ICMP header+data)
5. bridge_pfil (IN) re-add 14 bytes of Ethernet Header to this mbuf (m_len=1542
bytes)
6. bridge_pfil (OUT) takes this mbuf (m_len=1542), remove the Ethernet header
(m_len - 14 = 1528) and call bridge_fragment() because it's bigger than MTU.
7. bridge_fragment should have a bug, because it reduce the m_len to 1500 and
try to fordward it to NIC (it should be at 1514 minimum, not 1500!).
8. The ASSERT I've set is triggered: We can't send an mbuf without ethernet
header to the NIC.

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-pf mailing list