On 30/10/15(Fri) 19:44, Matthieu Herrb wrote: > When running my wifi configuration script which does: > > > ifconfig $1 inet6 -autoconfprivacy autoconf > > on a particular wifi network, I get a 100% reproducible panic on my > X240 running a kernel from Oct 25 (with a preliminary version of > kettenis inteldrm at pci patch). > > Manually copied from a picture : > > uwm_fault(0xffffffff81931280, 0xb, 0, 1) -> e > kernel: page fault trap, code=0 > Stopped at in6_ifadd+0x229; testb $0x2,0xb0(%rax) > ddb{0}> trace > in6_ifadd() at in6_ifadd+0x229 > nd6_addr_add() at nd6_addr_add+0x113 > taskq_thread() at taskq_thread+0x6c > end trace fame: 0x0, count -3 > ddb{0}> ps > .... > *11784 0 0 0 7 0x14200 systq > ... > > > Unfortunatly I'm not going to be able to re-test it with a more current > kernel since it was in a datacenter where access is a bit complicated > for me.
This seems to be a horrible bug related to the complexity of the ND6 and introduced by recent changes to run sleeping code in a task. In in6_ifadd(), line 2020 you can see: /* this is always non-NULL */ ia6 = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr); ... Sadly the comment is no longer true as in6_update_ifa() can return 0 without creating an address if "vltime == 0". This can now happen because nd6_addr_add() is executed in a task with a "nd_prefix" with a vltime and pltime of 0, see prelist_update() line 1254: error = nd6_prelist_add(new, dr, &newpr) ... /* * XXX: from the ND point of view, we can ignore a prefix * with the on-link bit being zero. However, we need a * prefix structure for references from autoconfigured * addresses. Thus, we explicitly make sure that the prefix * itself expires now. */ if (newpr->ndpr_raf_onlink == 0) { newpr->ndpr_vltime = 0; newpr->ndpr_pltime = 0; in6_init_prefix_ltimes(newpr); } Diff below should work around this problem. I don't think a proper fix can be written without rewriting this whole code. Index: netinet6/nd6_rtr.c =================================================================== RCS file: /cvs/src/sys/netinet6/nd6_rtr.c,v retrieving revision 1.133 diff -u -p -r1.133 nd6_rtr.c --- netinet6/nd6_rtr.c 2 Nov 2015 13:54:46 -0000 1.133 +++ netinet6/nd6_rtr.c 2 Nov 2015 15:45:39 -0000 @@ -2013,11 +2013,10 @@ in6_ifadd(struct nd_prefix *pr, int priv return (NULL); /* ifaddr must not have been allocated. */ } - /* this is always non-NULL */ ia6 = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr); /* Perform DAD, if needed. */ - if (ia6->ia6_flags & IN6_IFF_TENTATIVE) + if (ia != NULL && ia6->ia6_flags & IN6_IFF_TENTATIVE) nd6_dad_start(&ia6->ia_ifa); return (ia6);