-Fixes first of all the getcred on IPv6 and V4. The
copy's were incorrect and so was the locking. -A bug was also found that would create a race and panic when an abort arrived on a socket being read from. -Also fix the reader to get MSG_TRUNC when a partial delivery is aborted. -Also addresses a couple of coverity caught error path memory leaks and a couple of other valid complaints Approved by: gnn
This commit is contained in:
parent
46bcfc7375
commit
03b0b02163
@ -1274,6 +1274,7 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa,
|
||||
sizeof(struct in_addr));
|
||||
} else {
|
||||
/* invalid family! */
|
||||
SCTP_FREE(aa);
|
||||
return (-1);
|
||||
}
|
||||
aa->sent = 0; /* clear sent flag */
|
||||
|
@ -257,6 +257,7 @@ sctp_build_readq_entry(struct sctp_tcb *stcb,
|
||||
read_queue_e->port_from = stcb->rport;
|
||||
read_queue_e->do_not_ref_stcb = 0;
|
||||
read_queue_e->end_added = 0;
|
||||
read_queue_e->pdapi_aborted = 0;
|
||||
failed_build:
|
||||
return (read_queue_e);
|
||||
}
|
||||
@ -293,6 +294,7 @@ sctp_build_readq_entry_chk(struct sctp_tcb *stcb,
|
||||
read_queue_e->port_from = stcb->rport;
|
||||
read_queue_e->do_not_ref_stcb = 0;
|
||||
read_queue_e->end_added = 0;
|
||||
read_queue_e->pdapi_aborted = 0;
|
||||
failed_build:
|
||||
return (read_queue_e);
|
||||
}
|
||||
|
@ -582,6 +582,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
|
||||
*/
|
||||
SCTP_INP_READ_LOCK(stcb->sctp_ep);
|
||||
stcb->asoc.control_pdapi->end_added = 1;
|
||||
stcb->asoc.control_pdapi->pdapi_aborted = 1;
|
||||
if (stcb->asoc.control_pdapi->tail_mbuf) {
|
||||
stcb->asoc.control_pdapi->tail_mbuf->m_flags |= M_EOR;
|
||||
}
|
||||
@ -673,6 +674,7 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
|
||||
*/
|
||||
SCTP_INP_READ_LOCK(stcb->sctp_ep);
|
||||
stcb->asoc.control_pdapi->end_added = 1;
|
||||
stcb->asoc.control_pdapi->pdapi_aborted = 1;
|
||||
if (stcb->asoc.control_pdapi->tail_mbuf) {
|
||||
stcb->asoc.control_pdapi->tail_mbuf->m_flags |= M_EOR;
|
||||
}
|
||||
@ -1823,6 +1825,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
|
||||
sig = (uint8_t *) sctp_m_getptr(m_sig, 0, SCTP_SIGNATURE_SIZE, (uint8_t *) & tmp_sig);
|
||||
if (sig == NULL) {
|
||||
/* couldn't find signature */
|
||||
sctp_m_freem(m_sig);
|
||||
return (NULL);
|
||||
}
|
||||
/* compare the received digest with the computed digest */
|
||||
|
@ -9870,6 +9870,9 @@ sctp_lower_sosend(struct socket *so,
|
||||
}
|
||||
mm = sctp_copy_resume(sp, uio, srcv, max_len, user_marks_eor, &error, &sndout, &new_tail);
|
||||
if ((mm == NULL) || error) {
|
||||
if (mm) {
|
||||
sctp_m_freem(mm);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
/* Update the mbuf and count */
|
||||
|
@ -1769,8 +1769,10 @@ sctp_inpcb_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
|
||||
*/
|
||||
/* got to be root to get at low ports */
|
||||
if (ntohs(lport) < IPPORT_RESERVED) {
|
||||
if (p && (error = priv_check(p,
|
||||
PRIV_NETINET_RESERVEDPORT))) {
|
||||
if (p && (error =
|
||||
priv_check(p,
|
||||
PRIV_NETINET_RESERVEDPORT)
|
||||
)) {
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
SCTP_INP_INFO_WUNLOCK();
|
||||
@ -3290,46 +3292,30 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
if (sq->stcb == stcb) {
|
||||
sq->do_not_ref_stcb = 1;
|
||||
sq->sinfo_cumtsn = stcb->asoc.cumulative_tsn;
|
||||
if ((from_inpcbfree == 0) && so) {
|
||||
/*
|
||||
* Only if we have a socket lock do
|
||||
* we do this
|
||||
*/
|
||||
if ((sq->held_length) ||
|
||||
(sq->end_added == 0) ||
|
||||
((sq->length == 0) && (sq->end_added == 0))) {
|
||||
/* Held for PD-API */
|
||||
sq->held_length = 0;
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT)) {
|
||||
/*
|
||||
* need to change to
|
||||
* PD-API aborted
|
||||
*/
|
||||
stcb->asoc.control_pdapi = sq;
|
||||
sctp_notify_partial_delivery_indication(stcb,
|
||||
SCTP_PARTIAL_DELIVERY_ABORTED, 1);
|
||||
stcb->asoc.control_pdapi = NULL;
|
||||
} else {
|
||||
/*
|
||||
* need to get the
|
||||
* reader to remove
|
||||
* it
|
||||
*/
|
||||
sq->length = 0;
|
||||
if (sq->data) {
|
||||
struct mbuf *m;
|
||||
|
||||
m = sq->data;
|
||||
while (m) {
|
||||
sctp_sbfree(sq, stcb, &stcb->sctp_socket->so_rcv, m);
|
||||
m = sctp_m_free(m);
|
||||
}
|
||||
sq->data = NULL;
|
||||
sq->tail_mbuf = NULL;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If there is no end, there never will be
|
||||
* now.
|
||||
*/
|
||||
if (sq->end_added == 0) {
|
||||
/* Held for PD-API clear that. */
|
||||
sq->pdapi_aborted = 1;
|
||||
sq->held_length = 0;
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT)) {
|
||||
/*
|
||||
* Need to add a PD-API
|
||||
* aborted indication.
|
||||
* Setting the control_pdapi
|
||||
* assures that it will be
|
||||
* added right after this
|
||||
* msg.
|
||||
*/
|
||||
stcb->asoc.control_pdapi = sq;
|
||||
sctp_notify_partial_delivery_indication(stcb,
|
||||
SCTP_PARTIAL_DELIVERY_ABORTED, 1);
|
||||
stcb->asoc.control_pdapi = NULL;
|
||||
}
|
||||
}
|
||||
/* Add an end to wake them */
|
||||
sq->end_added = 1;
|
||||
cnt++;
|
||||
}
|
||||
|
@ -149,16 +149,6 @@ struct sctp_copy_all {
|
||||
int cnt_failed;
|
||||
};
|
||||
|
||||
union sctp_sockstore {
|
||||
#ifdef AF_INET
|
||||
struct sockaddr_in sin;
|
||||
#endif
|
||||
#ifdef AF_INET6
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
struct sockaddr sa;
|
||||
};
|
||||
|
||||
struct sctp_nets {
|
||||
TAILQ_ENTRY(sctp_nets) sctp_next; /* next link */
|
||||
|
||||
@ -371,6 +361,7 @@ struct sctp_queued_to_read { /* sinfo structure Pluse more */
|
||||
uint16_t port_from;
|
||||
uint8_t do_not_ref_stcb;
|
||||
uint8_t end_added;
|
||||
uint8_t pdapi_aborted;
|
||||
};
|
||||
|
||||
/* This data structure will be on the outbound
|
||||
|
@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
typedef uint32_t sctp_assoc_t;
|
||||
|
||||
@ -871,6 +872,17 @@ struct sctpstat {
|
||||
#define SCTP_STAT_DECR_COUNTER64(_x) SCTP_STAT_DECR(_x)
|
||||
#define SCTP_STAT_DECR_GAUGE32(_x) SCTP_STAT_DECR(_x)
|
||||
|
||||
union sctp_sockstore {
|
||||
#ifdef AF_INET
|
||||
struct sockaddr_in sin;
|
||||
#endif
|
||||
#ifdef AF_INET6
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
struct sockaddr sa;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Kernel defined for sctp_send
|
||||
*/
|
||||
|
@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/sctp_asconf.h>
|
||||
#include <netinet/sctp_timer.h>
|
||||
#include <netinet/sctp_auth.h>
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
#include <netkey/key.h>
|
||||
@ -483,11 +484,12 @@ sctp_ctlinput(cmd, sa, vip)
|
||||
static int
|
||||
sctp_getcred(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct xucred xuc;
|
||||
struct sockaddr_in addrs[2];
|
||||
struct sctp_inpcb *inp;
|
||||
struct sctp_nets *net;
|
||||
struct sctp_tcb *stcb;
|
||||
int error, s;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* XXXRW: Other instances of getcred use SUSER_ALLOWJAIL, as socket
|
||||
@ -502,7 +504,6 @@ sctp_getcred(SYSCTL_HANDLER_ARGS)
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
s = splnet();
|
||||
stcb = sctp_findassociation_addr_sa(sintosa(&addrs[0]),
|
||||
sintosa(&addrs[1]),
|
||||
&inp, &net, 1);
|
||||
@ -511,15 +512,29 @@ sctp_getcred(SYSCTL_HANDLER_ARGS)
|
||||
/* reduce ref-count */
|
||||
SCTP_INP_WLOCK(inp);
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
goto cred_can_cont;
|
||||
}
|
||||
error = ENOENT;
|
||||
goto out;
|
||||
}
|
||||
error = SYSCTL_OUT(req, inp->sctp_socket->so_cred, sizeof(struct ucred));
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
/*
|
||||
* We use the write lock here, only since in the error leg we need
|
||||
* it. If we used RLOCK, then we would have to
|
||||
* wlock/decr/unlock/rlock. Which in theory could create a hole.
|
||||
* Better to use higher wlock.
|
||||
*/
|
||||
SCTP_INP_WLOCK(inp);
|
||||
cred_can_cont:
|
||||
error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
|
||||
if (error) {
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
goto out;
|
||||
}
|
||||
cru2x(inp->sctp_socket->so_cred, &xuc);
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
|
||||
out:
|
||||
splx(s);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -3384,6 +3399,7 @@ sctp_optsset(struct socket *so,
|
||||
if (sctp_auth_add_hmacid(hmaclist, (uint16_t) hmacid)) {
|
||||
/* invalid HMACs were found */ ;
|
||||
error = EINVAL;
|
||||
sctp_free_hmaclist(hmaclist);
|
||||
goto sctp_set_hmac_done;
|
||||
}
|
||||
}
|
||||
@ -4655,8 +4671,10 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
|
||||
sin6->sin6_port = ((struct sockaddr_in6 *)&store)->sin6_port;
|
||||
|
||||
sin6->sin6_addr = ((struct sockaddr_in6 *)&store)->sin6_addr;
|
||||
if ((error = sa6_recoverscope(sin6)) != 0)
|
||||
if ((error = sa6_recoverscope(sin6)) != 0) {
|
||||
SCTP_FREE_SONAME(sin6);
|
||||
return (error);
|
||||
}
|
||||
*addr = (struct sockaddr *)sin6;
|
||||
}
|
||||
/* Wake any delayed sleep action */
|
||||
@ -4725,6 +4743,10 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
|
||||
sin_a = (struct sockaddr_in *)&net->ro._l_addr;
|
||||
if (sin_a == NULL)
|
||||
/* this will make coverity happy */
|
||||
continue;
|
||||
|
||||
if (sin_a->sin_family == AF_INET) {
|
||||
fnd = 1;
|
||||
break;
|
||||
|
@ -377,7 +377,12 @@ sctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from)
|
||||
sctp_clog[sctp_cwnd_log_at].time_event = sctp_get_time_of_event();
|
||||
sctp_clog[sctp_cwnd_log_at].from = (uint8_t) from;
|
||||
sctp_clog[sctp_cwnd_log_at].event_type = (uint8_t) SCTP_LOG_LOCK_EVENT;
|
||||
sctp_clog[sctp_cwnd_log_at].x.lock.sock = (void *)inp->sctp_socket;
|
||||
if (inp) {
|
||||
sctp_clog[sctp_cwnd_log_at].x.lock.sock = (void *)inp->sctp_socket;
|
||||
|
||||
} else {
|
||||
sctp_clog[sctp_cwnd_log_at].x.lock.sock = (void *)NULL;
|
||||
}
|
||||
sctp_clog[sctp_cwnd_log_at].x.lock.inp = (void *)inp;
|
||||
if (stcb) {
|
||||
sctp_clog[sctp_cwnd_log_at].x.lock.tcb_lock = mtx_owned(&stcb->tcb_mtx);
|
||||
@ -2575,7 +2580,6 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
|
||||
struct mbuf *m_notify;
|
||||
struct sctp_assoc_change *sac;
|
||||
struct sctp_queued_to_read *control;
|
||||
int locked = 0;
|
||||
|
||||
/*
|
||||
* First if we are are going down dump everything we can to the
|
||||
@ -2589,58 +2593,6 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
|
||||
/* If the socket is gone we are out of here */
|
||||
return;
|
||||
}
|
||||
if ((event == SCTP_COMM_LOST) || (event == SCTP_SHUTDOWN_COMP)) {
|
||||
if (stcb->asoc.control_pdapi) {
|
||||
/*
|
||||
* we were in the middle of a PD-API verify its
|
||||
* there.
|
||||
*/
|
||||
SCTP_INP_READ_LOCK(stcb->sctp_ep);
|
||||
locked = 1;
|
||||
TAILQ_FOREACH(control, &stcb->sctp_ep->read_queue, next) {
|
||||
if (control == stcb->asoc.control_pdapi) {
|
||||
/* Yep its here, notify them */
|
||||
if (event == SCTP_COMM_LOST) {
|
||||
/*
|
||||
* Abort/broken we had a
|
||||
* real PD-API aborted
|
||||
*/
|
||||
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_PDAPIEVNT)) {
|
||||
/*
|
||||
* hmm.. don't want
|
||||
* a notify if
|
||||
* held_lenght is
|
||||
* set,they may be
|
||||
* stuck. clear and
|
||||
* wake.
|
||||
*/
|
||||
if (control->held_length) {
|
||||
control->held_length = 0;
|
||||
control->end_added = 1;
|
||||
}
|
||||
} else {
|
||||
sctp_notify_partial_delivery_indication(stcb, event, 1);
|
||||
|
||||
}
|
||||
} else {
|
||||
/* implicit EOR on EOF */
|
||||
control->held_length = 0;
|
||||
control->end_added = 1;
|
||||
}
|
||||
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
|
||||
locked = 0;
|
||||
/* wake him up */
|
||||
control->do_not_ref_stcb = 1;
|
||||
stcb->asoc.control_pdapi = NULL;
|
||||
sorwakeup(stcb->sctp_socket);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (locked)
|
||||
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
* For TCP model AND UDP connected sockets we will send an error up
|
||||
* when an ABORT comes in.
|
||||
@ -2936,13 +2888,15 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb,
|
||||
&stcb->sctp_socket->so_rcv, 1);
|
||||
}
|
||||
|
||||
/* This always must be called with the read-queue LOCKED in the INP */
|
||||
void
|
||||
sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb,
|
||||
uint32_t error, int no_lock)
|
||||
uint32_t error, int nolock)
|
||||
{
|
||||
struct mbuf *m_notify;
|
||||
struct sctp_pdapi_event *pdapi;
|
||||
struct sctp_queued_to_read *control;
|
||||
struct sockbuf *sb;
|
||||
|
||||
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_PDAPIEVNT))
|
||||
/* event not enabled */
|
||||
@ -2965,62 +2919,44 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb,
|
||||
m_notify->m_pkthdr.rcvif = 0;
|
||||
m_notify->m_len = sizeof(struct sctp_pdapi_event);
|
||||
m_notify->m_next = NULL;
|
||||
|
||||
if (stcb->asoc.control_pdapi != NULL) {
|
||||
/* we will do some substitution */
|
||||
control = stcb->asoc.control_pdapi;
|
||||
if (no_lock == 0)
|
||||
SCTP_INP_READ_LOCK(stcb->sctp_ep);
|
||||
|
||||
if (control->data == NULL) {
|
||||
control->data = control->tail_mbuf = m_notify;
|
||||
control->held_length = 0;
|
||||
control->length = m_notify->m_len;
|
||||
control->end_added = 1;
|
||||
sctp_sballoc(stcb,
|
||||
&stcb->sctp_socket->so_rcv,
|
||||
m_notify);
|
||||
} else if (control->end_added == 0) {
|
||||
struct mbuf *m = NULL;
|
||||
|
||||
m = control->data;
|
||||
while (m) {
|
||||
sctp_sbfree(control, stcb,
|
||||
&stcb->sctp_socket->so_rcv, m);
|
||||
m = sctp_m_free(m);
|
||||
}
|
||||
control->data = NULL;
|
||||
control->length = m_notify->m_len;
|
||||
control->data = control->tail_mbuf = m_notify;
|
||||
control->held_length = 0;
|
||||
control->end_added = 1;
|
||||
sctp_sballoc(stcb, &stcb->sctp_socket->so_rcv, m);
|
||||
} else {
|
||||
/* Hmm .. should not happen */
|
||||
control->end_added = 1;
|
||||
stcb->asoc.control_pdapi = NULL;
|
||||
goto add_to_end;
|
||||
}
|
||||
if (no_lock == 0)
|
||||
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
|
||||
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
m_notify);
|
||||
if (control == NULL) {
|
||||
/* no memory */
|
||||
sctp_m_freem(m_notify);
|
||||
return;
|
||||
}
|
||||
control->length = m_notify->m_len;
|
||||
/* not that we need this */
|
||||
control->tail_mbuf = m_notify;
|
||||
control->held_length = 0;
|
||||
control->length = 0;
|
||||
if (nolock == 0) {
|
||||
SCTP_INP_READ_LOCK(stcb->sctp_ep);
|
||||
}
|
||||
sb = &stcb->sctp_socket->so_rcv;
|
||||
#ifdef SCTP_SB_LOGGING
|
||||
sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, m_notify->m_len);
|
||||
#endif
|
||||
sctp_sballoc(stcb, sb, m_notify);
|
||||
#ifdef SCTP_SB_LOGGING
|
||||
sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0);
|
||||
#endif
|
||||
atomic_add_int(&control->length, m_notify->m_len);
|
||||
control->end_added = 1;
|
||||
if (stcb->asoc.control_pdapi)
|
||||
TAILQ_INSERT_AFTER(&stcb->sctp_ep->read_queue, stcb->asoc.control_pdapi, control, next);
|
||||
else {
|
||||
/* we really should not see this case */
|
||||
TAILQ_INSERT_TAIL(&stcb->sctp_ep->read_queue, control, next);
|
||||
}
|
||||
if (nolock == 0) {
|
||||
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
|
||||
}
|
||||
if (stcb->sctp_ep && stcb->sctp_socket) {
|
||||
/* This should always be the case */
|
||||
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
|
||||
} else {
|
||||
/* append to socket */
|
||||
add_to_end:
|
||||
control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
m_notify);
|
||||
if (control == NULL) {
|
||||
/* no memory */
|
||||
sctp_m_freem(m_notify);
|
||||
return;
|
||||
}
|
||||
control->length = m_notify->m_len;
|
||||
/* not that we need this */
|
||||
control->tail_mbuf = m_notify;
|
||||
sctp_add_to_readq(stcb->sctp_ep, stcb,
|
||||
control,
|
||||
&stcb->sctp_socket->so_rcv, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3150,10 +3086,14 @@ void
|
||||
sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
|
||||
uint32_t error, void *data)
|
||||
{
|
||||
if (stcb == NULL) {
|
||||
/* unlikely but */
|
||||
return;
|
||||
}
|
||||
if ((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)
|
||||
) {
|
||||
) {
|
||||
/* No notifications up when we are in a no socket state */
|
||||
return;
|
||||
}
|
||||
@ -3829,6 +3769,13 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
|
||||
*/
|
||||
struct mbuf *m, *prev = NULL;
|
||||
|
||||
if (inp == NULL) {
|
||||
/* Gak, TSNH!! */
|
||||
#ifdef INVARIENTS
|
||||
panic("Gak, inp NULL on add_to_readq");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
SCTP_INP_READ_LOCK(inp);
|
||||
m = control->data;
|
||||
control->held_length = 0;
|
||||
@ -5032,6 +4979,8 @@ sctp_sorecvmsg(struct socket *so,
|
||||
if (control->end_added == 1) {
|
||||
/* he aborted, or is done i.e.did a shutdown */
|
||||
out_flags |= MSG_EOR;
|
||||
if (control->pdapi_aborted)
|
||||
out_flags |= MSG_TRUNC;
|
||||
goto done_with_control;
|
||||
}
|
||||
if (so->so_rcv.sb_cc > held_length) {
|
||||
@ -5143,6 +5092,8 @@ sctp_sorecvmsg(struct socket *so,
|
||||
* shutdown
|
||||
*/
|
||||
out_flags |= MSG_EOR;
|
||||
if (control->pdapi_aborted)
|
||||
out_flags |= MSG_TRUNC;
|
||||
goto done_with_control;
|
||||
}
|
||||
if (so->so_rcv.sb_cc > held_length) {
|
||||
|
@ -476,11 +476,12 @@ sctp6_ctlinput(cmd, pktdst, d)
|
||||
static int
|
||||
sctp6_getcred(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct xucred xuc;
|
||||
struct sockaddr_in6 addrs[2];
|
||||
struct sctp_inpcb *inp;
|
||||
struct sctp_nets *net;
|
||||
struct sctp_tcb *stcb;
|
||||
int error, s;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* XXXRW: Other instances of getcred use SUSER_ALLOWJAIL, as socket
|
||||
@ -499,26 +500,38 @@ sctp6_getcred(SYSCTL_HANDLER_ARGS)
|
||||
error = SYSCTL_IN(req, addrs, sizeof(addrs));
|
||||
if (error)
|
||||
return (error);
|
||||
s = splnet();
|
||||
|
||||
stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[0]),
|
||||
sin6tosa(&addrs[1]),
|
||||
&inp, &net, 1);
|
||||
if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
|
||||
error = ENOENT;
|
||||
if (inp) {
|
||||
if ((inp != NULL) && (stcb == NULL)) {
|
||||
/* reduce ref-count */
|
||||
SCTP_INP_WLOCK(inp);
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
goto cred_can_cont;
|
||||
}
|
||||
error = ENOENT;
|
||||
goto out;
|
||||
}
|
||||
error = SYSCTL_OUT(req, inp->sctp_socket->so_cred,
|
||||
sizeof(struct ucred));
|
||||
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
/*
|
||||
* We use the write lock here, only since in the error leg we need
|
||||
* it. If we used RLOCK, then we would have to
|
||||
* wlock/decr/unlock/rlock. Which in theory could create a hole.
|
||||
* Better to use higher wlock.
|
||||
*/
|
||||
SCTP_INP_WLOCK(inp);
|
||||
cred_can_cont:
|
||||
error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
|
||||
if (error) {
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
goto out;
|
||||
}
|
||||
cru2x(inp->sctp_socket->so_cred, &xuc);
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
|
||||
out:
|
||||
splx(s);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -1177,6 +1190,10 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
|
||||
sin_a6 = NULL;
|
||||
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
|
||||
sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
|
||||
if (sin_a6 == NULL)
|
||||
/* this will make coverity happy */
|
||||
continue;
|
||||
|
||||
if (sin_a6->sin6_family == AF_INET6) {
|
||||
fnd = 1;
|
||||
break;
|
||||
@ -1217,8 +1234,10 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
|
||||
}
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
/* Scoping things for v6 */
|
||||
if ((error = sa6_recoverscope(sin6)) != 0)
|
||||
if ((error = sa6_recoverscope(sin6)) != 0) {
|
||||
SCTP_FREE_SONAME(sin6);
|
||||
return (error);
|
||||
}
|
||||
(*addr) = (struct sockaddr *)sin6;
|
||||
return (0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user