diff options
author | rrs <rrs@FreeBSD.org> | 2006-11-08 00:21:13 +0000 |
---|---|---|
committer | rrs <rrs@FreeBSD.org> | 2006-11-08 00:21:13 +0000 |
commit | 1bedc49b68670bf727f50429a15911323ca540e3 (patch) | |
tree | f6f786f609125bed924191c84569dc69cd63afc8 /sys/netinet6 | |
parent | 0c2fa6c52c1266ecfbf3b99e2c6c0377acac1444 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/netinet6/sctp6_usrreq.c | 39 |
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); } |