diff options
author | Patrick McHardy <kaber@trash.net> | 2006-03-20 22:23:05 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-20 22:23:05 -0500 |
commit | a193a4abdd1f742a57f3f70b6a83c3e536876e97 (patch) | |
tree | 1b77f9f388ae153815248e8ef30b0297943c7016 /include | |
parent | 6ffd30fbbb1b4a01a9f56049521693375a864d3e (diff) |
[NETFILTER]: Fix skb->nf_bridge lifetime issues
The bridge netfilter code simulates the NF_IP_PRE_ROUTING hook and skips
the real hook by registering with high priority and returning NF_STOP if
skb->nf_bridge is present and the BRNF_NF_BRIDGE_PREROUTING flag is not
set. The flag is only set during the simulated hook.
Because skb->nf_bridge is only freed when the packet is destroyed, the
packet will not only skip the first invocation of NF_IP_PRE_ROUTING, but
in the case of tunnel devices on top of the bridge also all further ones.
Forwarded packets from a bridge encapsulated by a tunnel device and sent
as locally outgoing packet will also still have the incorrect bridge
information from the input path attached.
We already have nf_reset calls on all RX/TX paths of tunnel devices,
so simply reset the nf_bridge field there too. As an added bonus,
the bridge information for locally delivered packets is now also freed
when the packet is queued to a socket.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/skbuff.h | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 838ce0fdcef7..1a2611030d36 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -1351,16 +1351,6 @@ static inline void nf_conntrack_put_reasm(struct sk_buff *skb) | |||
1351 | kfree_skb(skb); | 1351 | kfree_skb(skb); |
1352 | } | 1352 | } |
1353 | #endif | 1353 | #endif |
1354 | static inline void nf_reset(struct sk_buff *skb) | ||
1355 | { | ||
1356 | nf_conntrack_put(skb->nfct); | ||
1357 | skb->nfct = NULL; | ||
1358 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
1359 | nf_conntrack_put_reasm(skb->nfct_reasm); | ||
1360 | skb->nfct_reasm = NULL; | ||
1361 | #endif | ||
1362 | } | ||
1363 | |||
1364 | #ifdef CONFIG_BRIDGE_NETFILTER | 1354 | #ifdef CONFIG_BRIDGE_NETFILTER |
1365 | static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) | 1355 | static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) |
1366 | { | 1356 | { |
@@ -1373,6 +1363,20 @@ static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge) | |||
1373 | atomic_inc(&nf_bridge->use); | 1363 | atomic_inc(&nf_bridge->use); |
1374 | } | 1364 | } |
1375 | #endif /* CONFIG_BRIDGE_NETFILTER */ | 1365 | #endif /* CONFIG_BRIDGE_NETFILTER */ |
1366 | static inline void nf_reset(struct sk_buff *skb) | ||
1367 | { | ||
1368 | nf_conntrack_put(skb->nfct); | ||
1369 | skb->nfct = NULL; | ||
1370 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
1371 | nf_conntrack_put_reasm(skb->nfct_reasm); | ||
1372 | skb->nfct_reasm = NULL; | ||
1373 | #endif | ||
1374 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
1375 | nf_bridge_put(skb->nf_bridge); | ||
1376 | skb->nf_bridge = NULL; | ||
1377 | #endif | ||
1378 | } | ||
1379 | |||
1376 | #else /* CONFIG_NETFILTER */ | 1380 | #else /* CONFIG_NETFILTER */ |
1377 | static inline void nf_reset(struct sk_buff *skb) {} | 1381 | static inline void nf_reset(struct sk_buff *skb) {} |
1378 | #endif /* CONFIG_NETFILTER */ | 1382 | #endif /* CONFIG_NETFILTER */ |