提交 a193a4ab 编写于 作者: P Patrick McHardy 提交者: David S. Miller

[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: NPatrick McHardy <kaber@trash.net>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 6ffd30fb
...@@ -1351,16 +1351,6 @@ static inline void nf_conntrack_put_reasm(struct sk_buff *skb) ...@@ -1351,16 +1351,6 @@ static inline void nf_conntrack_put_reasm(struct sk_buff *skb)
kfree_skb(skb); kfree_skb(skb);
} }
#endif #endif
static inline void nf_reset(struct sk_buff *skb)
{
nf_conntrack_put(skb->nfct);
skb->nfct = NULL;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_conntrack_put_reasm(skb->nfct_reasm);
skb->nfct_reasm = NULL;
#endif
}
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
{ {
...@@ -1373,6 +1363,20 @@ static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge) ...@@ -1373,6 +1363,20 @@ static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge)
atomic_inc(&nf_bridge->use); atomic_inc(&nf_bridge->use);
} }
#endif /* CONFIG_BRIDGE_NETFILTER */ #endif /* CONFIG_BRIDGE_NETFILTER */
static inline void nf_reset(struct sk_buff *skb)
{
nf_conntrack_put(skb->nfct);
skb->nfct = NULL;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_conntrack_put_reasm(skb->nfct_reasm);
skb->nfct_reasm = NULL;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
nf_bridge_put(skb->nf_bridge);
skb->nf_bridge = NULL;
#endif
}
#else /* CONFIG_NETFILTER */ #else /* CONFIG_NETFILTER */
static inline void nf_reset(struct sk_buff *skb) {} static inline void nf_reset(struct sk_buff *skb) {}
#endif /* CONFIG_NETFILTER */ #endif /* CONFIG_NETFILTER */
......
...@@ -154,10 +154,6 @@ static void send_reset(struct sk_buff *oldskb, int hook) ...@@ -154,10 +154,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
/* This packet will not be the same as the other: clear nf fields */ /* This packet will not be the same as the other: clear nf fields */
nf_reset(nskb); nf_reset(nskb);
nskb->nfmark = 0; nskb->nfmark = 0;
#ifdef CONFIG_BRIDGE_NETFILTER
nf_bridge_put(nskb->nf_bridge);
nskb->nf_bridge = NULL;
#endif
tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册