summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/sctp6_usrreq.c
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2006-11-08 00:21:13 +0000
committerrrs <rrs@FreeBSD.org>2006-11-08 00:21:13 +0000
commit1bedc49b68670bf727f50429a15911323ca540e3 (patch)
treef6f786f609125bed924191c84569dc69cd63afc8 /sys/netinet6/sctp6_usrreq.c
parent0c2fa6c52c1266ecfbf3b99e2c6c0377acac1444 (diff)
downloadFreeBSD-src-1bedc49b68670bf727f50429a15911323ca540e3.zip
FreeBSD-src-1bedc49b68670bf727f50429a15911323ca540e3.tar.gz
-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
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