]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
sctp: Tighten up locking around sctp_aloc_assoc()
authorMark Johnston <markj@FreeBSD.org>
Sat, 11 Sep 2021 14:15:21 +0000 (10:15 -0400)
committerMark Johnston <markj@FreeBSD.org>
Sat, 11 Sep 2021 14:15:21 +0000 (10:15 -0400)
commit2d5c48eccd9f29b9df8020bb1c3a8ffda38df37b
tree3c34e084f7a5d72ee035df6fe39dae3e9ad3c361
parent895545d0e6664ad05fefe63ce46eb670be7e4957
sctp: Tighten up locking around sctp_aloc_assoc()

All callers of sctp_aloc_assoc() mark the PCB as connected after a
successful call (for one-to-one-style sockets).  In all cases this is
done without the PCB lock, so the PCB's flags can be corrupted.  We also
do not atomically check whether a one-to-one-style socket is a listening
socket, which violates various assumptions in solisten_proto().

We need to hold the PCB lock across all of sctp_aloc_assoc() to fix
this.  In order to do that without introducing lock order reversals, we
have to hold the global info lock as well.

So:
- Convert sctp_aloc_assoc() so that the inp and info locks are
  consistently held.  It returns with the association lock held, as
  before.
- Fix an apparent bug where we failed to remove an association from a
  global hash if sctp_add_remote_addr() fails.
- sctp_select_a_tag() is called when initializing an association, and it
  acquires the global info lock.  To avoid lock recursion, push locking
  into its callers.
- Introduce sctp_aloc_assoc_connected(), which atomically checks for a
  listening socket and sets SCTP_PCB_FLAGS_CONNECTED.

There is still one edge case in sctp_process_cookie_new() where we do
not update PCB/socket state correctly.

Reviewed by: tuexen
MFC after: 1 week
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D31908
sys/netinet/sctp_input.c
sys/netinet/sctp_output.c
sys/netinet/sctp_pcb.c
sys/netinet/sctp_pcb.h
sys/netinet/sctp_usrreq.c
sys/netinet6/sctp6_usrreq.c