Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 19 Jun 2004 18:56:48 +0400
From:      Yar Tikhiy <yar@comp.chem.msu.su>
To:        hackers@freebsd.org, net@freebsd.org
Cc:        Eugene Grosbein <eugen@grosbein.pp.ru>
Subject:   Re: TIME_WAIT sockets from other users (was Re: bin/65928: [PATCH] stock ftpd uses superuser credentials for active mode sockets)
Message-ID:  <20040619145648.GB77898@comp.chem.msu.su>
In-Reply-To: <20040516141658.GA39893@comp.chem.msu.su>
References:  <20040508034514.GA937@grosbein.pp.ru> <Pine.BSF.4.53.0405080636010.66978@e0-0.zab2.int.zabbadoz.net> <20040508132354.GB44214@comp.chem.msu.su> <20040515182157.GB89625@comp.chem.msu.su> <20040516141658.GA39893@comp.chem.msu.su>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, May 16, 2004 at 06:16:58PM +0400, Yar Tikhiy wrote
  in <20040516141658.GA39893@comp.chem.msu.su>:

> Note for the impatient:  This message does not discuss the well-known
> issue of reusing local addresses through setting SO_REUSEADDR.  This
> message is on reusing local addresses occupied by sockets belonging
> to other users.
[...]
> > Attached below is a patch addressing the issue of the inability to
> > reuse a local IP:port couple occupied by an established TCP connection
> > from another user, but by no listeners.  Could anybody with fair
> > understanding of our TCP/IP stack review it please?  Thanks.
[...]
> One more detail to note:
> 
> Currently if another user's socket is in the TIME_WAIT state, it
> still counts as occupying the local IP:port couple.  I cannot see
> the point of such a behaviour.  Restricting bind() is to disallow
> unprivileged port stealth, but how can one steal a connection in
> the TIME_WAIT state?
> 
> For FreeBSD-4 the above patch would take care of this case along
> with established connections, but in CURRENT TIME_WAIT connections
> are a special case since they no longer use full-blown state.
> Therefore, for CURRENT the above patch mutates into the below one.
[...]

Since I've got no feedback on this issue, I have little hope that
someone will pay attention to my next patch ;-)
However, I have no experience with IPv6, so currently I've got
no choice but to offer my patch for your review, friends, so that
some kind person might take a glance at it while I'm exercising
myself over IPv6 ;-)

I made this patch by analogy with the IPv4 one, which is already
in the CURRENT kernel--luckily, the IPv6 code is rather comprehensible.
It addresses the same issue I was talking about a month ago, but
for the IPv6 stack: It enables the non-root reuse of local address:port
tuples occupied by established or TIME_WAIT TCP connections from
other local users, as long as these particular cases have no security
implications a.k.a.  "port theft."

-- 
Yar

Index: in6_pcb.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/in6_pcb.c,v
retrieving revision 1.52
diff -u -p -r1.52 in6_pcb.c
--- in6_pcb.c	12 Jun 2004 20:59:48 -0000	1.52
+++ in6_pcb.c	19 Jun 2004 14:15:14 -0000
@@ -194,14 +194,10 @@ in6_pcbbind(inp, nam, cred)
 				t = in6_pcblookup_local(pcbinfo,
 				    &sin6->sin6_addr, lport,
 				    INPLOOKUP_WILDCARD);
-				if (t && (t->inp_vflag & INP_TIMEWAIT)) {
-					if ((!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
-					    !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
-					    !(intotw(t)->tw_so_options & SO_REUSEPORT))
-					    && so->so_cred->cr_uid != 
-					    intotw(t)->tw_cred->cr_uid)
-						return (EADDRINUSE);
-				} else if (t &&
+				if (t &&
+				    ((t->inp_vflag & INP_TIMEWAIT) == 0) &&
+				    (so->so_type != SOCK_STREAM ||
+				     IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) &&
 				    (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
 			    	     !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
 				     (t->inp_socket->so_options & SO_REUSEPORT) 
@@ -216,17 +212,12 @@ in6_pcbbind(inp, nam, cred)
 					t = in_pcblookup_local(pcbinfo,
 						sin.sin_addr, lport,
 						INPLOOKUP_WILDCARD);
-					if (t && (t->inp_vflag & INP_TIMEWAIT)) {
-						if (so->so_cred->cr_uid !=
-						    intotw(t)->tw_cred->cr_uid &&
-						    (ntohl(t->inp_laddr.s_addr) !=
-						     INADDR_ANY || 
-						     ((inp->inp_vflag & 
-						       INP_IPV6PROTO) == 
-						      (t->inp_vflag & 
-						       INP_IPV6PROTO))))
-					    return (EADDRINUSE);
-					} else if (t && 
+					if (t &&
+					    ((t->inp_vflag &
+					      INP_TIMEWAIT) == 0) &&
+					    (so->so_type != SOCK_STREAM ||
+					     ntohl(t->inp_faddr.s_addr) ==
+					      INADDR_ANY) &&
 					    (so->so_cred->cr_uid !=
 					     t->inp_socket->so_cred->cr_uid) &&
 					    (ntohl(t->inp_laddr.s_addr) !=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040619145648.GB77898>