DF-2246 / fix.diff
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, |