⬢ DragonFlyBSD Kernel Audit
DF-5775 / fix.diff
← back to finding ↓ download raw
--- a/sys/platform/vkernel64/platform/init.c	2026-10-11 19:19:42.635929571 +0000
+++ b/sys/platform/vkernel64/platform/init.c	2026-10-11 19:20:00.435697315 +0000
@@ -392,6 +392,8 @@
 			 * set ncpus here.
 			 */
 			tok = strtok(optarg, ":");
+			if (tok == NULL)
+				usage_err("Bad -n option");
 			optcpus = strtol(tok, NULL, 0);
 			if (optcpus < 1 || optcpus > MAXCPU)
 				usage_err("Bad ncpus, valid range is 1-%d", MAXCPU);
@@ -502,7 +504,19 @@
 void
 handle_term(int sig)
 {
-	kill(childpid, sig);
+	/*
+	 * DF-5773: the monitor installs this handler AFTER fork(), so any
+	 * child forked by a LATER iteration of the monitor loop (i.e. after
+	 * a cpu_reset()/EX_VKERNEL_REBOOT reboot cycle) inherits it with
+	 * childpid == 0 -- where kill(0, sig) means "signal the whole
+	 * process group", splashing TERM onto the rc script/supervisor
+	 * that launched the vkernel and re-arming itself forever (each
+	 * delivery runs kill(0) again, keeping a TERM pending for
+	 * redelivery on handler return: an unstoppable signal storm).
+	 * Only the monitor (childpid > 0) may forward.
+	 */
+	if (childpid > 0)
+		kill(childpid, sig);
 }
 
 /*
@@ -1387,7 +1401,10 @@
 
 	if (pid_file != NULL) {
 		snprintf(buf, sizeof(buf), "%ld\n", (long)getpid());
-		fd = open(pid_file, O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0666);
+		/* DF-5775: never follow a symlinked pidfile */
+		fd = open(pid_file,
+			  O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK|O_NOFOLLOW,
+			  0666);
 		if (fd < 0) {
 			if (errno == EWOULDBLOCK) {
 				perror("Failed to lock pidfile, "