summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_usrreq.c
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2004-04-04 20:14:55 +0000
committerpjd <pjd@FreeBSD.org>2004-04-04 20:14:55 +0000
commit2e6142d4d93140acd5fb604c6bec6cc22241afe0 (patch)
tree8cec7a6640b29bad2a5ae1144c74f31d41b06d2a /sys/netinet/tcp_usrreq.c
parentb9ea41bd9ea2a78e248851f2c9d6bbf97c4691ce (diff)
downloadFreeBSD-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!
Diffstat (limited to 'sys/netinet/tcp_usrreq.c')
-rw-r--r--sys/netinet/tcp_usrreq.c63
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;
OpenPOWER on IntegriCloud