linux/net/ipv6
Martin KaFai Lau 7ece54a60e ipv6: Fix SO_REUSEPORT UDP socket with implicit sk_ipv6only
If a sk_v6_rcv_saddr is !IPV6_ADDR_ANY and !IPV6_ADDR_MAPPED, it
implicitly implies it is an ipv6only socket.  However, in inet6_bind(),
this addr_type checking and setting sk->sk_ipv6only to 1 are only done
after sk->sk_prot->get_port(sk, snum) has been completed successfully.

This inconsistency between sk_v6_rcv_saddr and sk_ipv6only confuses
the 'get_port()'.

In particular, when binding SO_REUSEPORT UDP sockets,
udp_reuseport_add_sock(sk,...) is called.  udp_reuseport_add_sock()
checks "ipv6_only_sock(sk2) == ipv6_only_sock(sk)" before adding sk to
sk2->sk_reuseport_cb.  In this case, ipv6_only_sock(sk2) could be
1 while ipv6_only_sock(sk) is still 0 here.  The end result is,
reuseport_alloc(sk) is called instead of adding sk to the existing
sk2->sk_reuseport_cb.

It can be reproduced by binding two SO_REUSEPORT UDP sockets on an
IPv6 address (!ANY and !MAPPED).  Only one of the socket will
receive packet.

The fix is to set the implicit sk_ipv6only before calling get_port().
The original sk_ipv6only has to be saved such that it can be restored
in case get_port() failed.  The situation is similar to the
inet_reset_saddr(sk) after get_port() has failed.

Thanks to Calvin Owens <calvinowens@fb.com> who created an easy
reproduction which leads to a fix.

