diff options
author | Mark Johnston <markj@FreeBSD.org> | 2021-09-11 14:15:21 +0000 |
---|---|---|
committer | Michael Tuexen <tuexen@FreeBSD.org> | 2022-02-22 22:47:28 +0000 |
commit | aa16c2fcaf1d5e541fc91a66bbba352ba313429c (patch) | |
tree | c91f46d2c1df82b3c82433291496717dfa7de5c7 /sys/netinet/sctp_pcb.h | |
parent | 238e4a1179b0b03bf39bcc4e096f6771d2d82faa (diff) |
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
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D31908
(cherry picked from commit 2d5c48eccd9f29b9df8020bb1c3a8ffda38df37b)
Diffstat (limited to 'sys/netinet/sctp_pcb.h')
-rw-r--r-- | sys/netinet/sctp_pcb.h | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h index a3d0b489eb82..adbecf9bd00f 100644 --- a/sys/netinet/sctp_pcb.h +++ b/sys/netinet/sctp_pcb.h @@ -577,6 +577,10 @@ struct sctp_tcb * sctp_aloc_assoc(struct sctp_inpcb *, struct sockaddr *, int *, uint32_t, uint32_t, uint32_t, uint16_t, uint16_t, struct thread *, int); +struct sctp_tcb * +sctp_aloc_assoc_connected(struct sctp_inpcb *, struct sockaddr *, + int *, uint32_t, uint32_t, uint32_t, uint16_t, uint16_t, + struct thread *, int); int sctp_free_assoc(struct sctp_inpcb *, struct sctp_tcb *, int, int); |