Commit 36d12690 authored by Changli Gao's avatar Changli Gao Committed by David S. Miller

act_nat: fix on the TX path

On the TX path, skb->data points to the ethernet header, not the network
header. So when validating the packet length for accessing we should
take the ethernet header into account.
Signed-off-by: default avatarChangli Gao <xiaosuo@gmail.com>
Acked-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c33788b4
...@@ -114,6 +114,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, ...@@ -114,6 +114,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
int egress; int egress;
int action; int action;
int ihl; int ihl;
int noff;
spin_lock(&p->tcf_lock); spin_lock(&p->tcf_lock);
...@@ -132,7 +133,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, ...@@ -132,7 +133,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
if (unlikely(action == TC_ACT_SHOT)) if (unlikely(action == TC_ACT_SHOT))
goto drop; goto drop;
if (!pskb_may_pull(skb, sizeof(*iph))) noff = skb_network_offset(skb);
if (!pskb_may_pull(skb, sizeof(*iph) + noff))
goto drop; goto drop;
iph = ip_hdr(skb); iph = ip_hdr(skb);
...@@ -144,7 +146,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, ...@@ -144,7 +146,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
if (!((old_addr ^ addr) & mask)) { if (!((old_addr ^ addr) & mask)) {
if (skb_cloned(skb) && if (skb_cloned(skb) &&
!skb_clone_writable(skb, sizeof(*iph)) && !skb_clone_writable(skb, sizeof(*iph) + noff) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
goto drop; goto drop;
...@@ -172,9 +174,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, ...@@ -172,9 +174,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
{ {
struct tcphdr *tcph; struct tcphdr *tcph;
if (!pskb_may_pull(skb, ihl + sizeof(*tcph)) || if (!pskb_may_pull(skb, ihl + sizeof(*tcph) + noff) ||
(skb_cloned(skb) && (skb_cloned(skb) &&
!skb_clone_writable(skb, ihl + sizeof(*tcph)) && !skb_clone_writable(skb, ihl + sizeof(*tcph) + noff) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
goto drop; goto drop;
...@@ -186,9 +188,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, ...@@ -186,9 +188,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
{ {
struct udphdr *udph; struct udphdr *udph;
if (!pskb_may_pull(skb, ihl + sizeof(*udph)) || if (!pskb_may_pull(skb, ihl + sizeof(*udph) + noff) ||
(skb_cloned(skb) && (skb_cloned(skb) &&
!skb_clone_writable(skb, ihl + sizeof(*udph)) && !skb_clone_writable(skb, ihl + sizeof(*udph) + noff) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
goto drop; goto drop;
...@@ -205,7 +207,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, ...@@ -205,7 +207,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
{ {
struct icmphdr *icmph; struct icmphdr *icmph;
if (!pskb_may_pull(skb, ihl + sizeof(*icmph))) if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + noff))
goto drop; goto drop;
icmph = (void *)(skb_network_header(skb) + ihl); icmph = (void *)(skb_network_header(skb) + ihl);
...@@ -215,7 +217,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, ...@@ -215,7 +217,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
(icmph->type != ICMP_PARAMETERPROB)) (icmph->type != ICMP_PARAMETERPROB))
break; break;
if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph))) if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph) +
noff))
goto drop; goto drop;
icmph = (void *)(skb_network_header(skb) + ihl); icmph = (void *)(skb_network_header(skb) + ihl);
...@@ -229,8 +232,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, ...@@ -229,8 +232,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
break; break;
if (skb_cloned(skb) && if (skb_cloned(skb) &&
!skb_clone_writable(skb, !skb_clone_writable(skb, ihl + sizeof(*icmph) +
ihl + sizeof(*icmph) + sizeof(*iph)) && sizeof(*iph) + noff) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
goto drop; goto drop;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment