Re: TIME_WAIT sockets from other users (was Re: bin/65928: [PATCH] stock ftpd uses superuser credentials for active mode sockets)

From: Yar Tikhiy (yar_at_comp.chem.msu.su)
Date: 06/19/04

  • Next message: Roman Kurakin: "if_sppp"
    Date: Sat, 19 Jun 2004 18:56:48 +0400
    To: hackers@freebsd.org, net@freebsd.org
    
    

    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) !=
    _______________________________________________
    freebsd-net@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-net
    To unsubscribe, send any mail to "freebsd-net-unsubscribe@freebsd.org"
    

  • Next message: Roman Kurakin: "if_sppp"

    Relevant Pages