Thanks for the report.
On 18/04/20(Sat) 18:17, Julian Brost wrote:
> I encountered a reproducible kernel panic during an accidental IPv6
> misconfiguration. In order to reproduce, the OpenBSD machine must be in
> the same subnet as a router that has fe80::1/64 configured and sends
> IPv6 route advertisements, for example with radvd using this config:
>
> interface eth0 {
> AdvSendAdvert on;
> MinRtrAdvInterval 10;
> MaxRtrAdvInterval 30;
> prefix 2001:db8::/64 {
> AdvOnLink on;
> AdvAutonomous on;
> AdvRouterAddr on;
> };
> };
>
> With this setup, I was able to to reliably trigger the assertion using
> the following steps:
>
> - Install Openbsd using 6.6/amd64 install66.iso
> - IPv4: none
> - IPv6: autoconf
> - Reboot into system, log in
> - echo inet6 alias fe80::1 64 >> /etc/hostname.vio0
> # The file now contains the following:
> # inet6 autoconf
> # inet6 alias fe80::1 64
> - Reboot and log in again
> - ping6 2001::
> # The exact address doesn't seem to matter, it also doesn't have to
> # respond or anything. Sometimes this step isn't even necessary as the
> # panic occurs by itself after the login prompt.
> - Wait a bit (less than a minute in my case) and observe the panic
>
[...]
> vio0: DAD detected duplicate IPv6 address fe80:1::1: NS in/out=0/1, NA in=1
> vio0: DAD complete for fe80:1::1 - duplicate found
> vio0: manual intervention required
Interesting :)
> login: panic: kernel diagnostic assertion "!ISSET(rt->rt_flags,
> RTF_LOCAL)" failed: file "/usr/src/sys/netinet6/nd6.c", line 727
That means some part of the ND code is incorrectly setting an `expire'
value to an entry that is local, and therefor should never expire.
Could you try to reproduce the issue with the diff below? It should
also panic but points us to the place where the bug is.
Index: netinet6/nd6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/nd6.c,v
retrieving revision 1.229
diff -u -p -r1.229 nd6.c
--- netinet6/nd6.c 29 Nov 2019 16:41:01 -0000 1.229
+++ netinet6/nd6.c 20 Apr 2020 10:07:15 -0000
@@ -306,6 +306,7 @@ nd6_llinfo_settimer(struct llinfo_nd6 *l
time_t expire = time_uptime + secs;
NET_ASSERT_LOCKED();
+ KASSERT(!ISSET(ln->ln_rt->rt_flags, RTF_LOCAL));
ln->ln_rt->rt_expire = expire;
if (!timeout_pending(&nd6_timer_to) || expire < nd6_timer_next) {