Re: Panic in ebtables-5 with 2.4.25 with ip_conntrack and vlan

Bart De Schuymer <[email protected]>
Newsgroups gmane.linux.network.bridge.ebtables.devel
Message-ID <[email protected]>
On Tuesday 24 February 2004 22:50, Bart De Schuymer wrote:
> On Tuesday 24 February 2004 22:01, Adam Osuchowski wrote:
> > Hello,
> >
> > there is small problem with ebtables 5 on 2.4.24 & 2.4.25 kernels. When
> > fragmented IP packet embedded in tagged vlan frame traverses the kernel
> > with ip_conntrack enabled a panic occures due to memory underflow.
> >
> > The following patch resolve this problem but maybe there is better way to
> > fix it.
>
> Thanks for the report and patch.
> I'll have a closer look at it later this week, I'm kind of busy at the
> moment. Hopefully there's a less intrusive fix...

I don't see any way to deal with this without changing the ip_fragment() code.
I'll be sending the 2.6 equivalent of the patch below to David Miller.
I've put the pad length decision into the netfilter_bridge header, to
keep ip_fragment() cleaner.

cheers,
Bart


--- linux-2.4.24/include/linux/netfilter_bridge.h.save	Sun Feb 29 18:06:45 2004
+++ linux-2.4.24/include/linux/netfilter_bridge.h	Sun Feb 29 18:08:55 2004
@@ -86,6 +86,20 @@ void nf_bridge_save_header(struct sk_buf
 	memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
 }
 
+/* This is called by the IP fragmenting code and it ensures there is
+ * enough room for the encapsulating header (if there is one). */
+static inline
+int nf_bridge_pad(struct sk_buff *skb)
+{
+	if (skb->protocol == __constant_htons(ETH_P_IP))
+		return 0;
+	if (skb->nf_bridge) {
+		if (skb->protocol == __constant_htons(ETH_P_8021Q))
+			return 4;
+	}
+	return 0;
+}
+
 struct bridge_skb_cb {
 	union {
 		__u32 ipv4;
--- linux-2.4.24/net/ipv4/ip_output.c.save	Sun Feb 29 18:20:32 2004
+++ linux-2.4.24/net/ipv4/ip_output.c	Sun Feb 29 19:58:03 2004
@@ -75,6 +75,7 @@
 #include <net/inetpeer.h>
 #include <linux/igmp.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_bridge.h>
 #include <linux/mroute.h>
 #include <linux/netlink.h>
 
@@ -757,7 +758,7 @@ int ip_fragment(struct sk_buff *skb, int
 	int ptr;
 	struct net_device *dev;
 	struct sk_buff *skb2;
-	unsigned int mtu, hlen, left, len; 
+	unsigned int mtu, hlen, left, len, ll_rs;
 	int offset;
 	int not_last_frag;
 	struct rtable *rt = (struct rtable*)skb->dst;
@@ -787,6 +788,13 @@ int ip_fragment(struct sk_buff *skb, int
 	offset = (ntohs(iph->frag_off) & IP_OFFSET) << 3;
 	not_last_frag = iph->frag_off & htons(IP_MF);
 
+	ll_rs = dev->hard_header_len+15;
+#ifdef CONFIG_BRIDGE_NETFILTER
+	/* for bridged IP traffic encapsulated inside f.e. a vlan header,
+	 * we need to make room for the encapsulating header */
+	ll_rs += nf_bridge_pad(skb);
+	mtu -= nf_bridge_pad(skb);
+#endif
 	/*
 	 *	Keep copying data until we run out.
 	 */
@@ -805,7 +813,7 @@ int ip_fragment(struct sk_buff *skb, int
 		 *	Allocate buffer.
 		 */
 
-		if ((skb2 = alloc_skb(len+hlen+dev->hard_header_len+15,GFP_ATOMIC)) == NULL) {
+		if ((skb2 = alloc_skb(len+hlen+ll_rs,GFP_ATOMIC)) == NULL) {
 			NETDEBUG(printk(KERN_INFO "IP: frag: no memory for new fragment!\n"));
 			err = -ENOMEM;
 			goto fail;
@@ -817,7 +825,7 @@ int ip_fragment(struct sk_buff *skb, int
 
 		skb2->pkt_type = skb->pkt_type;
 		skb2->priority = skb->priority;
-		skb_reserve(skb2, (dev->hard_header_len+15)&~15);
+		skb_reserve(skb2, ll_rs&~15);
 		skb_put(skb2, len + hlen);
 		skb2->nh.raw = skb2->data;
 		skb2->h.raw = skb2->data + hlen;



-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now.
Build and deploy apps & Web services for Linux with
a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.