summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/sctp6_usrreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6/sctp6_usrreq.c')
-rw-r--r--sys/netinet6/sctp6_usrreq.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c
index 3483658..8f8b62a 100644
--- a/sys/netinet6/sctp6_usrreq.c
+++ b/sys/netinet6/sctp6_usrreq.c
@@ -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);
}
OpenPOWER on IntegriCloud