This is a backport of part of a bug fix that's already in mainline
Linux. The first part of the original fix was applied to 2.6.18, the
subsequent parts to 2.6.19. As a result, Xen currently only has the
first part in the linux-2.6.18-xen.hg tree.
The patch in question was originally posted here:
http://marc.info/?l=linux-netdev&m=115629237505025&w=2
I'm sure adding backported fixes isn't something you want to do
regularly, but as this was found and fixed for a problem on Xen it might
be more applicable.
The bug I saw (if I remember correctly - it's been some time since I
found and backported this fix) was one where netfilter would try to pull
16 bytes (rather than ETH_HLEN) off the front of a socket buffer, and
this would drop us two bytes from the end of the previous page. This
caused a seg fault as the previous page was not in use. For many
drivers this wouldn't be a problem as they have an extra two bytes of
head room thanks to NET_IP_ALIGN, or they just get lucky with the
previous page - I think the reason this was originally found on Xen was
due to it being much more likely that you'll be unlucky. If I'm honest
I didn't look too deeply once I found this fixed it.
To keep it short and simple, I've only backported the functional bits of
the above patch. I.e. I've left out the code rearrangement and clarity
changes.
Signed-off-by: Kieran Mansley <kmansley@xxxxxxxxxxxxxx>
Kieran
Backport 2.6.19 netfilter ETH_HLEN bug fix
diff -r 9bf1ddd0f6bf include/linux/netfilter_bridge.h
--- a/include/linux/netfilter_bridge.h Wed Oct 17 09:24:03 2007 +0100
+++ b/include/linux/netfilter_bridge.h Fri Oct 19 10:53:27 2007 +0100
@@ -7,6 +7,7 @@
#include <linux/netfilter.h>
#if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER)
#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
#endif
/* Bridge Hooks */
@@ -54,16 +55,19 @@ int nf_bridge_maybe_copy_header(struct s
if (skb->nf_bridge) {
if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
- err = skb_cow(skb, 18);
+ int header_size = ETH_HLEN + VLAN_HLEN;
+
+ err = skb_cow(skb, header_size);
if (err)
return err;
- memcpy(skb->data - 18, skb->nf_bridge->data, 18);
- skb_push(skb, 4);
+ memcpy(skb->data - header_size, skb->nf_bridge->data,
+ header_size);
+ skb_push(skb, VLAN_HLEN);
} else {
- err = skb_cow(skb, 16);
+ err = skb_cow(skb, ETH_HLEN);
if (err)
return err;
- memcpy(skb->data - 16, skb->nf_bridge->data, 16);
+ memcpy(skb->data - ETH_HLEN, skb->nf_bridge->data,
ETH_HLEN);
}
}
return 0;
diff -r 9bf1ddd0f6bf net/bridge/br_netfilter.c
--- a/net/bridge/br_netfilter.c Wed Oct 17 09:24:03 2007 +0100
+++ b/net/bridge/br_netfilter.c Fri Oct 19 10:37:06 2007 +0100
@@ -127,10 +127,10 @@ static inline struct nf_bridge_info *nf_
static inline void nf_bridge_save_header(struct sk_buff *skb)
{
- int header_size = 16;
+ int header_size = ETH_HLEN;
if (skb->protocol == htons(ETH_P_8021Q))
- header_size = 18;
+ header_size += VLAN_HLEN;
memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
}
netfilter_bug
Description: Text document
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|