aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-08-26 23:28:30 -0400
committerDavid S. Miller <davem@davemloft.net>2006-08-26 23:28:30 -0400
commit3a13813e6effcfad5910d47b15b724621b50b878 (patch)
tree30aaf88578ee23b0a1c0f90e7ee1100244d62415
parent8dbc16033e35c7443cd56cb5ba308bb19cb7b469 (diff)
[BRIDGE] netfilter: memory corruption fix
The bridge-netfilter code will overwrite memory if there is not headroom in the skb to save the header. This first showed up when using Xen with sky2 driver that doesn't allocate the extra space. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netfilter_bridge.h14
-rw-r--r--net/bridge/br_forward.c10
2 files changed, 19 insertions, 5 deletions
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index 10c13dc4665b..427c67ff89e9 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -48,15 +48,25 @@ enum nf_br_hook_priorities {
48 48
49/* Only used in br_forward.c */ 49/* Only used in br_forward.c */
50static inline 50static inline
51void nf_bridge_maybe_copy_header(struct sk_buff *skb) 51int nf_bridge_maybe_copy_header(struct sk_buff *skb)
52{ 52{
53 int err;
54
53 if (skb->nf_bridge) { 55 if (skb->nf_bridge) {
54 if (skb->protocol == __constant_htons(ETH_P_8021Q)) { 56 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
57 err = skb_cow(skb, 18);
58 if (err)
59 return err;
55 memcpy(skb->data - 18, skb->nf_bridge->data, 18); 60 memcpy(skb->data - 18, skb->nf_bridge->data, 18);
56 skb_push(skb, 4); 61 skb_push(skb, 4);
57 } else 62 } else {
63 err = skb_cow(skb, 16);
64 if (err)
65 return err;
58 memcpy(skb->data - 16, skb->nf_bridge->data, 16); 66 memcpy(skb->data - 16, skb->nf_bridge->data, 16);
67 }
59 } 68 }
69 return 0;
60} 70}
61 71
62/* This is called by the IP fragmenting code and it ensures there is 72/* This is called by the IP fragmenting code and it ensures there is
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 6ccd32b30809..864fbbc7b24d 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -40,11 +40,15 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
40 else { 40 else {
41#ifdef CONFIG_BRIDGE_NETFILTER 41#ifdef CONFIG_BRIDGE_NETFILTER
42 /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */ 42 /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */
43 nf_bridge_maybe_copy_header(skb); 43 if (nf_bridge_maybe_copy_header(skb))
44 kfree_skb(skb);
45 else
44#endif 46#endif
45 skb_push(skb, ETH_HLEN); 47 {
48 skb_push(skb, ETH_HLEN);
46 49
47 dev_queue_xmit(skb); 50 dev_queue_xmit(skb);
51 }
48 } 52 }
49 53
50 return 0; 54 return 0;