From mboxrd@z Thu Jan 1 00:00:00 1970 From: Antonio Quartulli Subject: [PATCH net] bridge: clean the nf_bridge status when forwarding the skb Date: Tue, 15 Oct 2013 00:51:36 +0200 Message-ID: <1381791096-3561-1-git-send-email-antonio@meshcoding.com> Cc: netdev@vger.kernel.org, Antonio Quartulli , Stephen Hemminger To: "David S. Miller" Return-path: Received: from s3.neomailbox.net ([178.209.62.157]:20647 "EHLO s3.neomailbox.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756676Ab3JNWwR (ORCPT ); Mon, 14 Oct 2013 18:52:17 -0400 Sender: netdev-owner@vger.kernel.org List-ID: From: Antonio Quartulli Even if it is forbidden to enslave a bridge interface into another one, it is still possible to create a chain of virtual interfaces including two distinct bridges. In this case, the skb entering the second bridge could have the nf_bridge field already set due to a previous operation and consequently lead to wrong a processing of the packet itself. To prevent this behaviour release and set to NULL the nf_bridge field of the skb when forwarding the packet. Cc: Stephen Hemminger Signed-off-by: Antonio Quartulli --- I know that not using "extern" when declaring the prototype is not consistent with the surrounding code, but checkpatch complaints about using "extern" in .h file and I prefer to not do something "wrong" even if stylistically ugly. Cheers, net/bridge/br_forward.c | 2 ++ net/bridge/br_netfilter.c | 10 ++++++++++ net/bridge/br_private.h | 2 ++ 3 files changed, 14 insertions(+) diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 4b81b14..62955f3 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -49,6 +49,8 @@ int br_dev_queue_push_xmit(struct sk_buff *skb) } else { skb_push(skb, ETH_HLEN); br_drop_fake_rtable(skb); + br_netfilter_skb_free(skb); + dev_queue_xmit(skb); } diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index f877362..7cad3e2 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -1086,3 +1086,13 @@ void br_netfilter_fini(void) #endif dst_entries_destroy(&fake_dst_ops); } + +/** + * br_netfilter_skb_free - clean the NF bridge data in an skb + * @skb: the skb which the data to free belongs to + */ +void br_netfilter_skb_free(struct sk_buff *skb) +{ + nf_bridge_put(skb->nf_bridge); + skb->nf_bridge = NULL; +} diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index efb57d9..2a5f637 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -730,10 +730,12 @@ static inline u16 br_get_pvid(const struct net_port_vlans *v) extern int br_netfilter_init(void); extern void br_netfilter_fini(void); extern void br_netfilter_rtable_init(struct net_bridge *); +void br_netfilter_skb_free(struct sk_buff *skb); #else #define br_netfilter_init() (0) #define br_netfilter_fini() do { } while(0) #define br_netfilter_rtable_init(x) +#define br_netfilter_skb_free(x) #endif /* br_stp.c */ -- 1.8.3.2