There's a concurrency issue in setups with if_bridge, if_epair and a
real interface.
The setup is:
re0 -- real interface
epair0 -- epair, with one side A in jail 0, side B in jail 1
bridge0 -- bridge with addm re0 addm epair0a
If you send a broadcast udp packet through re0 (with a UDP checksum),
there's a chance that it will be sent on the network with a bad
checksum, and that checksum will be the UDP size.
This seems to be happening as a result of the following chain:
a) if_bridge.c:bridge_output uses m_copypacket to generate an mbuf with
shared data, which is then enqueued to each interface in the bridge
(with the add order above, epair0a goes first)
b) if_epair sends the mbuf to side B
c) udp_usrreq.c:udp_input (in the vtnet jail, processing the incoming
packet on epair0b) munges the data in the mbuf as part of verifying the
checksum; it puts most of the data back, but the IP header checksum
value is replaced with the UDP length.
d) if_re sends the packet out on the physical interface
Unshare the mbuf prior to enqueuing it to ensure that any modifications
the receiving epair makes don't affect other interfaces.
MFC after: 3 weeks