linux/net/ipv6
Michal Kubeček 72a2cad7b6 net: account for current skb length when deciding about UFO
commit a5cb659bbc upstream.

Our customer encountered stuck NFS writes for blocks starting at specific
offsets w.r.t. page boundary caused by networking stack sending packets via
UFO enabled device with wrong checksum. The problem can be reproduced by
composing a long UDP datagram from multiple parts using MSG_MORE flag:

  sendto(sd, buff, 1000, MSG_MORE, ...);
  sendto(sd, buff, 1000, MSG_MORE, ...);
  sendto(sd, buff, 3000, 0, ...);

Assume this packet is to be routed via a device with MTU 1500 and
NETIF_F_UFO enabled. When second sendto() gets into __ip_append_data(),
this condition is tested (among others) to decide whether to call
ip_ufo_append_data():

  ((length + fragheaderlen) > mtu) || (skb && skb_is_gso(skb))

At the moment, we already have skb with 1028 bytes of data which is not
marked for GSO so that the test is false (fragheaderlen is usually 20).
Thus we append second 1000 bytes to this skb without invoking UFO. Third
sendto(), however, has sufficient length to trigger the UFO path so that we
end up with non-UFO skb followed by a UFO one. Later on, udp_send_skb()
uses udp_csum() to calculate the checksum but that assumes all fragments
have correct checksum in skb->csum which is not true for UFO fragments.

When checking against MTU, we need to add skb->len to length of new segment
if we already have a partially filled skb and fragheaderlen only if there
isn't one.

In the IPv6 case, skb can only be null if this is the first segment so that
we have to use headersize (length of the first IPv6 header) rather than
fragheaderlen (length of IPv6 header of further fragments) for skb == NULL.

Fixes: e89e9cf539 ("[IPv4/IPv6]: UFO Scatter-gather approach")
Fixes: e4c5e13aa4 ("ipv6: Should use consistent conditional judgement for
	ip6 fragment between __ip6_append_data and ip6_finish_output")
Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
Acked-by: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16:
 - Move headersize out of the if-statement in ip6_append_data() so it can be
   used for this
 - Adjust context to apply after "udp: consistently apply ufo or fragmentation"]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
