diff options
author | pjd <pjd@FreeBSD.org> | 2004-04-04 20:14:55 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2004-04-04 20:14:55 +0000 |
commit | 2e6142d4d93140acd5fb604c6bec6cc22241afe0 (patch) | |
tree | 8cec7a6640b29bad2a5ae1144c74f31d41b06d2a | |
parent | b9ea41bd9ea2a78e248851f2c9d6bbf97c4691ce (diff) | |
download | FreeBSD-src-2e6142d4d93140acd5fb604c6bec6cc22241afe0.zip FreeBSD-src-2e6142d4d93140acd5fb604c6bec6cc22241afe0.tar.gz |
Fix a panic possibility caused by returning without releasing locks.
It was fixed by moving problemetic checks, as well as checks that
doesn't need locking before locks are acquired.
Submitted by: Ryan Sommers <ryans@gamersimpact.com>
In co-operation with: cperciva, maxim, mlaier, sam
Tested by: submitter (previous patch), me (current patch)
Reviewed by: cperciva, mlaier (previous patch), sam (current patch)
Approved by: sam
Dedicated to: enough!
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 63 |
1 files changed, 26 insertions, 37 deletions
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 2d8f9e7..339a30f 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -238,20 +238,18 @@ tcp_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td) struct sockaddr_in *sinp; const int inirw = INI_WRITE; - COMMON_START(); - + sinp = (struct sockaddr_in *)nam; + if (nam->sa_len != sizeof (*sinp)) + return (EINVAL); /* * Must check for multicast addresses and disallow binding * to them. */ - sinp = (struct sockaddr_in *)nam; - if (nam->sa_len != sizeof (*sinp)) - return (EINVAL); if (sinp->sin_family == AF_INET && - IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { - error = EAFNOSUPPORT; - goto out; - } + IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) + return (EAFNOSUPPORT); + + COMMON_START(); error = in_pcbbind(inp, nam, td->td_ucred); if (error) goto out; @@ -269,20 +267,18 @@ tcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td) struct sockaddr_in6 *sin6p; const int inirw = INI_WRITE; - COMMON_START(); - + sin6p = (struct sockaddr_in6 *)nam; + if (nam->sa_len != sizeof (*sin6p)) + return (EINVAL); /* * Must check for multicast addresses and disallow binding * to them. */ - sin6p = (struct sockaddr_in6 *)nam; - if (nam->sa_len != sizeof (*sin6p)) - return (EINVAL); if (sin6p->sin6_family == AF_INET6 && - IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) { - error = EAFNOSUPPORT; - goto out; - } + IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) + return (EAFNOSUPPORT); + + COMMON_START(); inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { @@ -366,23 +362,19 @@ tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) struct sockaddr_in *sinp; const int inirw = INI_WRITE; - COMMON_START(); - - /* - * Must disallow TCP ``connections'' to multicast addresses. - */ sinp = (struct sockaddr_in *)nam; if (nam->sa_len != sizeof (*sinp)) return (EINVAL); + /* + * Must disallow TCP ``connections'' to multicast addresses. + */ if (sinp->sin_family == AF_INET - && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { - error = EAFNOSUPPORT; - goto out; - } - + && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) + return (EAFNOSUPPORT); if (td && jailed(td->td_ucred)) prison_remote_ip(td->td_ucred, 0, &sinp->sin_addr.s_addr); + COMMON_START(); if ((error = tcp_connect(tp, nam, td)) != 0) goto out; error = tcp_output(tp); @@ -400,20 +392,17 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) struct sockaddr_in6 *sin6p; const int inirw = INI_WRITE; - COMMON_START(); - - /* - * Must disallow TCP ``connections'' to multicast addresses. - */ sin6p = (struct sockaddr_in6 *)nam; if (nam->sa_len != sizeof (*sin6p)) return (EINVAL); + /* + * Must disallow TCP ``connections'' to multicast addresses. + */ if (sin6p->sin6_family == AF_INET6 - && IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) { - error = EAFNOSUPPORT; - goto out; - } + && IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) + return (EAFNOSUPPORT); + COMMON_START(); if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { struct sockaddr_in sin; |