diff options
author | oleg <oleg@FreeBSD.org> | 2009-06-09 21:27:11 +0000 |
---|---|---|
committer | oleg <oleg@FreeBSD.org> | 2009-06-09 21:27:11 +0000 |
commit | 1980405dfdd449338905e8f38096f7b4e80f7784 (patch) | |
tree | 7f52d144f542aa5d755cf5429a93e60617651de6 /sys/net/if_bridge.c | |
parent | 8fdb55dd4173ed49af8cc002203d5c23e353315e (diff) | |
download | FreeBSD-src-1980405dfdd449338905e8f38096f7b4e80f7784.zip FreeBSD-src-1980405dfdd449338905e8f38096f7b4e80f7784.tar.gz |
Close long existed race with net.inet.ip.fw.one_pass = 0:
If packet leaves ipfw to other kernel subsystem (dummynet, netgraph, etc)
it carries pointer to matching ipfw rule. If this packet then reinjected back
to ipfw, ruleset processing starts from that rule. If rule was deleted
meanwhile, due to existed race condition panic was possible (as well as
other odd effects like parsing rules in 'reap list').
P.S. this commit changes ABI so userland ipfw related binaries should be
recompiled.
MFC after: 1 month
Tested by: Mikolaj Golub
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r-- | sys/net/if_bridge.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index f4551d1..db2f617 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -3041,11 +3041,19 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir) if (ip_fw_chk_ptr && pfil_ipfw != 0 && dir == PFIL_OUT && ifp != NULL) { INIT_VNET_INET(curvnet); + struct dn_pkt_tag *dn_tag; error = -1; - args.rule = ip_dn_claim_rule(*mp); - if (args.rule != NULL && V_fw_one_pass) - goto ipfwpass; /* packet already partially processed */ + dn_tag = ip_dn_claim_tag(*mp); + if (dn_tag != NULL) { + if (dn_tag->rule != NULL && V_fw_one_pass) + /* packet already partially processed */ + goto ipfwpass; + args.rule = dn_tag->rule; /* matching rule to restart */ + args.rule_id = dn_tag->rule_id; + args.chain_id = dn_tag->chain_id; + } else + args.rule = NULL; args.m = *mp; args.oif = ifp; |