Skip to content

Commit

Permalink
Improve locking for notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
tuexen committed Sep 8, 2023
1 parent 3e0636a commit 61de530
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 57 deletions.
12 changes: 4 additions & 8 deletions usrsctplib/netinet/sctp_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -1731,13 +1731,9 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
struct sctp_authkey_event *auth;
struct sctp_queued_to_read *control;

if ((stcb == NULL) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
/* If the socket is gone we are out of here */
return;
}
KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_AUTHEVNT))
/* event not enabled */
Expand Down Expand Up @@ -1782,7 +1778,7 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, so_locked);
SCTP_READ_LOCK_HELD, so_locked);
}

/*-
Expand Down
132 changes: 83 additions & 49 deletions usrsctplib/netinet/sctputil.c
Original file line number Diff line number Diff line change
Expand Up @@ -3255,10 +3255,11 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
("sctp_notify_assoc_change: ABORT chunk provided for local termination"));
KASSERT(!from_peer || !timedout,
("sctp_notify_assoc_change: timeouts can only be local"));
if (stcb == NULL) {
return;
}
KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
inp = stcb->sctp_ep;
SCTP_INP_READ_LOCK_ASSERT(inp);

if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
notif_len = (unsigned int)sizeof(struct sctp_assoc_change);
if (abort != NULL) {
Expand Down Expand Up @@ -3339,7 +3340,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
control->tail_mbuf = m_notify;
sctp_add_to_readq(inp, stcb, control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, so_locked);
SCTP_READ_LOCK_HELD, so_locked);
} else {
sctp_m_freem(m_notify);
}
Expand Down Expand Up @@ -3409,11 +3410,15 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
struct sctp_paddr_change *spc;
struct sctp_queued_to_read *control;

if ((stcb == NULL) ||
sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT)) {
KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT)) {
/* event not enabled */
return;
}

m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_paddr_change), 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL)
return;
Expand Down Expand Up @@ -3497,7 +3502,7 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, so_locked);
SCTP_READ_LOCK_HELD, so_locked);
}

static void
Expand All @@ -3511,9 +3516,12 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
struct sctp_chunkhdr *chkhdr;
int notifhdr_len, chk_len, chkhdr_len, padding_len, payload_len;

if ((stcb == NULL) ||
(sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) {
KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
/* event not enabled */
return;
}
Expand Down Expand Up @@ -3626,7 +3634,7 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, so_locked);
SCTP_READ_LOCK_HELD, so_locked);
}

static void
Expand All @@ -3639,12 +3647,16 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
struct sctp_queued_to_read *control;
int notifhdr_len;

if ((stcb == NULL) ||
(sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) {
KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
/* event not enabled */
return;
}

if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
notifhdr_len = sizeof(struct sctp_send_failed_event);
} else {
Expand Down Expand Up @@ -3722,7 +3734,7 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, so_locked);
SCTP_READ_LOCK_HELD, so_locked);
}

static void
Expand All @@ -3732,8 +3744,11 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb, int so_locked)
struct sctp_adaptation_event *sai;
struct sctp_queued_to_read *control;

if ((stcb == NULL) ||
sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT)) {
KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT)) {
/* event not enabled */
return;
}
Expand Down Expand Up @@ -3769,7 +3784,7 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb, int so_locked)
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, so_locked);
SCTP_READ_LOCK_HELD, so_locked);
}

static void
Expand All @@ -3782,15 +3797,16 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
struct sctp_queued_to_read *control;
struct sockbuf *sb;

if ((stcb == NULL) ||
sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_PDAPIEVNT)) {
KASSERT(aborted_control != NULL, ("aborted_control is NULL"));
KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_PDAPIEVNT)) {
/* event not enabled */
return;
}

KASSERT(aborted_control != NULL, ("aborted_control is NULL"));
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_pdapi_event), 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL)
/* no space left */
Expand Down Expand Up @@ -3864,6 +3880,10 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb, int so_locked)
struct sctp_shutdown_event *sse;
struct sctp_queued_to_read *control;

KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

/*
* For TCP model AND UDP connected sockets we will send an error up
* when an SHUTDOWN completes
Expand All @@ -3890,6 +3910,7 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb, int so_locked)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}

if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT)) {
/* event not enabled */
return;
Expand Down Expand Up @@ -3924,7 +3945,7 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb, int so_locked)
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, so_locked);
SCTP_READ_LOCK_HELD, so_locked);
}

static void
Expand All @@ -3934,8 +3955,11 @@ sctp_notify_sender_dry_event(struct sctp_tcb *stcb, int so_locked)
struct sctp_sender_dry_event *event;
struct sctp_queued_to_read *control;

if ((stcb == NULL) ||
sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DRYEVNT)) {
KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DRYEVNT)) {
/* event not enabled */
return;
}
Expand Down Expand Up @@ -3971,7 +3995,7 @@ sctp_notify_sender_dry_event(struct sctp_tcb *stcb, int so_locked)
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, so_locked);
SCTP_READ_LOCK_HELD, so_locked);
}

static void
Expand All @@ -3981,13 +4005,10 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, int flag, int so_locked)
struct sctp_queued_to_read *control;
struct sctp_stream_change_event *stradd;

if ((stcb == NULL) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
/* If the socket is gone we are out of here. */
return;
}
KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT)) {
/* event not enabled */
return;
Expand Down Expand Up @@ -4034,7 +4055,7 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, int flag, int so_locked)
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, so_locked);
SCTP_READ_LOCK_HELD, so_locked);
}

static void
Expand All @@ -4044,13 +4065,10 @@ sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, int flag, int so_locked)
struct sctp_queued_to_read *control;
struct sctp_assoc_reset_event *strasoc;

if ((stcb == NULL) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
/* If the socket is gone we are out of here. */
return;
}
KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT)) {
/* event not enabled */
return;
Expand Down Expand Up @@ -4091,7 +4109,7 @@ sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, int flag, int so_locked)
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, so_locked);
SCTP_READ_LOCK_HELD, so_locked);
}

static void
Expand All @@ -4103,8 +4121,11 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
struct sctp_stream_reset_event *strreset;
int len;

if ((stcb == NULL) ||
(sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT))) {
KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT)) {
/* event not enabled */
return;
}
Expand Down Expand Up @@ -4155,7 +4176,7 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
SCTP_READ_LOCK_HELD, so_locked);
}

static void
Expand All @@ -4168,10 +4189,14 @@ sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error,
unsigned int notif_len;
uint16_t chunk_len;

if ((stcb == NULL) ||
sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) {
KASSERT(stcb != NULL, ("stcb == NULL"));
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_INP_READ_LOCK_ASSERT(stcb->sctp_ep);

if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) {
return;
}

if (chunk != NULL) {
chunk_len = ntohs(chunk->ch.chunk_length);
/*
Expand Down Expand Up @@ -4217,7 +4242,7 @@ sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error,
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb, control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, so_locked);
SCTP_READ_LOCK_HELD, so_locked);
} else {
sctp_m_freem(m_notify);
}
Expand Down Expand Up @@ -4253,9 +4278,15 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
return;
}
}
if (notification != SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION) {
SCTP_INP_READ_LOCK(inp);
}
SCTP_INP_READ_LOCK_ASSERT(inp);

if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ)) {
SCTP_INP_READ_UNLOCK(inp);
return;
}

Expand Down Expand Up @@ -4419,6 +4450,9 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
__func__, notification, notification);
break;
}
if (notification != SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION) {
SCTP_INP_READ_UNLOCK(inp);
}
}

void
Expand Down

0 comments on commit 61de530

Please sign in to comment.