Re: kernel panic on shutdoen/reboot

Vitaliy Makkoveev <[email protected]> Mon, 1 Jun 2026 06:24:38 +0300
Newsgroups gmane.os.openbsd.bugs
Message-ID <[email protected]>
On Mon, May 25, 2026 at 04:45:26PM +0200, [email protected] wrote:
> >Synopsis:	<Kernel panic at shutdoen/reboot when rad is enabled>
> >Category:	
> >Environment:
> 	System      : OpenBSD 7.9
> 	Details     : OpenBSD 7.9 (GENERIC.MP) #222: Wed May  6 18:07:56 MDT 2026
> 			 [email protected]:/usr/src/sys/arch/arm64/compile/GENERIC.MP
> 
> 	Architecture: OpenBSD.arm64
> 	Machine     : arm64
> >Description:
> 	When rad is enabled, the system panics at shutdoen/reboot, no orderly reboot possible
> >How-To-Repeat:
> 	rcctl enable rad
> 	rcctl start rad
> 	shutdowen -r now
> 	... panic
> 	... reboot
> 	rcctl disable rad
> 	rcctl stop rad
> 	... panic
> 	... reboot
> 	rcctl check rad
> 	rad (failed)
>         shutdown -r now
> 	... ok
> >Fix:
> 	disable rad
> 

Hello,

I have no cad(4) device and I have no ability to compile this diff, so
I'm sending it offlist. Does it help?

Index: sys/dev/fdt/if_cad.c
===================================================================
RCS file: /cvs/src/sys/dev/fdt/if_cad.c,v
retrieving revision 1.16
diff -u -p -r1.16 if_cad.c
--- sys/dev/fdt/if_cad.c	17 Sep 2025 09:17:12 -0000	1.16
+++ sys/dev/fdt/if_cad.c	1 Jun 2026 06:33:49 -0000
@@ -589,21 +589,33 @@ cad_ioctl(struct ifnet *ifp, u_long cmd,
 {
 	struct cad_softc *sc = ifp->if_softc;
 	struct ifreq *ifr = (struct ifreq *)data;
-	int error = 0, netlock_held = 1;
+	int error = 0, netlock_status;
 	int s;
 
-	switch (cmd) {
-	case SIOCGIFMEDIA:
-	case SIOCSIFMEDIA:
-	case SIOCGIFSFFPAGE:
-		netlock_held = 0;
+	netlock_status = rw_status(&netlock);
+	case RW_WRITE:
+		NET_UNLOCK();
+		break;
+	case RW_READ:
+		switch (cmd) {
+		case SIOCADDMULTI:
+		case SIOCDELMULTI:
+			/*
+			 * We are called from sockets layer with socket
+			 * lock and shared netlock held
+			 */
+			NET_UNLOCK_SHARED();
+			break;
+		default:
+			/* The shared netlock was taken by another thread */
+			netlock_status = 0;
+			break;
+		}
 		break;
 	}
 
-	if (netlock_held)
-		NET_UNLOCK();
 	rw_enter_write(&sc->sc_cfg_lock);
-	if (netlock_held)
+	if (netlock_status)
 		NET_LOCK();
 	s = splnet();
 
@@ -647,6 +659,15 @@ cad_ioctl(struct ifnet *ifp, u_long cmd,
 	}
 
 	splx(s);
+	switch (netlock_status) {
+	case RW_READ:
+		NET_UNLOCK();
+		NET_LOCK_SHARED();
+		break;
+	case RW_WRITE:
+		/* Exclusive netlock is already held */
+		break;
+	}
 	rw_exit_write(&sc->sc_cfg_lock);
 
 	return error;