From owner-freebsd-bugs Tue Jul 31 1:30:12 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 3862637B403 for ; Tue, 31 Jul 2001 01:30:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.4/8.11.4) id f6V8U1x89146; Tue, 31 Jul 2001 01:30:01 -0700 (PDT) (envelope-from gnats) Received: from router.tcs.dnsalias.org (ip167-211.fli-ykh.psinet.ne.jp [210.129.167.211]) by hub.freebsd.org (Postfix) with ESMTP id A70C037B403 for ; Tue, 31 Jul 2001 01:22:34 -0700 (PDT) (envelope-from inoue@tcs.dnsalias.org) Received: (from inoue@localhost) by router.tcs.dnsalias.org (8.11.4/3.7Wpl2/01032921) id f6V8QjX45246; Tue, 31 Jul 2001 17:26:45 +0900 (JST) Message-Id: <200107310826.f6V8QjX45246@router.tcs.dnsalias.org> Date: Tue, 31 Jul 2001 17:26:45 +0900 (JST) From: inoue@nd.net.fujitsu.co.jp Reply-To: inoue@nd.net.fujitsu.co.jp To: FreeBSD-gnats-submit@freebsd.org Cc: inoue@nd.net.fujitsu.co.jp X-Send-Pr-Version: 3.113 Subject: kern/29345: freebsd can crash after removing a network card Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >Number: 29345 >Category: kern >Synopsis: freebsd can crash after removing a network card >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Jul 31 01:30:01 PDT 2001 >Closed-Date: >Last-Modified: >Originator: Inoue Yuichi >Release: FreeBSD 5.0-CURRENT-20010729-JPSNAP >Organization: FUJITSU >Environment: FreeBSD dhcp022158141.nd.net.fujitsu.co.jp 5.0-CURRENT-20010729-JPSNAP FreeBSD 5.0-CURRENT-20010729-JPSNAP #1: Tue Jul 31 12:56:22 JST 2001 inoue@dhcp022158141.nd.net.fujitsu.co.jp: /usr/src/sys/i386/compile/GENERIC i386 FreeBSD 4.3-RELEASE >Description: When running aplication joined multicast address, removing network card, and kill aplication. imo_membership[].inm_ifp refer interface pointer after removing interface. When kill aplication, release socket,and imo_membership. imo_membership use already not exist interface pointer. Then, kernel panic. >How-To-Repeat: shell> route6d removing a netword card shell> kill `cat /var/run/route6d` kernel panic >Fix: --- netinet.patch --- diff -uNr netinet/in.c /usr/src/sys/netinet/in.c --- netinet/in.c Tue Jul 31 14:04:40 2001 +++ /usr/src/sys/netinet/in.c Tue Jul 31 12:54:46 2001 @@ -48,6 +48,7 @@ #include #include +#include #include @@ -68,6 +69,9 @@ struct in_multihead in_multihead; /* XXX BSS initialization */ +extern struct inpcbinfo ripcbinfo; +extern struct inpcbinfo udbinfo; + /* * Return 1 if an internet address is for a ``local'' host * (one to which we have a connection). If subnetsarelocal @@ -402,6 +406,14 @@ * a routing process they will come back. */ in_ifadown(&ia->ia_ifa, 1); + /* + * XXX horrible hack to detect that we are being called + * from if_detach() + */ + if (!ifnet_addrs[ifp->if_index - 1]) { + in_pcbpurgeif0(LIST_FIRST(ripcbinfo.listhead), ifp); + in_pcbpurgeif0(LIST_FIRST(udbinfo.listhead), ifp); + } /* * Protect from ipintr() traversing address list diff -uNr netinet/in_pcb.c /usr/src/sys/netinet/in_pcb.c --- netinet/in_pcb.c Tue Jul 31 14:04:40 2001 +++ /usr/src/sys/netinet/in_pcb.c Tue Jul 31 12:53:05 2001 @@ -689,6 +689,44 @@ splx(s); } +void +in_pcbpurgeif0(head, ifp) + struct inpcb *head; + struct ifnet *ifp; +{ + struct inpcb *inp; + struct ip_moptions *imo; + int i, gap; + + for (inp = head; inp != NULL; inp = LIST_NEXT(inp, inp_list)) { + imo = inp->inp_moptions; + if ((inp->inp_vflag & INP_IPV4) && + imo != NULL) { + /* + * Unselect the outgoing interface if it is being + * detached. + */ + if (imo->imo_multicast_ifp == ifp) + imo->imo_multicast_ifp = NULL; + + /* + * Drop multicast group membership if we joined + * through the interface being detached. + */ + for (i = 0, gap = 0; i < imo->imo_num_memberships; + i++) { + if (imo->imo_membership[i]->inm_ifp == ifp) { + in_delmulti(imo->imo_membership[i]); + gap++; + } else if (gap != 0) + imo->imo_membership[i - gap] = + imo->imo_membership[i]; + } + imo->imo_num_memberships -= gap; + } + } +} + /* * Check for alternatives when higher level complains * about service problems. For now, invalidate cached diff -uNr netinet/in_pcb.h /usr/src/sys/netinet/in_pcb.h --- netinet/in_pcb.h Tue Jul 31 14:04:40 2001 +++ /usr/src/sys/netinet/in_pcb.h Tue Jul 31 12:53:05 2001 @@ -275,6 +275,7 @@ extern int ipport_hifirstauto; extern int ipport_hilastauto; +void in_pcbpurgeif0 __P((struct inpcb *, struct ifnet *)); void in_losing __P((struct inpcb *)); void in_rtchange __P((struct inpcb *, int)); int in_pcballoc __P((struct socket *, struct inpcbinfo *, struct proc *)); --- netinet.patch --- --- netinet6.patch --- diff -uNr netinet6/in6_ifattach.c /usr/src/sys/netinet6/in6_ifattach.c --- netinet6/in6_ifattach.c Tue Jul 31 14:04:47 2001 +++ /usr/src/sys/netinet6/in6_ifattach.c Tue Jul 31 12:55:52 2001 @@ -47,10 +47,12 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -72,6 +74,9 @@ struct callout in6_tmpaddrtimer_ch; +extern struct inpcbinfo udbinfo; +extern struct inpcbinfo ripcbinfo; + static int get_rand_ifid __P((struct ifnet *, struct in6_addr *)); static int generate_tmp_ifid __P((u_int8_t *, const u_int8_t *, u_int8_t *)); static int get_hw_ifid __P((struct ifnet *, struct in6_addr *)); @@ -942,6 +947,8 @@ } /* leave from all multicast groups joined */ + in6_pcbpurgeif0(LIST_FIRST(udbinfo.listhead), ifp); + in6_pcbpurgeif0(LIST_FIRST(ripcbinfo.listhead), ifp); for (in6m = LIST_FIRST(&in6_multihead); in6m; in6m = in6m_next) { in6m_next = LIST_NEXT(in6m, in6m_entry); if (in6m->in6m_ifp != ifp) diff -uNr netinet6/in6_pcb.c /usr/src/sys/netinet6/in6_pcb.c --- netinet6/in6_pcb.c Tue Jul 31 14:04:47 2001 +++ /usr/src/sys/netinet6/in6_pcb.c Tue Jul 31 12:53:10 2001 @@ -932,6 +932,45 @@ } } +void +in6_pcbpurgeif0(head, ifp) + struct in6pcb *head; + struct ifnet *ifp; +{ + struct in6pcb *in6p; + struct ip6_moptions *im6o; + struct in6_multi_mship *imm, *nimm; + + for (in6p = head; in6p != NULL; in6p = LIST_NEXT(in6p, inp_list)) { + im6o = in6p->in6p_moptions; + if ((in6p->inp_vflag & INP_IPV6) && + im6o) { + /* + * Unselect the outgoing interface if it is being + * detached. + */ + if (im6o->im6o_multicast_ifp == ifp) + im6o->im6o_multicast_ifp = NULL; + + /* + * Drop multicast group membership if we joined + * through the interface being detached. + * XXX controversial - is it really legal for kernel + * to force this? + */ + for (imm = im6o->im6o_memberships.lh_first; + imm != NULL; imm = nimm) { + nimm = imm->i6mm_chain.le_next; + if (imm->i6mm_maddr->in6m_ifp == ifp) { + LIST_REMOVE(imm, i6mm_chain); + in6_delmulti(imm->i6mm_maddr); + free(imm, M_IPMADDR); + } + } + } + } +} + /* * Check for alternatives when higher level complains * about service problems. For now, invalidate cached diff -uNr netinet6/in6_pcb.h /usr/src/sys/netinet6/in6_pcb.h --- netinet6/in6_pcb.h Tue Jul 31 14:04:47 2001 +++ /usr/src/sys/netinet6/in6_pcb.h Tue Jul 31 12:53:10 2001 @@ -74,6 +74,7 @@ #define sin6tosa(sin6) ((struct sockaddr *)(sin6)) #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) +void in6_pcbpurgeif0 __P((struct in6pcb *, struct ifnet *)); void in6_losing __P((struct inpcb *)); int in6_pcballoc __P((struct socket *, struct inpcbinfo *, struct proc *)); int in6_pcbbind __P((struct inpcb *, struct sockaddr *, struct proc *)); --- netinet6.patch --- >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message