⬢ DragonFlyBSD Kernel Audit
DF-4697 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/disk/nvme/nvme_admin.c	2026-09-22 22:06:14.009580937 +0000
+++ b/sys/dev/disk/nvme/nvme_admin.c	2026-09-22 22:06:20.053502285 +0000
@@ -638,13 +638,22 @@
 			    sc->nscary[j]->nsid == rp->nsids[i])
 				break;
 		}
-		if (j == NVME_MAX_NAMESPACES) {
-			j = i;
-			if (sc->nscary[j] != NULL) {
-				for (j = NVME_MAX_NAMESPACES - 1; j >= 0; --j) {
-					if (sc->nscary[j] == NULL)
-						break;
-				}
+		if (j != NVME_MAX_NAMESPACES) {
+			/*
+			 * Duplicate nsid in the device-supplied list.
+			 * Never re-run the identify/attach sequence for a
+			 * namespace we already processed in this scan; a
+			 * second nvme_disk_attach() on a live namespace
+			 * corrupts the global disklist and devstat queues.
+			 */
+			nvme_put_request(req);
+			continue;
+		}
+		j = i;
+		if (sc->nscary[j] != NULL) {
+			for (j = NVME_MAX_NAMESPACES - 1; j >= 0; --j) {
+				if (sc->nscary[j] == NULL)
+					break;
 			}
 		}
 		if (j < 0) {
--- a/sys/dev/disk/nvme/nvme_disk.c	2026-09-22 22:06:14.013580885 +0000
+++ b/sys/dev/disk/nvme/nvme_disk.c	2026-09-22 22:06:28.173396615 +0000
@@ -74,6 +74,18 @@
 	size_t len;
 	uint64_t cap_gb;
 
+	/*
+	 * Defense-in-depth: the active namespace list is device-controlled
+	 * and must never cause the same namespace to be attached twice;
+	 * a second disk_create() on a live struct disk corrupts the global
+	 * disklist and devstat queues.
+	 */
+	if (nsc->cdev != NULL) {
+		device_printf(nsc->sc->dev,
+			      "namespace %u already attached\n", nsc->nsid);
+		return;
+	}
+
 	sc = nsc->sc;
 	devstat_add_entry(&nsc->stats, "nvme", nsc->unit, nsc->blksize,
 			  DEVSTAT_NO_ORDERED_TAGS,
@@ -118,6 +130,7 @@
 	if (nsc->cdev) {
 		disk_destroy(&nsc->disk);
 		devstat_remove_entry(&nsc->stats);
+		nsc->cdev = NULL;	/* allow a later re-attach */
 	}
 }