linux/include
Kuniyuki Iwashima 69421bf984 udp: Update reuse->has_conns under reuseport_lock.
When we call connect() for a UDP socket in a reuseport group, we have
to update sk->sk_reuseport_cb->has_conns to 1.  Otherwise, the kernel
could select a unconnected socket wrongly for packets sent to the
connected socket.

However, the current way to set has_conns is illegal and possible to
trigger that problem.  reuseport_has_conns() changes has_conns under
rcu_read_lock(), which upgrades the RCU reader to the updater.  Then,
it must do the update under the updater's lock, reuseport_lock, but
it doesn't for now.

For this reason, there is a race below where we fail to set has_conns
resulting in the wrong socket selection.  To avoid the race, let's split
the reader and updater with proper locking.

 cpu1                               cpu2
+----+                             +----+

__ip[46]_datagram_connect()        reuseport_grow()
.                                  .
|- reuseport_has_conns(sk, true)   |- more_reuse = __reuseport_alloc(more_socks_size)
|  .                               |
|  |- rcu_read_lock()
|  |- reuse = rcu_dereference(sk->sk_reuseport_cb)
|  |
|  |                               |  /* reuse->has_conns == 0 here */
|  |                               |- more_reuse->has_conns = reuse->has_conns
|  |- reuse->has_conns = 1         |  /* more_reuse->has_conns SHOULD BE 1 HERE */
|  |                               |
|  |                               |- rcu_assign_pointer(reuse->socks[i]->sk_reuseport_cb,
|  |                               |                     more_reuse)
|  `- rcu_read_unlock()            `- kfree_rcu(reuse, rcu)
|
|- sk->sk_state = TCP_ESTABLISHED

Note the likely(reuse) in reuseport_has_conns_set() is always true,
but we put the test there for ease of review.  [0]

For the record, usually, sk_reuseport_cb is changed under lock_sock().
The only exception is reuseport_grow() & TCP reqsk migration case.

  1) shutdown() TCP listener, which is moved into the latter part of
     reuse->socks[] to migrate reqsk.

  2) New listen() overflows reuse->socks[] and call reuseport_grow().

  3) reuse->max_socks overflows u16 with the new listener.

  4) reuseport_grow() pops the old shutdown()ed listener from the array
     and update its sk->sk_reuseport_cb as NULL without lock_sock().

shutdown()ed TCP sk->sk_reuseport_cb can be changed without lock_sock(),
but, reuseport_has_conns_set() is called only for UDP under lock_sock(),
so likely(reuse) never be false in reuseport_has_conns_set().

[0]: https://lore.kernel.org/netdev/CANn89iLja=eQHbsM_Ta2sQF0tOGU8vAGrh_izRuuHjuO1ouUag@mail.gmail.com/

Fixes: acdcecc612 ("udp: correct reuseport selection with connected sockets")
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://lore.kernel.org/r/20221014182625.89913-1-kuniyu@amazon.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2022-10-18 10:17:18 +02:00
..
acpi platform-drivers-x86 for v6.1-1 2022-10-05 10:38:24 -07:00
asm-generic - hfs and hfsplus kmap API modernization from Fabio Francesco 2022-10-12 11:00:22 -07:00
clocksource
crypto crypto: scatterwalk - Remove unused inline function scatterwalk_aligned() 2022-09-30 13:59:13 +08:00
drm Driver core changes for 6.1-rc1 2022-10-07 17:04:10 -07:00
dt-bindings These are the pin control changes for the v6.1 kernel cycle: 2022-10-11 10:59:59 -07:00
keys
kunit kunit: declare kunit_assert structs as const 2022-10-07 10:19:18 -06:00
kvm
linux net: phylink: add mac_managed_pm in phylink_config structure 2022-10-15 11:51:51 +01:00
math-emu
media USB/Thunderbolt changes for 6.1-rc1 2022-10-07 16:48:26 -07:00
memory
misc
net udp: Update reuse->has_conns under reuseport_lock. 2022-10-18 10:17:18 +02:00
pcmcia
ras
rdma
rv
scsi SCSI misc on 20221007 2022-10-07 12:33:18 -07:00
soc These are the pin control changes for the v6.1 kernel cycle: 2022-10-11 10:59:59 -07:00
sound ASoC: Updates for v6.1 2022-10-03 16:30:42 +02:00
target
trace f2fs-for-6.1-rc1 2022-10-10 20:28:41 -07:00
uapi VFIO updates for v6.1-rc1 2022-10-12 14:46:48 -07:00
ufs SCSI misc on 20221007 2022-10-07 12:33:18 -07:00
vdso
video
xen xen/virtio: enable grant based virtio on x86 2022-10-10 14:31:26 +02:00