Fixes: e32ea7e747 ("soreuseport: fast reuseport UDP socket selection")
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-01-29 11:37:40 -05:00
..
ila rhashtable: Change rhashtable_walk_start to return void 2017-12-11 09:58:38 -05:00
netfilter netfilter: remove messages print and boot/module load time 2018-01-19 18:39:49 +01:00
addrconf_core.c net: ipv6: Make inet6addr_validator a blocking notifier 2017-10-20 13:15:07 +01:00
addrconf.c net: delete /proc THIS_MODULE references 2018-01-16 15:01:33 -05:00
addrlabel.c rtnetlink: ipv6: convert remaining users to rtnl_register_module 2017-12-04 13:35:36 -05:00
af_inet6.c ipv6: Fix SO_REUSEPORT UDP socket with implicit sk_ipv6only 2018-01-29 11:37:40 -05:00
ah6.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next 2017-11-15 11:56:19 -08:00
anycast.c net: delete /proc THIS_MODULE references 2018-01-16 15:01:33 -05:00
calipso.c net, calipso: convert calipso_doi.refcount from atomic_t to refcount_t 2017-07-04 22:35:16 +01:00
datagram.c net: ipv6: Allow connect to linklocal address from socket bound to vrf 2018-01-08 14:11:18 -05:00
esp6_offload.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2018-01-23 13:51:56 -05:00
esp6.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2018-01-17 00:10:42 -05:00
exthdrs_core.c net: ipv6: remove unused code in ipv6_find_hdr() 2017-10-05 21:53:02 -07:00
exthdrs_offload.c
exthdrs.c ipv6: sr: fix TLVs not being copied using setsockopt 2018-01-10 16:03:55 -05:00
fib6_notifier.c net: Add module reference to FIB notifiers 2017-09-01 20:33:42 -07:00
fib6_rules.c net: ipv6: avoid overhead when no custom FIB rules are installed 2017-08-08 21:40:08 -07:00
fou6.c
icmp.c ipv6: mark expected switch fall-throughs 2017-10-18 14:13:08 +01:00
inet6_connection_sock.c
inet6_hashtables.c inet: Add a 2nd listener hashtable (port+addr) 2017-12-03 10:18:28 -05:00
ip6_checksum.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
ip6_fib.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2018-01-19 22:59:33 -05:00
ip6_flowlabel.c net: delete /proc THIS_MODULE references 2018-01-16 15:01:33 -05:00
ip6_gre.c net: erspan: use bitfield instead of mask and offset 2018-01-25 21:39:43 -05:00
ip6_icmp.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
ip6_input.c
ip6_offload.c gso: fix payload length when gso_size is zero 2017-10-08 10:12:15 -07:00
ip6_offload.h
ip6_output.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2018-01-24 23:44:15 -05:00
ip6_tunnel.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2018-01-29 10:15:51 -05:00
ip6_udp_tunnel.c
ip6_vti.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2018-01-29 10:15:51 -05:00
ip6mr.c net: delete /proc THIS_MODULE references 2018-01-16 15:01:33 -05:00
ipcomp6.c
ipv6_sockglue.c ipv6: Fix getsockopt() for sockets with default IPV6_AUTOFLOWLABEL 2018-01-23 19:53:24 -05:00
Kconfig ipv6: sr: add helper functions for seg6local 2017-08-25 17:10:24 -07:00
Makefile License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
mcast_snoop.c
mcast.c ipv6: mcast: remove dead code 2018-01-19 14:17:44 -05:00
mip6.c
ndisc.c net: ipv6: sysctl to specify IPv6 ND traffic class 2017-11-11 15:13:02 +09:00
netfilter.c netfilter: remove struct nf_afinfo and its helper functions 2018-01-08 18:11:02 +01:00
output_core.c net: accept UFO datagrams from tuntap and packet 2017-11-24 01:37:35 +09:00
ping.c net/ipv6: Convert icmpv6_push_pending_frames to void 2017-10-06 09:52:31 -07:00
proc.c net: delete /proc THIS_MODULE references 2018-01-16 15:01:33 -05:00
protocol.c
raw.c net: delete /proc THIS_MODULE references 2018-01-16 15:01:33 -05:00
reassembly.c inet: frags: Convert timers to use timer_setup() 2017-10-18 12:39:55 +01:00
route.c net/ipv6: Add support for onlink flag 2018-01-26 10:16:43 -05:00
seg6_hmac.c ipv6: sr: Use ARRAY_SIZE macro 2017-09-01 18:35:23 -07:00
seg6_iptunnel.c ipv6: sr: add support for encapsulation of L2 frames 2017-08-25 17:10:23 -07:00
seg6_local.c ipv6: use ARRAY_SIZE for array sizing calculation on array seg6_action_table 2018-01-09 11:40:46 -05:00
seg6.c rhashtable: Change rhashtable_walk_start to return void 2017-12-11 09:58:38 -05:00
sit.c net: don't call update_pmtu unconditionally 2018-01-25 16:27:34 -05:00
syncookies.c tcp: Namespace-ify sysctl_tcp_workaround_signed_windows 2017-10-28 19:24:38 +09:00
sysctl_net_ipv6.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2017-11-04 09:26:51 +09:00
tcp_ipv6.c net: delete /proc THIS_MODULE references 2018-01-16 15:01:33 -05:00
tcpv6_offload.c gso: validate gso_type in GSO handlers 2018-01-22 16:01:30 -05:00
tunnel6.c
udp_impl.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
udp_offload.c gso: validate gso_type in GSO handlers 2018-01-22 16:01:30 -05:00
udp.c net: delete /proc THIS_MODULE references 2018-01-16 15:01:33 -05:00
udplite.c net: delete /proc THIS_MODULE references 2018-01-16 15:01:33 -05:00
xfrm6_input.c xfrm: Reinject transport-mode packets through tasklet 2017-12-19 08:23:21 +01:00
xfrm6_mode_beet.c networking: make skb_pull & friends return void pointers 2017-06-16 11:48:39 -04:00
xfrm6_mode_ro.c
xfrm6_mode_transport.c
xfrm6_mode_tunnel.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2018-01-24 23:44:15 -05:00
xfrm6_output.c
xfrm6_policy.c net: Create and use new helper xfrm_dst_child(). 2017-11-30 09:54:25 -05:00
xfrm6_protocol.c
xfrm6_state.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
xfrm6_tunnel.c xfrm6_tunnel: exit_net cleanup check added 2017-11-14 15:46:17 +09:00