⬢ DragonFlyBSD Kernel Audit
DF-5473 / fix.diff
← back to finding ↓ download raw
--- a/sys/platform/vkernel64/x86_64/db_trace.c	2026-10-06 02:39:23.807794758 +0000
+++ b/sys/platform/vkernel64/x86_64/db_trace.c	2026-10-06 02:39:38.363605685 +0000
@@ -128,8 +128,18 @@
 
 /*
  * Stack trace.
+ *
+ * NOTE: the inherited pc64 definition of INKERNEL() as `>= USRSTACK` is
+ * WRONG for the vkernel: the vkernel's kernel lives in [KvaStart, KvaEnd)
+ * (vmparam.h KERNEL_KVA_START 512GB .. +KERNEL_KVA_SIZE, mapped at
+ * platform/init.c:609-621), which is deep INSIDE the guest-user VA range
+ * [0, USRSTACK) — the inherited test would reject every real kernel frame
+ * and accept every guest-user address.  Keep the macro but bound the walk
+ * by the actual kernel KVA range (KvaStart/KvaEnd, vm/pmap.h).
  */
-#define	INKERNEL(va)	(((vm_offset_t)(va)) >= USRSTACK)
+#define	INKERNEL(va)	\
+	(((vm_offset_t)(va)) >= KvaStart && \
+	 ((vm_offset_t)(va)) < KvaEnd)
 
 struct x86_64_frame {
 	struct x86_64_frame	*f_frame;
@@ -224,7 +234,8 @@
 	db_expr_t offset;
 	const char *sym, *name;
 
-	if ((unsigned long)*fp < PAGE_SIZE) {
+	if ((unsigned long)*fp < PAGE_SIZE || !INKERNEL((vm_offset_t)*fp)) {
+		db_printf("frame %p is not in kernel space\n", *fp);
 		*fp = NULL;
 		return;
 	}
@@ -255,6 +266,18 @@
 	 */
 	if (frame_type == NORMAL) {
 		*ip = (db_addr_t) rip;
+		/*
+		 * The adopted frame must be in kernel KVA and must move
+		 * strictly up the stack: kills wild pointers, cycles, and
+		 * guest-user frame chains adopted from corrupted stack
+		 * content (which fault in db_read_bytes — whose no-fault
+		 * recovery is broken outside a DDB session).
+		 */
+		if (!INKERNEL((vm_offset_t)rbp) ||
+		    (struct x86_64_frame *)rbp <= *fp) {
+			*fp = NULL;
+			return;
+		}
 		*fp = (struct x86_64_frame *) rbp;
 		return;
 	}
@@ -306,7 +329,10 @@
 	}
 
 	*ip = (db_addr_t) rip;
-	*fp = (struct x86_64_frame *) rbp;
+	if (!INKERNEL((vm_offset_t)rbp))
+		*fp = NULL;
+	else
+		*fp = (struct x86_64_frame *) rbp;
 }
 
 void
@@ -333,6 +359,10 @@
 		 * a convenience.
 		 */
 		frame = (struct x86_64_frame *)addr;
+		if (!INKERNEL((vm_offset_t)frame)) {
+			db_printf("%p is not in kernel space\n", (void *)addr);
+			return;
+		}
 		for (i = 0; i < 4096; i += 8) {
 			struct x86_64_frame *check;