Page MenuHomeFreeBSD

if_bridge: map unmapped mbufs before filtering
Needs ReviewPublic

Authored by netchild on Thu, Sep 3, 6:57 AM.
Tags
None
Referenced Files
F170121089: D59332.id.diff
Thu, Sep 3, 2:05 PM
F170096628: D59332.id185682.diff
Thu, Sep 3, 12:15 PM
F170092959: D59332.diff
Thu, Sep 3, 12:00 PM
F170086306: D59332.id185682.diff
Thu, Sep 3, 11:31 AM
F170050310: D59332.id.diff
Thu, Sep 3, 9:05 AM
F170049395: D59332.id.diff
Thu, Sep 3, 9:01 AM
F170046669: D59332.diff
Thu, Sep 3, 8:48 AM
F170029400: D59332.id185682.diff
Thu, Sep 3, 7:25 AM

Details

Summary

bridge_pfil() dereferences the packet through m_pullup(), m_adj() and
M_PREPEND(). A member that advertises IFCAP_MEXTPG can hand the bridge
an unmapped chain, on which mtod() is NULL. Convert it to a mapped
chain on entry, preventing a panic when a sendfile(2) or KTLS segment
from a VNET jail is filtered.

m_pullup() asserted only the first mbuf of the chain and m_copyup() not
at all. Assert inside both copy loops.

Fixes: c38abd64dbc1 ("if_epair: support IFCAP_MEXTPG")
Assisted-by: Claude Code (Opus 5)

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 76419
Build 73302: arc lint + arc unit

Event Timeline

netchild held this revision as a draft.
netchild published this revision for review.Thu, Sep 3, 7:01 AM

Unit tests in D59333

After a bit more digging around. This does not seem only to be a particular problem for the bridge, this is a problem for everything pfil related...
ipfw_check_frame_mbuf() seems to have the same bug (depends on net.link.ether.ipfw=1).
pf's ethernet hook seems to be safe at first look (m_copydata()).
if_enc passes the chain without touching, safe.
dummynet: pulls 14 bytes, so probably safe.
ipfilter: no idea, maybe.

Is this the right place to fix it, or should ip_ouput() map them more early (before the PFIL hooks)?

Is this the right place to fix it, or should ip_ouput() map them more early (before the PFIL hooks)?

I take the part about ip_ouput back, it is not involved here. The failure case here is epair_tx_start_deferred → bridge_input → bridge_forward → bridge_pfil.

sys/net/if_bridge.c
3964

We have spent a fair bit of effort trying to remove these calls when possible. They are expensive and add a new failure mode. For instance, it looks like there's a bug here: we're dropping a packet but not incrementing any error counters.

Can we avoid the problem by only pulling up sizeof(struct ether_header) bytes at first, and then sizeof(struct llc) bytes later if needed?

sys/net/if_bridge.c
3964

Other areas in the bridge code seem to drop packets without increasing counters too.

I think this could be modeled here in the bridge code in a way like pf does it already in another place. But this then opens up the possibility that other places run into that same panic (see in my previous comments).

I can test easily on the system where I got the panic with pf. I have a look at coming up with something less expensive.