When the bridge topology allows a single skb to traverse more than one
bridge we end up leaking skb->nf_bridge each time the skb enters the
second or higher bridge.  The leak occurs when bridge netfilter is
enabled on 2.4 (with bridge netfilter patch) and 2.6 git head,
proposed 2.4 fix below.

Leaky topology:

brvlan1 -> vlan1 __
                   \-> brtrunk -> eth0

To configure the above toploogy, something like:

 brctl addbr brtrunk
 brctl addif brtrunk eth0
 ifconfig eth0 0.0.0.0
 ifconfig brtrunk 0.0.0.0

 vconfig set_name_type VLAN_PLUS_VID_NO_PAD
 vconfig add brtrunk 1
 ifconfig vlan1 up

 brctl addbr brvlan1
 brctl addif brvlan1 vlan1
 ifconfig brvlan1 10.10.0.1

To see the leak send a packet between 10.10.0.1 and anywhere that
causes the packet to pass through brvlan1 and brtrunk.  For example, a host
10.10.0.2 on the same physical network as eth0 configured:

 vconfig set_name_type VLAN_PLUS_VID_NO_PAD
 vconfig add eth0 1
 ifconfig vlan1 10.10.0.2

A proposed fix for 2.4 follows.  I don't understand completely the way
packets traverse bridge netfilter so I have only called
nf_bridge_put() where I see the leak.  Perhaps nf_bridge_put() should
be called before other calls to nf_bridge_alloc().

        * net/bridge/br_netfilter.c (br_nf_pre_routing) : Call nf_bridge_put()
          before potentially allocating a new nf_bridge structure and
          overwriting the pointer to it.
        * net/core/skbuff.c (alloc_skb) : Initialize nf_bridge to NULL so
          we can safely call nf_bridge_put() on newly allocated skb's.

Signed-off-by: David Kimdon <[EMAIL PROTECTED]>

--- linux-2.4.x/net/bridge/br_netfilter.c
+++ linux-2.4.x/net/bridge/br_netfilter.c
@@ -284,6 +284,7 @@
 #ifdef CONFIG_NETFILTER_DEBUG
        skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING);
 #endif
+       nf_bridge_put(skb->nf_bridge);
        if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
                return NF_DROP;
 
--- linux-2.4.x/net/core/skbuff.c
+++ linux-2.4.x/net/core/skbuff.c
@@ -216,6 +216,9 @@
        atomic_set(&(skb_shinfo(skb)->dataref), 1);
        skb_shinfo(skb)->nr_frags = 0;
        skb_shinfo(skb)->frag_list = NULL;
+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
+       skb->nf_bridge = NULL;
+#endif
        return skb;
 
 nodata:

-- 
David Kimdon                        (650) 829 2621
Devicescape Software
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to