History 2017-09-15 18:30:15 +01:00
..
netfilter netfilter: rpfilter: fix incorrect loopback packet judgment 2017-03-16 02:26:59 +00:00
addrconf.c ipv6: avoid unregistering inet6_dev for loopback 2017-09-15 18:30:14 +01:00
addrconf_core.c ipv6: remove rt6i_genid 2014-10-15 12:05:29 +02:00
addrlabel.c ipv6/addrlabel: fix ip6addrlbl_get() 2016-01-25 10:44:00 +00:00
af_inet6.c ipv6: move stub initialization after ipv6 setup completion 2017-07-18 18:40:39 +01:00
ah6.c ah6: Use the IPsec protocol multiplexer API 2014-03-14 07:28:07 +01:00
anycast.c ipv6: restore the behavior of ipv6_sock_ac_drop() 2014-10-15 12:05:28 +02:00
datagram.c ipv6/udp: use sticky pktinfo egress ifindex on connect() 2016-03-09 10:38:49 +00:00
esp6.c esp6: Use the IPsec protocol multiplexer API 2014-03-14 07:28:07 +01:00
exthdrs.c ipv6: Need to export ipv6_push_frag_opts for tunneling now. 2017-08-26 02:14:43 +01:00
exthdrs_core.c ipv6: re-enable fragment header matching in ipv6_find_hdr 2016-03-24 10:01:14 +00:00
exthdrs_offload.c ipv6: fix exthdrs offload registration in out_rt path 2015-09-30 13:20:50 +01:00
fib6_rules.c ipv6: Do not leak throw route references 2017-09-15 18:30:13 +01:00
icmp.c ipv6: fix endianness error in icmpv6_err 2016-08-22 22:38:15 +01:00
inet6_connection_sock.c ipv6: add complete rcu protection around np->opt 2015-12-18 16:06:24 +00:00
inet6_hashtables.c inet: convert inet_ehash_secret and ipv6_hash_secret to net_get_random_once 2013-10-19 19:45:35 -04:00
ip6_checksum.c udp: Generic functions to set checksum 2014-06-04 22:46:38 -07:00
ip6_fib.c ipv6: make ECMP route replacement less greedy 2017-07-18 18:40:12 +01:00
ip6_flowlabel.c ipv6: fix a lockdep splat 2016-02-25 10:51:01 +00:00
ip6_gre.c ip6_tunnel: must reload ipv6h in ip6ip6_tnl_xmit() 2017-03-16 02:27:05 +00:00
ip6_icmp.c ipv6: Kill ipv6 dependency of icmpv6_send(). 2013-04-29 13:54:36 -04:00
ip6_input.c ipv6: Make MLD packets to only be processed locally 2015-08-10 17:10:15 +01:00
ip6_offload.c ipv6: Fix leak in ipv6_gso_segment(). 2017-09-15 18:29:56 +01:00
ip6_offload.h ipv6: Pull IPv6 GSO registration out of the module 2012-11-15 17:39:24 -05:00
ip6_output.c net: account for current skb length when deciding about UFO 2017-09-15 18:30:15 +01:00
ip6_tunnel.c ip6_tunnel: Fix missing tunnel encapsulation limit option 2017-08-26 02:14:43 +01:00
ip6_vti.c vti6: fix uninit when using x-netns 2015-05-06 11:33:05 +01:00
ip6mr.c ipmr/ip6mr: Initialize the last assert time of mfc entries. 2017-03-16 02:27:17 +00:00
ipcomp6.c ipcomp6: Use the IPsec protocol multiplexer API 2014-03-14 07:28:07 +01:00
ipv6_sockglue.c ipv6: add complete rcu protection around np->opt 2015-12-18 16:06:24 +00:00
Kconfig ip6_vti: Fix build when NET_IP_TUNNEL is not set. 2014-02-20 14:29:49 +01:00
Makefile xfrm6: Add IPsec protocol multiplexer 2014-03-14 07:28:07 +01:00
mcast.c igmp, mld: Fix memory leak in igmpv3/mld_del_delrec() 2017-03-16 02:27:26 +00:00
mip6.c ipv4/ipv6: Fix FSF address in file headers 2013-12-06 12:37:56 -05:00
ndisc.c net: ipv6: send unsolicited NA on admin up 2017-08-26 02:14:33 +01:00
netfilter.c netfilter: Fix potential use after free in ip6_route_me_harder() 2014-05-09 02:36:39 +02:00
output_core.c ipv6: avoid overflow of offset in ip6_find_1stfragopt 2017-08-26 02:14:48 +01:00
ping.c net: ping: do not abuse udp_poll() 2017-09-15 18:29:56 +01:00
proc.c snmp: fix some left over of snmp stats 2014-05-14 15:33:47 -04:00
protocol.c net: remove outdated comment for ipv4 and ipv6 protocol handler 2013-11-28 18:47:51 -05:00
raw.c net: ping: do not abuse udp_poll() 2017-09-15 18:29:56 +01:00
reassembly.c ipv6: distinguish frag queues by device for multicast and link-local packets 2015-12-18 16:06:23 +00:00
route.c ipv6: only call ip6_route_dev_notify() once for NETDEV_UNREGISTER 2017-09-15 18:30:14 +01:00
sit.c sit: fix a double free on error path 2017-03-16 02:27:25 +00:00
syncookies.c ipv6: add complete rcu protection around np->opt 2015-12-18 16:06:24 +00:00
sysctl_net_ipv6.c net: add a sysctl to reflect the fwmark on replies 2014-05-13 18:35:08 -04:00
tcp_ipv6.c dccp/tcp: fix routing redirect race 2017-07-18 18:40:12 +01:00
tcpv6_offload.c net-gre-gro: Fix a bug that breaks the forwarding path 2014-07-16 14:45:26 -07:00
tunnel6.c ipv6: fix tunnel error handling 2015-12-13 17:49:43 +00:00
udp.c udp: prevent skbs lingering in tunnel socket queues 2017-03-16 02:27:17 +00:00
udp_impl.h net: ipv4/ipv6: Remove extern from function prototypes 2013-10-19 19:12:11 -04:00
udp_offload.c ipv6: Check ip6_find_1stfragopt() return value properly. 2017-06-05 21:17:24 +01:00
udplite.c net: Eliminate no_check from protosw 2014-05-23 16:28:53 -04:00
xfrm6_input.c netfilter: ipv6: use NFPROTO values for NF_HOOK invocation 2010-03-25 16:00:49 +01:00
xfrm6_mode_beet.c ipsec: be careful of non existing mac headers 2012-02-23 16:50:45 -05:00
xfrm6_mode_ro.c ipv6: xfrm: Handle errors reported by xfrm6_find_1stfragopt() 2017-09-15 18:29:54 +01:00
xfrm6_mode_transport.c ipv6: xfrm: Handle errors reported by xfrm6_find_1stfragopt() 2017-09-15 18:29:54 +01:00
xfrm6_mode_tunnel.c ipv6: update skb->csum when CE mark is propagated 2016-01-28 11:06:06 +00:00
xfrm6_output.c ipv6: Fix IPsec pre-encap fragmentation check 2015-11-16 11:27:17 +00:00
xfrm6_policy.c xfrm: dst_entries_init() per-net dst_ops 2016-01-28 11:57:51 +00:00
xfrm6_protocol.c xfrm6: Properly handle unsupported protocols 2014-05-06 07:08:38 +02:00
xfrm6_state.c xfrm: make local error reporting more robust 2013-08-14 13:07:12 +02:00
xfrm6_tunnel.c ipv4/ipv6: Fix FSF address in file headers 2013-12-06 12:37:56 -05:00