diff options
| author | Changli Gao <xiaosuo@gmail.com> | 2010-08-03 13:39:18 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-08-05 00:53:14 -0400 |
| commit | 36d12690a2e9bcacae5a2a7e0fb6345a3caad625 (patch) | |
| tree | f3e451b268d498af9ec171f6b454538091010f71 | |
| parent | c33788b45f754bd5dd8adc520e37fa38ac1849c7 (diff) | |
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: Changli Gao <xiaosuo@gmail.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/sched/act_nat.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index d0386a413e8d..509a2d53a99d 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c | |||
| @@ -114,6 +114,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
| 114 | int egress; | 114 | int egress; |
| 115 | int action; | 115 | int action; |
| 116 | int ihl; | 116 | int ihl; |
| 117 | int noff; | ||
| 117 | 118 | ||
| 118 | spin_lock(&p->tcf_lock); | 119 | spin_lock(&p->tcf_lock); |
| 119 | 120 | ||
| @@ -132,7 +133,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
| 132 | if (unlikely(action == TC_ACT_SHOT)) | 133 | if (unlikely(action == TC_ACT_SHOT)) |
| 133 | goto drop; | 134 | goto drop; |
| 134 | 135 | ||
| 135 | if (!pskb_may_pull(skb, sizeof(*iph))) | 136 | noff = skb_network_offset(skb); |
| 137 | if (!pskb_may_pull(skb, sizeof(*iph) + noff)) | ||
| 136 | goto drop; | 138 | goto drop; |
| 137 | 139 | ||
| 138 | iph = ip_hdr(skb); | 140 | iph = ip_hdr(skb); |
| @@ -144,7 +146,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
| 144 | 146 | ||
| 145 | if (!((old_addr ^ addr) & mask)) { | 147 | if (!((old_addr ^ addr) & mask)) { |
| 146 | if (skb_cloned(skb) && | 148 | if (skb_cloned(skb) && |
| 147 | !skb_clone_writable(skb, sizeof(*iph)) && | 149 | !skb_clone_writable(skb, sizeof(*iph) + noff) && |
| 148 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | 150 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
| 149 | goto drop; | 151 | goto drop; |
| 150 | 152 | ||
| @@ -172,9 +174,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
| 172 | { | 174 | { |
| 173 | struct tcphdr *tcph; | 175 | struct tcphdr *tcph; |
| 174 | 176 | ||
| 175 | if (!pskb_may_pull(skb, ihl + sizeof(*tcph)) || | 177 | if (!pskb_may_pull(skb, ihl + sizeof(*tcph) + noff) || |
| 176 | (skb_cloned(skb) && | 178 | (skb_cloned(skb) && |
| 177 | !skb_clone_writable(skb, ihl + sizeof(*tcph)) && | 179 | !skb_clone_writable(skb, ihl + sizeof(*tcph) + noff) && |
| 178 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) | 180 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) |
| 179 | goto drop; | 181 | goto drop; |
| 180 | 182 | ||
| @@ -186,9 +188,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
| 186 | { | 188 | { |
| 187 | struct udphdr *udph; | 189 | struct udphdr *udph; |
| 188 | 190 | ||
| 189 | if (!pskb_may_pull(skb, ihl + sizeof(*udph)) || | 191 | if (!pskb_may_pull(skb, ihl + sizeof(*udph) + noff) || |
| 190 | (skb_cloned(skb) && | 192 | (skb_cloned(skb) && |
| 191 | !skb_clone_writable(skb, ihl + sizeof(*udph)) && | 193 | !skb_clone_writable(skb, ihl + sizeof(*udph) + noff) && |
| 192 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) | 194 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) |
| 193 | goto drop; | 195 | goto drop; |
| 194 | 196 | ||
| @@ -205,7 +207,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
| 205 | { | 207 | { |
| 206 | struct icmphdr *icmph; | 208 | struct icmphdr *icmph; |
| 207 | 209 | ||
| 208 | if (!pskb_may_pull(skb, ihl + sizeof(*icmph))) | 210 | if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + noff)) |
| 209 | goto drop; | 211 | goto drop; |
| 210 | 212 | ||
| 211 | icmph = (void *)(skb_network_header(skb) + ihl); | 213 | icmph = (void *)(skb_network_header(skb) + ihl); |
| @@ -215,7 +217,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
| 215 | (icmph->type != ICMP_PARAMETERPROB)) | 217 | (icmph->type != ICMP_PARAMETERPROB)) |
| 216 | break; | 218 | break; |
| 217 | 219 | ||
| 218 | if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph))) | 220 | if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph) + |
| 221 | noff)) | ||
| 219 | goto drop; | 222 | goto drop; |
| 220 | 223 | ||
| 221 | icmph = (void *)(skb_network_header(skb) + ihl); | 224 | icmph = (void *)(skb_network_header(skb) + ihl); |
| @@ -229,8 +232,8 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a, | |||
| 229 | break; | 232 | break; |
| 230 | 233 | ||
| 231 | if (skb_cloned(skb) && | 234 | if (skb_cloned(skb) && |
| 232 | !skb_clone_writable(skb, | 235 | !skb_clone_writable(skb, ihl + sizeof(*icmph) + |
| 233 | ihl + sizeof(*icmph) + sizeof(*iph)) && | 236 | sizeof(*iph) + noff) && |
| 234 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) | 237 | pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) |
| 235 | goto drop; | 238 | goto drop; |
| 236 | 239 | ||
