summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Guo <ggang@tilera.com>2011-11-14 19:00:54 +0800
committerPablo Neira Ayuso <pablo@netfilter.org>2011-11-21 18:46:18 +0100
commit5e2afba4ecd7931ea06e6fa116ab28e6943dbd42 (patch)
treea497953b9aca136e0276b3315630eaf16831d8fd
parent648ae8e53d58ed1b667db173a2d4ff2132a3b529 (diff)
downloadlinux-5e2afba4ecd7931ea06e6fa116ab28e6943dbd42.tar.gz
linux-5e2afba4ecd7931ea06e6fa116ab28e6943dbd42.tar.bz2
linux-5e2afba4ecd7931ea06e6fa116ab28e6943dbd42.zip
netfilter: possible unaligned packet header in ip_route_me_harder
This patch tries to fix the following issue in netfilter: In ip_route_me_harder(), we invoke pskb_expand_head() that rellocates new header with additional head room which can break the alignment of the original packet header. In one of my NAT test case, the NIC port for internal hosts is configured with vlan and the port for external hosts is with general configuration. If we ping an external "unknown" hosts from an internal host, an icmp packet will be sent. We find that in icmp_send()->...->ip_route_me_harder()->pskb_expand_head(), hh_len=18 and current headroom (skb_headroom(skb)) of the packet is 16. After calling pskb_expand_head() the packet header becomes to be unaligned and then our system (arch/tile) panics immediately. Signed-off-by: Paul Guo <ggang@tilera.com> Acked-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--net/ipv4/netfilter.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 9899619ab9b8..4f47e064e262 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -64,7 +64,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
/* Change in oif may mean change in hh_len. */
hh_len = skb_dst(skb)->dev->hard_header_len;
if (skb_headroom(skb) < hh_len &&
- pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC))
+ pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)),
+ 0, GFP_ATOMIC))
return -1;
return 0;