HomeFreeBSD

Simplify unix socket connection peer locking.

Description

Simplify unix socket connection peer locking.

unp_pcb_owned_lock2() has some sharp edges and forces callers to deal
with a bunch of cases. Simplify it:

  • Rename to unp_pcb_lock_peer().
  • Return the connected peer instead of forcing callers to load it beforehand.
  • Handle self-connected sockets.
  • In unp_connectat(), just lock the accept socket directly. It should not be possible for the nascent socket to participate in any other lock orders.
  • Get rid of connect_internal(). It does not provide any useful checking anymore.
  • Block in unp_connectat() when a different thread is concurrently attempting to lock both sides of a connection. This provides simpler semantics for callers of unp_pcb_lock_peer().
  • Make unp_connectat() return EISCONN if the socket is already connected. This fixes a race[1] when multiple threads attempt to connect() to different addresses using the same datagram socket. Upper layers will disconnect a connected datagram socket before calling the protocol connect's method, but there is no synchronization between this and protocol-layer code.

Reported by: syzkaller [1]
Tested by: pho
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D26299

Details