* Fix a bug where the length of the ASCONF-ACK was calculated wrong due
to using an uninitialized variable. * Fix a bug where a NULL pointer was dereferenced when interfaces come and go at a high rate. * Fix a bug where inps where not deregistered from iterators. * Fix a race condition in freeing an association. * Fix a refcount problem related to the iterator. Each of the above bug results in a panic. It shows up when interfaces come and go at a high rate. Obtained from: rrs (partly) MFC after: 3 days
This commit is contained in:
parent
7824be8be0
commit
9afd287a77
@ -826,6 +826,7 @@ send_reply:
|
|||||||
ack->serial_number = serial_num;
|
ack->serial_number = serial_num;
|
||||||
ack->last_sent_to = NULL;
|
ack->last_sent_to = NULL;
|
||||||
ack->data = m_ack;
|
ack->data = m_ack;
|
||||||
|
ack->len = 0;
|
||||||
n = m_ack;
|
n = m_ack;
|
||||||
while (n) {
|
while (n) {
|
||||||
ack->len += SCTP_BUF_LEN(n);
|
ack->len += SCTP_BUF_LEN(n);
|
||||||
@ -1025,7 +1026,8 @@ sctp_asconf_nets_cleanup(struct sctp_tcb *stcb, struct sctp_ifn *ifn)
|
|||||||
* address.
|
* address.
|
||||||
*/
|
*/
|
||||||
if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro) &&
|
if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro) &&
|
||||||
SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index) {
|
((ifn == NULL) ||
|
||||||
|
(SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index))) {
|
||||||
/* clear any cached route */
|
/* clear any cached route */
|
||||||
RTFREE(net->ro.ro_rt);
|
RTFREE(net->ro.ro_rt);
|
||||||
net->ro.ro_rt = NULL;
|
net->ro.ro_rt = NULL;
|
||||||
|
@ -3074,6 +3074,9 @@ sctp_iterator_inp_being_freed(struct sctp_inpcb *inp)
|
|||||||
SCTP_FREE(it, SCTP_M_ITER);
|
SCTP_FREE(it, SCTP_M_ITER);
|
||||||
} else {
|
} else {
|
||||||
it->inp = LIST_NEXT(it->inp, sctp_list);
|
it->inp = LIST_NEXT(it->inp, sctp_list);
|
||||||
|
if (it->inp) {
|
||||||
|
SCTP_INP_INCR_REF(it->inp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* When its put in the refcnt is incremented so decr
|
* When its put in the refcnt is incremented so decr
|
||||||
@ -3114,17 +3117,10 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
|
|||||||
#ifdef SCTP_LOG_CLOSING
|
#ifdef SCTP_LOG_CLOSING
|
||||||
sctp_log_closing(inp, NULL, 0);
|
sctp_log_closing(inp, NULL, 0);
|
||||||
#endif
|
#endif
|
||||||
if (from == SCTP_CALLED_AFTER_CMPSET_OFCLOSE) {
|
SCTP_ITERATOR_LOCK();
|
||||||
/*
|
/* mark any iterators on the list or being processed */
|
||||||
* Once we are in we can remove the flag from = 1 is only
|
sctp_iterator_inp_being_freed(inp);
|
||||||
* passed from the actual closing routines that are called
|
SCTP_ITERATOR_UNLOCK();
|
||||||
* via the sockets layer.
|
|
||||||
*/
|
|
||||||
SCTP_ITERATOR_LOCK();
|
|
||||||
/* mark any iterators on the list or being processed */
|
|
||||||
sctp_iterator_inp_being_freed(inp);
|
|
||||||
SCTP_ITERATOR_UNLOCK();
|
|
||||||
}
|
|
||||||
so = inp->sctp_socket;
|
so = inp->sctp_socket;
|
||||||
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
|
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
|
||||||
/* been here before.. eeks.. get out of here */
|
/* been here before.. eeks.. get out of here */
|
||||||
@ -4637,7 +4633,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
|||||||
atomic_add_int(&stcb->asoc.refcnt, 1);
|
atomic_add_int(&stcb->asoc.refcnt, 1);
|
||||||
|
|
||||||
SCTP_TCB_UNLOCK(stcb);
|
SCTP_TCB_UNLOCK(stcb);
|
||||||
|
|
||||||
SCTP_INP_INFO_WLOCK();
|
SCTP_INP_INFO_WLOCK();
|
||||||
SCTP_INP_WLOCK(inp);
|
SCTP_INP_WLOCK(inp);
|
||||||
SCTP_TCB_LOCK(stcb);
|
SCTP_TCB_LOCK(stcb);
|
||||||
@ -4680,6 +4675,16 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
|||||||
if (from_inpcbfree == SCTP_NORMAL_PROC) {
|
if (from_inpcbfree == SCTP_NORMAL_PROC) {
|
||||||
atomic_add_int(&stcb->asoc.refcnt, -1);
|
atomic_add_int(&stcb->asoc.refcnt, -1);
|
||||||
}
|
}
|
||||||
|
if (stcb->asoc.refcnt) {
|
||||||
|
stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
|
||||||
|
sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
|
||||||
|
if (from_inpcbfree == SCTP_NORMAL_PROC) {
|
||||||
|
SCTP_INP_INFO_WUNLOCK();
|
||||||
|
SCTP_INP_WUNLOCK(inp);
|
||||||
|
}
|
||||||
|
SCTP_TCB_UNLOCK(stcb);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
asoc->state = 0;
|
asoc->state = 0;
|
||||||
if (inp->sctp_tcbhash) {
|
if (inp->sctp_tcbhash) {
|
||||||
LIST_REMOVE(stcb, sctp_tcbhash);
|
LIST_REMOVE(stcb, sctp_tcbhash);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user