DragonFlyBSD Kernel Audit
DF-2246 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/ddb/db_sysctl.c b/sys/ddb/db_sysctl.c
--- a/sys/ddb/db_sysctl.c
+++ b/sys/ddb/db_sysctl.c
@@ -44,12 +44,29 @@
 #include <sys/kernel.h>
 #include <sys/sysctl.h>
 #include <sys/reboot.h>
+#include <sys/jail.h>
 
 #define DESCRIPTION	"Set to `ddb' or `gdb' to enter the kernel debugger"
 #define READ_MODE	""
 #define MODE_DDB	"ddb"
 #define MODE_GDB	"gdb"
 
+
+/*
+ * Destructive DDB knobs are host-only controls: panicking or entering the
+ * kernel debugger takes down the whole system, so they must never fire from
+ * inside a jail.  The generic SYSCAP_NOSYSCTL_WR gate is allowed in jails
+ * (prison_priv_check(), kern_jail.c), so each handler re-checks jail
+ * confinement before doing anything destructive.
+ */
+static __inline int
+ddb_sysctl_confined(struct sysctl_req *req)
+{
+	if (req->td != NULL && jailed(req->td->td_ucred))
+		return (EPERM);
+	return (0);
+}
+
 /*
  * This sysctl forces the kernel to enter the debugger.
  */
@@ -64,6 +81,9 @@
 	error = sysctl_handle_string(oidp, &dmode[0], sizeof(dmode), req);
 
 	if (error == 0 && req->newptr != NULL) {
+		error = ddb_sysctl_confined(req);
+		if (error)
+			return (error);
 		if (strcmp(dmode, MODE_DDB) == 0)
 			boothowto &= ~RB_GDB;
 		else if (strcmp(dmode, MODE_GDB) == 0)
@@ -87,8 +107,12 @@
 	int val = 0;
 
 	err = sysctl_handle_int(oidp, &val, 0, req);
-	if (val == 1)
+	if (val == 1) {
+		err = ddb_sysctl_confined(req);
+		if (err)
+			return (err);
 		panic("sysctl_debug_panic");
+	}
 	return err;
 }
 SYSCTL_PROC(_debug, OID_AUTO, panic, CTLTYPE_INT | CTLFLAG_RW, 0, 0,
@@ -121,8 +145,12 @@
 	int val = 0;
 
 	err = sysctl_handle_int(oidp, &val, 0, req);
-	if (val == 1)
+	if (val == 1) {
+		err = ddb_sysctl_confined(req);
+		if (err)
+			return (err);
 		stack_guard_panic2();
+	}
 	return err;
 }
 SYSCTL_PROC(_debug, OID_AUTO, panic2, CTLTYPE_INT | CTLFLAG_RW, 0, 0,