On 11/12/14(Thu) 12:37, frantisek holop wrote:
> > > login: kernel: page fault trap, code=0
> > > Stopped at in_selectsrc+0xd8: movl 0xf0(%esi),%ebx
> > > ddb{0}> trace
> > > in_selectsrc(f617cdc8,d80b6714,d35d9270,d8cfac44,d8cfac34) at
> > > in_selectsrc+0xd8
> > >
> > > udp_output(d8cfabfc,d80b6900,d80b6700,0,0) at udp_output+0xf8
> > > sosend(d7f881c8,d80b6700,f617ce90,d80b6900,0) at sosend+0x44b
> > > sendit(d84f4b40,103,f617cef4,0,f617cf80) at sendit+0x1e1
> > > sys_sendto(d84f4b40,f617cf60,f617cf80,d0568b5a,d84f4b40) at
> > > sys_sendto+0x6c
> > > syscall() at syscall+0x144
> > > --- syscall (number 259) ---
> > > 0x2:
> > > ddb{0}>
>
> run0 usb dongle + dhclient through a home router,
> with one special route added that is forwarded through
> a linux box (on the same home router network) which
> is connected to a vpn in a different country.
> it is added like this:
>
> # route add 192.168.10.2 $LINUX_IP
>
> jenkins is running a shell script, that is running
> tests on the 192.168.10.2 web site accessible only
> through the vpn. the tests are simple selenium tests
> recorded through the firefox plugin. a quick google
> reveals that jenkins itself might be using some
> udp/multicast functionality:
> https://wiki.jenkins-ci.org/display/JENKINS/Auto-discovering+Jenkins+on+the+network
Could you try the diff below and let me know if it improves the
situation? It should prevent your kernel to panic. Even though,
more work might be required to have working socket w/ multicast
using USB devices upon resume.
What's happening is simply a use after free because there's no way to
invalidate multicast options attached to a pcb when an interface is
detached. I which multicast would have been implemented using route
entries instead of this hack...
Change below works around this problem by using interface indexes.
Index: net/if.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if.c,v
retrieving revision 1.306
diff -u -p -r1.306 if.c
--- net/if.c 8 Dec 2014 10:46:14 -0000 1.306
+++ net/if.c 11 Dec 2014 13:09:23 -0000
@@ -533,11 +533,6 @@ do { \
#endif
#undef IF_DETACH_QUEUES
- /*
- * XXX transient ifp refs? inpcb.ip_moptions.imo_multicast_ifp?
- * Other network stacks than INET?
- */
-
/* Remove the interface from the list of all interfaces. */
TAILQ_REMOVE(&ifnet, ifp, if_list);
if (ISSET(ifp->if_xflags, IFXF_TXREADY))
Index: net/if_pfsync.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_pfsync.c,v
retrieving revision 1.212
diff -u -p -r1.212 if_pfsync.c
--- net/if_pfsync.c 23 Nov 2014 07:39:02 -0000 1.212
+++ net/if_pfsync.c 11 Dec 2014 13:09:23 -0000
@@ -1354,7 +1354,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cm
if (imo->imo_num_memberships > 0) {
in_delmulti(imo->imo_membership[
--imo->imo_num_memberships]);
- imo->imo_multicast_ifp = NULL;
+ imo->imo_ifidx = 0;
}
splx(s);
break;
@@ -1379,7 +1379,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cm
if (imo->imo_num_memberships > 0) {
in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
- imo->imo_multicast_ifp = NULL;
+ imo->imo_ifidx = 0;
}
if (sc->sc_sync_if &&
@@ -1401,7 +1401,7 @@ pfsyncioctl(struct ifnet *ifp, u_long cm
return (ENOBUFS);
}
imo->imo_num_memberships++;
- imo->imo_multicast_ifp = sc->sc_sync_if;
+ imo->imo_ifidx = sc->sc_sync_if->if_index;
imo->imo_multicast_ttl = PFSYNC_DFLTTL;
imo->imo_multicast_loop = 0;
}
Index: net/if_vxlan.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_vxlan.c,v
retrieving revision 1.17
diff -u -p -r1.17 if_vxlan.c
--- net/if_vxlan.c 5 Dec 2014 15:50:04 -0000 1.17
+++ net/if_vxlan.c 11 Dec 2014 13:09:23 -0000
@@ -179,8 +179,9 @@ vxlan_multicast_cleanup(struct ifnet *if
{
struct vxlan_softc *sc = (struct vxlan_softc *)ifp->if_softc;
struct ip_moptions *imo = &sc->sc_imo;
- struct ifnet *mifp = imo->imo_multicast_ifp;
+ struct ifnet *mifp;
+ mifp = if_get(imo->imo_ifidx);
if (mifp != NULL) {
if (sc->sc_ahcookie != NULL) {
hook_disestablish(mifp->if_addrhooks, sc->sc_ahcookie);
@@ -200,7 +201,7 @@ vxlan_multicast_cleanup(struct ifnet *if
if (imo->imo_num_memberships > 0) {
in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
- imo->imo_multicast_ifp = NULL;
+ imo->imo_ifidx = 0;
}
}
@@ -229,7 +230,7 @@ vxlan_multicast_join(struct ifnet *ifp,
return (ENOBUFS);
imo->imo_num_memberships++;
- imo->imo_multicast_ifp = mifp;
+ imo->imo_ifidx = mifp->if_index;
if (sc->sc_ttl > 0)
imo->imo_multicast_ttl = sc->sc_ttl;
else
Index: netinet/igmp.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/igmp.c,v
retrieving revision 1.46
diff -u -p -r1.46 igmp.c
--- netinet/igmp.c 18 Nov 2014 02:37:31 -0000 1.46
+++ netinet/igmp.c 11 Dec 2014 13:09:23 -0000
@@ -641,7 +641,7 @@ igmp_sendpkt(struct in_multi *inm, int t
m->m_data -= sizeof(struct ip);
m->m_len += sizeof(struct ip);
- imo.imo_multicast_ifp = if_get(inm->inm_ifidx);
+ imo.imo_ifidx = inm->inm_ifidx;
imo.imo_multicast_ttl = 1;
/*
Index: netinet/in_pcb.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.164
diff -u -p -r1.164 in_pcb.c
--- netinet/in_pcb.c 5 Dec 2014 15:50:04 -0000 1.164
+++ netinet/in_pcb.c 11 Dec 2014 13:09:23 -0000
@@ -871,7 +871,7 @@ in_selectsrc(struct in_addr **insrc, str
if (IN_MULTICAST(sin->sin_addr.s_addr) && mopts != NULL) {
struct ifnet *ifp;
- ifp = mopts->imo_multicast_ifp;
+ ifp = if_get(mopts->imo_ifidx);
if (ifp != NULL) {
if (ifp->if_rdomain == rtable_l2(rtableid))
IFP_TO_IA(ifp, ia);
Index: netinet/ip_carp.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.240
diff -u -p -r1.240 ip_carp.c
--- netinet/ip_carp.c 5 Dec 2014 15:50:04 -0000 1.240
+++ netinet/ip_carp.c 11 Dec 2014 13:09:23 -0000
@@ -1643,7 +1643,7 @@ carp_multicast_cleanup(struct carp_softc
}
}
imo->imo_num_memberships = 0;
- imo->imo_multicast_ifp = NULL;
+ imo->imo_ifidx = 0;
#ifdef INET6
while (!LIST_EMPTY(&im6o->im6o_memberships)) {
@@ -1653,7 +1653,7 @@ carp_multicast_cleanup(struct carp_softc
LIST_REMOVE(imm, i6mm_chain);
in6_leavegroup(imm);
}
- im6o->im6o_multicast_ifp = NULL;
+ im6o->im6o_ifidx = 0;
#endif
/* And any other multicast memberships */
@@ -1930,7 +1930,7 @@ carp_join_multicast(struct carp_softc *s
imo->imo_membership[0] = imm;
imo->imo_num_memberships = 1;
- imo->imo_multicast_ifp = &sc->sc_if;
+ imo->imo_ifidx = sc->sc_if.if_index;
imo->imo_multicast_ttl = CARP_DFLTTL;
imo->imo_multicast_loop = 0;
return (0);
@@ -2039,7 +2039,7 @@ carp_join_multicast6(struct carp_softc *
}
/* apply v6 multicast membership */
- im6o->im6o_multicast_ifp = &sc->sc_if;
+ im6o->im6o_ifidx = sc->sc_if.if_index;
if (imm)
LIST_INSERT_HEAD(&im6o->im6o_memberships, imm,
i6mm_chain);
Index: netinet/ip_mroute.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_mroute.c,v
retrieving revision 1.72
diff -u -p -r1.72 ip_mroute.c
--- netinet/ip_mroute.c 5 Dec 2014 15:50:04 -0000 1.72
+++ netinet/ip_mroute.c 11 Dec 2014 13:09:23 -0000
@@ -1653,7 +1653,7 @@ send_packet(struct vif *vifp, struct mbu
*/
struct ip_moptions imo;
- imo.imo_multicast_ifp = vifp->v_ifp;
+ imo.imo_ifidx = vifp->v_ifp->if_index;
imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - IPTTLDEC;
imo.imo_multicast_loop = 1;
Index: netinet/ip_output.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.274
diff -u -p -r1.274 ip_output.c
--- netinet/ip_output.c 8 Dec 2014 10:51:00 -0000 1.274
+++ netinet/ip_output.c 11 Dec 2014 13:09:23 -0000
@@ -191,8 +191,7 @@ ip_output(struct mbuf *m0, struct mbuf *
if ((IN_MULTICAST(ip->ip_dst.s_addr) ||
(ip->ip_dst.s_addr == INADDR_BROADCAST)) &&
- imo != NULL && imo->imo_multicast_ifp != NULL) {
- ifp = imo->imo_multicast_ifp;
+ imo != NULL && (ifp = if_get(imo->imo_ifidx)) != NULL) {
mtu = ifp->if_mtu;
IFP_TO_IA(ifp, ia);
} else {
@@ -342,8 +341,7 @@ reroute:
if ((IN_MULTICAST(ip->ip_dst.s_addr) ||
(ip->ip_dst.s_addr == INADDR_BROADCAST)) &&
- imo != NULL && imo->imo_multicast_ifp != NULL) {
- ifp = imo->imo_multicast_ifp;
+ imo != NULL && (ifp = if_get(imo->imo_ifidx)) != NULL) {
mtu = ifp->if_mtu;
IFP_TO_IA(ifp, ia);
} else {
@@ -1679,7 +1677,7 @@ ip_setmoptions(int optname, struct ip_mo
(sizeof(*immp) * IP_MIN_MEMBERSHIPS), M_IPMOPTS,
M_WAITOK|M_ZERO);
*imop = imo;
- imo->imo_multicast_ifp = NULL;
+ imo->imo_ifidx = 0;
imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
imo->imo_num_memberships = 0;
@@ -1704,7 +1702,7 @@ ip_setmoptions(int optname, struct ip_mo
* chosen every time a multicast packet is sent.
*/
if (addr.s_addr == INADDR_ANY) {
- imo->imo_multicast_ifp = NULL;
+ imo->imo_ifidx = 0;
break;
}
/*
@@ -1723,7 +1721,7 @@ ip_setmoptions(int optname, struct ip_mo
error = EADDRNOTAVAIL;
break;
}
- imo->imo_multicast_ifp = ifp;
+ imo->imo_ifidx = ifp->if_index;
break;
case IP_MULTICAST_TTL:
@@ -1923,7 +1921,7 @@ ip_setmoptions(int optname, struct ip_mo
/*
* If all options have default values, no need to keep the data.
*/
- if (imo->imo_multicast_ifp == NULL &&
+ if (imo->imo_ifidx == 0 &&
imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL &&
imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP &&
imo->imo_num_memberships == 0) {
@@ -1945,6 +1943,7 @@ ip_getmoptions(int optname, struct ip_mo
u_char *loop;
struct in_addr *addr;
struct in_ifaddr *ia;
+ struct ifnet *ifp;
*mp = m_get(M_WAIT, MT_SOOPTS);
@@ -1953,10 +1952,10 @@ ip_getmoptions(int optname, struct ip_mo
case IP_MULTICAST_IF:
addr = mtod(*mp, struct in_addr *);
(*mp)->m_len = sizeof(struct in_addr);
- if (imo == NULL || imo->imo_multicast_ifp == NULL)
+ if (imo == NULL || (ifp = if_get(imo->imo_ifidx)) == NULL)
addr->s_addr = INADDR_ANY;
else {
- IFP_TO_IA(imo->imo_multicast_ifp, ia);
+ IFP_TO_IA(ifp, ia);
addr->s_addr = (ia == NULL) ? INADDR_ANY
: ia->ia_addr.sin_addr.s_addr;
}
Index: netinet/ip_var.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_var.h,v
retrieving revision 1.57
diff -u -p -r1.57 ip_var.h
--- netinet/ip_var.h 5 Nov 2014 14:03:02 -0000 1.57
+++ netinet/ip_var.h 11 Dec 2014 13:09:23 -0000
@@ -101,12 +101,12 @@ struct ipoption {
* passed to ip_output when IP multicast options are in use.
*/
struct ip_moptions {
- struct ifnet *imo_multicast_ifp; /* ifp for outgoing multicasts */
+ struct in_multi **imo_membership; /* group memberships */
+ unsigned short imo_ifidx; /* ifp index for outgoing multicasts */
u_int8_t imo_multicast_ttl; /* TTL for outgoing multicasts */
u_int8_t imo_multicast_loop; /* 1 => hear sends if a member */
u_int16_t imo_num_memberships; /* no. memberships this socket */
u_int16_t imo_max_memberships; /* max memberships this socket */
- struct in_multi **imo_membership; /* group memberships */
};
#include <sys/queue.h>
Index: netinet6/in6_src.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/in6_src.c,v
retrieving revision 1.49
diff -u -p -r1.49 in6_src.c
--- netinet6/in6_src.c 5 Dec 2014 15:50:04 -0000 1.49
+++ netinet6/in6_src.c 11 Dec 2014 13:09:23 -0000
@@ -200,7 +200,7 @@ in6_selectsrc(struct in6_addr **in6src,
* choose a loopback interface as the outgoing interface.
*/
if (IN6_IS_ADDR_MULTICAST(dst)) {
- ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
+ ifp = mopts ? if_get(mopts->im6o_ifidx) : NULL;
if (!ifp && dstsock->sin6_scope_id)
ifp = if_get(htons(dstsock->sin6_scope_id));
@@ -345,7 +345,7 @@ selectroute(struct sockaddr_in6 *dstsock
* interface for the address is specified by the caller, use it.
*/
if (IN6_IS_ADDR_MULTICAST(dst) &&
- mopts != NULL && (ifp = mopts->im6o_multicast_ifp) != NULL) {
+ mopts != NULL && (ifp = if_get(mopts->im6o_ifidx)) != NULL) {
goto done; /* we do not need a route for multicast. */
}
@@ -617,8 +617,7 @@ in6_embedscope(struct in6_addr *in6, con
in6->s6_addr16[1] = htons(pi->ipi6_ifindex);
} else if (in6p && IN6_IS_ADDR_MULTICAST(in6) &&
in6p->inp_moptions6 &&
- in6p->inp_moptions6->im6o_multicast_ifp) {
- ifp = in6p->inp_moptions6->im6o_multicast_ifp;
+ (ifp = if_get(in6p->inp_moptions6->im6o_ifidx))) {
in6->s6_addr16[1] = htons(ifp->if_index);
} else if (scopeid) {
ifp = if_get(scopeid);
Index: netinet6/ip6_mroute.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/ip6_mroute.c,v
retrieving revision 1.74
diff -u -p -r1.74 ip6_mroute.c
--- netinet6/ip6_mroute.c 5 Dec 2014 15:50:04 -0000 1.74
+++ netinet6/ip6_mroute.c 11 Dec 2014 13:09:23 -0000
@@ -1437,7 +1437,7 @@ phyint_send(struct ip6_hdr *ip6, struct
if (m->m_pkthdr.rcvif == NULL) {
struct ip6_moptions im6o;
- im6o.im6o_multicast_ifp = ifp;
+ im6o.im6o_ifidx = ifp->if_index;
/* XXX: ip6_output will override ip6->ip6_hlim */
im6o.im6o_multicast_hlim = ip6->ip6_hlim;
im6o.im6o_multicast_loop = 1;
Index: netinet6/ip6_output.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.163
diff -u -p -r1.163 ip6_output.c
--- netinet6/ip6_output.c 5 Dec 2014 15:50:04 -0000 1.163
+++ netinet6/ip6_output.c 11 Dec 2014 13:09:23 -0000
@@ -2329,7 +2329,7 @@ ip6_setmoptions(int optname, struct ip6_
if (im6o == NULL)
return (ENOBUFS);
*im6op = im6o;
- im6o->im6o_multicast_ifp = NULL;
+ im6o->im6o_ifidx = 0;
im6o->im6o_multicast_hlim = ip6_defmcasthlim;
im6o->im6o_multicast_loop = IPV6_DEFAULT_MULTICAST_LOOP;
LIST_INIT(&im6o->im6o_memberships);
@@ -2359,7 +2359,7 @@ ip6_setmoptions(int optname, struct ip6_
break;
}
}
- im6o->im6o_multicast_ifp = ifp;
+ im6o->im6o_ifidx = ifindex;
break;
case IPV6_MULTICAST_HOPS:
@@ -2572,7 +2572,7 @@ ip6_setmoptions(int optname, struct ip6_
* If all options have default values, no need to keep the option
* structure.
*/
- if (im6o->im6o_multicast_ifp == NULL &&
+ if (im6o->im6o_ifidx == 0 &&
im6o->im6o_multicast_hlim == ip6_defmcasthlim &&
im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP &&
LIST_EMPTY(&im6o->im6o_memberships)) {
@@ -2598,10 +2598,10 @@ ip6_getmoptions(int optname, struct ip6_
case IPV6_MULTICAST_IF:
ifindex = mtod(*mp, u_int *);
(*mp)->m_len = sizeof(u_int);
- if (im6o == NULL || im6o->im6o_multicast_ifp == NULL)
+ if (im6o == NULL || im6o->im6o_ifidx == 0)
*ifindex = 0;
else
- *ifindex = im6o->im6o_multicast_ifp->if_index;
+ *ifindex = im6o->im6o_ifidx;
return (0);
case IPV6_MULTICAST_HOPS:
Index: netinet6/ip6_var.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/ip6_var.h,v
retrieving revision 1.49
diff -u -p -r1.49 ip6_var.h
--- netinet6/ip6_var.h 11 Jul 2014 16:39:06 -0000 1.49
+++ netinet6/ip6_var.h 11 Dec 2014 13:09:23 -0000
@@ -92,10 +92,10 @@ struct ip6asfrag {
#define IP6_REASS_MBUF(ip6af) ((ip6af)->ip6af_m)
struct ip6_moptions {
- struct ifnet *im6o_multicast_ifp; /* ifp for outgoing multicasts */
+ LIST_HEAD(, in6_multi_mship) im6o_memberships;
+ unsigned short im6o_ifidx; /* ifp index for outgoing multicasts */
u_char im6o_multicast_hlim; /* hoplimit for outgoing multicasts */
u_char im6o_multicast_loop; /* 1 >= hear sends if a member */
- LIST_HEAD(, in6_multi_mship) im6o_memberships;
};
/*
Index: netinet6/mld6.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/mld6.c,v
retrieving revision 1.39
diff -u -p -r1.39 mld6.c
--- netinet6/mld6.c 18 Nov 2014 02:37:31 -0000 1.39
+++ netinet6/mld6.c 11 Dec 2014 13:09:23 -0000
@@ -438,7 +438,7 @@ mld6_sendpkt(struct in6_multi *in6m, int
/* construct multicast option */
bzero(&im6o, sizeof(im6o));
- im6o.im6o_multicast_ifp = ifp;
+ im6o.im6o_ifidx = ifp->if_index;
im6o.im6o_multicast_hlim = 1;
/*
Index: netinet6/nd6_nbr.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/nd6_nbr.c,v
retrieving revision 1.86
diff -u -p -r1.86 nd6_nbr.c
--- netinet6/nd6_nbr.c 5 Dec 2014 15:50:04 -0000 1.86
+++ netinet6/nd6_nbr.c 11 Dec 2014 13:09:23 -0000
@@ -398,7 +398,7 @@ nd6_ns_output(struct ifnet *ifp, struct
if (daddr6 == NULL || IN6_IS_ADDR_MULTICAST(daddr6)) {
m->m_flags |= M_MCAST;
- im6o.im6o_multicast_ifp = ifp;
+ im6o.im6o_ifidx = ifp->if_index;
im6o.im6o_multicast_hlim = 255;
im6o.im6o_multicast_loop = 0;
}
@@ -949,7 +949,7 @@ nd6_na_output(struct ifnet *ifp, struct
if (IN6_IS_ADDR_MULTICAST(daddr6)) {
m->m_flags |= M_MCAST;
- im6o.im6o_multicast_ifp = ifp;
+ im6o.im6o_ifidx = ifp->if_index;
im6o.im6o_multicast_hlim = 255;
im6o.im6o_multicast_loop = 0;
}
Index: netinet6/nd6_rtr.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet6/nd6_rtr.c,v
retrieving revision 1.92
diff -u -p -r1.92 nd6_rtr.c
--- netinet6/nd6_rtr.c 5 Dec 2014 15:50:04 -0000 1.92
+++ netinet6/nd6_rtr.c 11 Dec 2014 13:09:23 -0000
@@ -202,7 +202,7 @@ nd6_rs_output(struct ifnet* ifp, struct
m->m_flags |= M_MCAST;
m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT;
- im6o.im6o_multicast_ifp = ifp;
+ im6o.im6o_ifidx = ifp->if_index;
im6o.im6o_multicast_hlim = 255;
im6o.im6o_multicast_loop = 0;