diff options
author | David S. Miller <davem@davemloft.net> | 2014-05-30 20:56:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-30 20:56:09 -0400 |
commit | dbfc4b698ab83494eb8a03f5f3c478cec29a4f62 (patch) | |
tree | f04719877ba135dcc38335c0e9f2323f7c3d742a | |
parent | 554215c5ca08d196ed48a66693e7fc6e5f81f00e (diff) | |
parent | f44a5f45f544561302e855e7bd104e5f506ec01b (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says:
====================
The following patchset contains a late fix for IPVS:
* Fix crash when trying to remove the transport header with non-linear
skbuffs, this was introduced in 3.6-rc. Patch from Peter Christensen
via the IPVS folks.
I'll pass this to -stable once this hits mainstream.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 4f26ee46b51f..3d2d2c8108ca 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -1392,15 +1392,19 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1392 | 1392 | ||
1393 | if (ipip) { | 1393 | if (ipip) { |
1394 | __be32 info = ic->un.gateway; | 1394 | __be32 info = ic->un.gateway; |
1395 | __u8 type = ic->type; | ||
1396 | __u8 code = ic->code; | ||
1395 | 1397 | ||
1396 | /* Update the MTU */ | 1398 | /* Update the MTU */ |
1397 | if (ic->type == ICMP_DEST_UNREACH && | 1399 | if (ic->type == ICMP_DEST_UNREACH && |
1398 | ic->code == ICMP_FRAG_NEEDED) { | 1400 | ic->code == ICMP_FRAG_NEEDED) { |
1399 | struct ip_vs_dest *dest = cp->dest; | 1401 | struct ip_vs_dest *dest = cp->dest; |
1400 | u32 mtu = ntohs(ic->un.frag.mtu); | 1402 | u32 mtu = ntohs(ic->un.frag.mtu); |
1403 | __be16 frag_off = cih->frag_off; | ||
1401 | 1404 | ||
1402 | /* Strip outer IP and ICMP, go to IPIP header */ | 1405 | /* Strip outer IP and ICMP, go to IPIP header */ |
1403 | __skb_pull(skb, ihl + sizeof(_icmph)); | 1406 | if (pskb_pull(skb, ihl + sizeof(_icmph)) == NULL) |
1407 | goto ignore_ipip; | ||
1404 | offset2 -= ihl + sizeof(_icmph); | 1408 | offset2 -= ihl + sizeof(_icmph); |
1405 | skb_reset_network_header(skb); | 1409 | skb_reset_network_header(skb); |
1406 | IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u\n", | 1410 | IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u\n", |
@@ -1408,7 +1412,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1408 | ipv4_update_pmtu(skb, dev_net(skb->dev), | 1412 | ipv4_update_pmtu(skb, dev_net(skb->dev), |
1409 | mtu, 0, 0, 0, 0); | 1413 | mtu, 0, 0, 0, 0); |
1410 | /* Client uses PMTUD? */ | 1414 | /* Client uses PMTUD? */ |
1411 | if (!(cih->frag_off & htons(IP_DF))) | 1415 | if (!(frag_off & htons(IP_DF))) |
1412 | goto ignore_ipip; | 1416 | goto ignore_ipip; |
1413 | /* Prefer the resulting PMTU */ | 1417 | /* Prefer the resulting PMTU */ |
1414 | if (dest) { | 1418 | if (dest) { |
@@ -1427,12 +1431,13 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1427 | /* Strip outer IP, ICMP and IPIP, go to IP header of | 1431 | /* Strip outer IP, ICMP and IPIP, go to IP header of |
1428 | * original request. | 1432 | * original request. |
1429 | */ | 1433 | */ |
1430 | __skb_pull(skb, offset2); | 1434 | if (pskb_pull(skb, offset2) == NULL) |
1435 | goto ignore_ipip; | ||
1431 | skb_reset_network_header(skb); | 1436 | skb_reset_network_header(skb); |
1432 | IP_VS_DBG(12, "Sending ICMP for %pI4->%pI4: t=%u, c=%u, i=%u\n", | 1437 | IP_VS_DBG(12, "Sending ICMP for %pI4->%pI4: t=%u, c=%u, i=%u\n", |
1433 | &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, | 1438 | &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, |
1434 | ic->type, ic->code, ntohl(info)); | 1439 | type, code, ntohl(info)); |
1435 | icmp_send(skb, ic->type, ic->code, info); | 1440 | icmp_send(skb, type, code, info); |
1436 | /* ICMP can be shorter but anyways, account it */ | 1441 | /* ICMP can be shorter but anyways, account it */ |
1437 | ip_vs_out_stats(cp, skb); | 1442 | ip_vs_out_stats(cp, skb); |
1438 | 1443 | ||