Reproducable panic in in6_pcbbind
Olivier Houchard
cognet at ci0.org
Wed May 21 06:45:43 PDT 2003
On Wed, May 21, 2003 at 08:40:11AM -0500, Craig Boston wrote:
> > I experienced the same kgdb trace last manth. I found the crashdump
> > lied about where the trap occured. What DDB prints? If the true trap
> > point is at in6_pcbbind() in netinet6/in6_pcb.c, the problem may be
> > same to kern/50621.
>
> This may be the same problem. It happens if I disconnect and quickly
> reconnect the ssh session (causing ssh to open a listener socket on
> ::1). I thought it might be related to TIME_WAIT, and kern/50621 seems
> to point to that as well.
>
> I do have a serial console hooked up, so as soon as I get a moment when
> I can remount everything read-only I'll try to trigger the bug and see
> what DDB says.
>
> Craig
Hi,
I had the same problem, and the attached patch should fix it, although
I'm not sure of how right it is.
Cheers,
Olivier
-------------- next part --------------
Index: in6_pcb.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/in6_pcb.c,v
retrieving revision 1.36
diff -u -p -r1.36 in6_pcb.c
--- in6_pcb.c 19 Feb 2003 22:32:42 -0000 1.36
+++ in6_pcb.c 14 May 2003 05:17:39 -0000
@@ -198,12 +198,18 @@ in6_pcbbind(inp, nam, td)
t = in6_pcblookup_local(pcbinfo,
&sin6->sin6_addr, lport,
INPLOOKUP_WILDCARD);
- if (t &&
+ 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 &&
(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
- !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
- (t->inp_socket->so_options &
- SO_REUSEPORT) == 0) &&
- (so->so_cred->cr_uid !=
+ !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
+ (t->inp_socket->so_options & SO_REUSEPORT)
+ == 0) && (so->so_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid))
return (EADDRINUSE);
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
@@ -214,7 +220,17 @@ in6_pcbbind(inp, nam, td)
t = in_pcblookup_local(pcbinfo,
sin.sin_addr, lport,
INPLOOKUP_WILDCARD);
- if (t &&
+ 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 &&
(so->so_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid) &&
(ntohl(t->inp_laddr.s_addr) !=
@@ -226,7 +242,9 @@ in6_pcbbind(inp, nam, td)
}
t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
lport, wild);
- if (t && (reuseport & t->inp_socket->so_options) == 0)
+ if (t && (reuseport & ((t->inp_vflag & INP_TIMEWAIT) ?
+ intotw(t)->tw_so_options :
+ t->inp_socket->so_options)) == 0)
return(EADDRINUSE);
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
@@ -235,12 +253,19 @@ in6_pcbbind(inp, nam, td)
in6_sin6_2_sin(&sin, sin6);
t = in_pcblookup_local(pcbinfo, sin.sin_addr,
lport, wild);
- if (t &&
- (reuseport & t->inp_socket->so_options)
- == 0 &&
- (ntohl(t->inp_laddr.s_addr)
- != INADDR_ANY ||
- INP_SOCKAF(so) ==
+ if (t && t->inp_vflag & INP_TIMEWAIT) {
+ if ((reuseport &
+ intotw(t)->tw_so_options) == 0 &&
+ (ntohl(t->inp_laddr.s_addr) !=
+ INADDR_ANY || ((inp->inp_vflag &
+ INP_IPV6PROTO) ==
+ (t->inp_vflag & INP_IPV6PROTO))))
+ return (EADDRINUSE);
+ }
+ else if (t &&
+ (reuseport & t->inp_socket->so_options)
+ == 0 && (ntohl(t->inp_laddr.s_addr) !=
+ INADDR_ANY || INP_SOCKAF(so) ==
INP_SOCKAF(t->inp_socket)))
return (EADDRINUSE);
}
More information about the freebsd-current
mailing list