Page MenuHomeFreeBSD

D37106.diff
No OneTemporary

D37106.diff

diff --git a/share/man/man9/sysctl.9 b/share/man/man9/sysctl.9
--- a/share/man/man9/sysctl.9
+++ b/share/man/man9/sysctl.9
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 1, 2020
+.Dd October 24, 2022
.Dt SYSCTL 9
.Os
.Sh NAME
@@ -893,7 +893,20 @@
A process in capability mode can write to this sysctl.
.It Dv CTLFLAG_SECURE
This sysctl can be written to only if the effective securelevel of the
-process is \[<=] 0.
+system is \[<=] 0.
+.It Dv CTLFLAG_KDB_SECURE
+This sysctl allows users to control settings related to KDB and
+.Xr ddb 4 .
+To ensure that they cannot be abused to lower the effective securelevel
+of the system, this flag ensures that they can only be written to if at
+least one of the following two conditions is met: the securelevel is
+\[<=] 0, or a
+.Xr mac 9
+policy explicitly permits it.
+For example, the
+.Xr mac_ddb 4
+limits the possible operations of KDB such that it is safe to enter
+DDB even with a raised securelevel.
.It Dv CTLFLAG_PRISON
This sysctl can be written to by processes in
.Xr jail 2 .
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -129,17 +129,17 @@
int debugger_on_panic = 1;
#endif
SYSCTL_INT(_debug, OID_AUTO, debugger_on_panic,
- CTLFLAG_RWTUN | CTLFLAG_SECURE,
+ CTLFLAG_RWTUN | CTLFLAG_KDB_SECURE,
&debugger_on_panic, 0, "Run debugger on kernel panic");
static bool debugger_on_recursive_panic = false;
SYSCTL_BOOL(_debug, OID_AUTO, debugger_on_recursive_panic,
- CTLFLAG_RWTUN | CTLFLAG_SECURE,
+ CTLFLAG_RWTUN | CTLFLAG_KDB_SECURE,
&debugger_on_recursive_panic, 0, "Run debugger on recursive kernel panic");
int debugger_on_trap = 0;
SYSCTL_INT(_debug, OID_AUTO, debugger_on_trap,
- CTLFLAG_RWTUN | CTLFLAG_SECURE,
+ CTLFLAG_RWTUN | CTLFLAG_KDB_SECURE,
&debugger_on_trap, 0, "Run debugger on kernel trap before panic");
#ifdef KDB_TRACE
@@ -150,7 +150,7 @@
static bool trace_all_panics = false;
#endif
SYSCTL_INT(_debug, OID_AUTO, trace_on_panic,
- CTLFLAG_RWTUN | CTLFLAG_SECURE,
+ CTLFLAG_RWTUN | CTLFLAG_KDB_SECURE,
&trace_on_panic, 0, "Print stack trace on kernel panic");
SYSCTL_BOOL(_debug, OID_AUTO, trace_all_panics, CTLFLAG_RWTUN,
&trace_all_panics, 0, "Print stack traces on secondary kernel panics");
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -42,6 +42,7 @@
#include "opt_capsicum.h"
#include "opt_ddb.h"
+#include "opt_kdb.h"
#include "opt_ktrace.h"
#include "opt_sysctl.h"
@@ -2247,11 +2248,24 @@
#endif
/* Is this sysctl sensitive to securelevels? */
- if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) {
- lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE;
- error = securelevel_gt(req->td->td_ucred, lvl);
- if (error)
- goto out;
+ if (req->newptr) {
+ if (oid->oid_kind & CTLFLAG_SECURE) {
+ lvl = (oid->oid_kind & CTLMASK_SECURE) >>
+ CTLSHIFT_SECURE;
+ error = securelevel_gt(req->td->td_ucred, lvl);
+ if (error)
+ goto out;
+ }
+
+ if ((oid->oid_kind & CTLFLAG_KDB_SECURE) != 0) {
+ error = securelevel_gt(req->td->td_ucred, 0);
+#ifdef MAC
+ if (error)
+ error = mac_kdb_check_sysctl(oid, req);
+#endif
+ if (error)
+ goto out;
+ }
}
/* Is this sysctl writable by only privileged users? */
diff --git a/sys/kern/subr_kdb.c b/sys/kern/subr_kdb.c
--- a/sys/kern/subr_kdb.c
+++ b/sys/kern/subr_kdb.c
@@ -103,7 +103,7 @@
"currently selected KDB backend");
SYSCTL_PROC(_debug_kdb, OID_AUTO, enter,
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE | CTLFLAG_MPSAFE, NULL, 0,
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KDB_SECURE | CTLFLAG_MPSAFE, NULL, 0,
kdb_sysctl_enter, "I",
"set to enter the debugger");
@@ -133,11 +133,11 @@
"set to cause a stack overflow");
SYSCTL_INT(_debug_kdb, OID_AUTO, break_to_debugger,
- CTLFLAG_RWTUN | CTLFLAG_SECURE,
+ CTLFLAG_RWTUN | CTLFLAG_KDB_SECURE,
&kdb_break_to_debugger, 0, "Enable break to debugger");
SYSCTL_INT(_debug_kdb, OID_AUTO, alt_break_to_debugger,
- CTLFLAG_RWTUN | CTLFLAG_SECURE,
+ CTLFLAG_RWTUN | CTLFLAG_KDB_SECURE,
&kdb_alt_break_to_debugger, 0, "Enable alternative break to debugger");
/*
diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h
--- a/sys/security/mac/mac_framework.h
+++ b/sys/security/mac/mac_framework.h
@@ -214,6 +214,7 @@
void mac_ipq_update(struct mbuf *m, struct ipq *q);
int mac_kdb_check_backend(struct kdb_dbbe *be);
+int mac_kdb_check_sysctl(struct sysctl_oid *oid, struct sysctl_req *req);
int mac_kenv_check_dump(struct ucred *cred);
int mac_kenv_check_get(struct ucred *cred, char *name);
diff --git a/sys/security/mac/mac_kdb.c b/sys/security/mac/mac_kdb.c
--- a/sys/security/mac/mac_kdb.c
+++ b/sys/security/mac/mac_kdb.c
@@ -32,6 +32,7 @@
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/sysctl.h>
#include <ddb/ddb.h>
@@ -48,6 +49,23 @@
return (error);
}
+int
+mac_kdb_check_sysctl(struct sysctl_oid *oid, struct sysctl_req *req)
+{
+ int error = 0;
+
+ if ((oid->oid_kind & CTLFLAG_KDB_SECURE) == 0)
+ /* We don't know what this is; be safe and block it. */
+ return (EPERM);
+
+ /*
+ * Unlike other policies, this one must be explicitly granted by a
+ * module in order to override the system securelevel setting.
+ */
+ MAC_POLICY_GRANT_NOSLEEP(kdb_check_sysctl, oid, req);
+ return (error);
+}
+
int
mac_ddb_command_register(struct db_command_table *table, struct db_command *cmd)
{
diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h
--- a/sys/security/mac/mac_policy.h
+++ b/sys/security/mac/mac_policy.h
@@ -260,6 +260,8 @@
struct ipq *q, struct label *qlabel);
typedef int (*mpo_kdb_check_backend_t)(struct kdb_dbbe *be);
+typedef int (*mpo_kdb_check_sysctl_t)(struct sysctl_oid *oid,
+ struct sysctl_req *req);
typedef int (*mpo_kenv_check_dump_t)(struct ucred *cred);
typedef int (*mpo_kenv_check_get_t)(struct ucred *cred, char *name);
@@ -777,6 +779,7 @@
mpo_ipq_update_t mpo_ipq_update;
mpo_kdb_check_backend_t mpo_kdb_check_backend;
+ mpo_kdb_check_sysctl_t mpo_kdb_check_sysctl;
mpo_kenv_check_dump_t mpo_kenv_check_dump;
mpo_kenv_check_get_t mpo_kenv_check_get;
diff --git a/sys/security/mac_ddb/mac_ddb.c b/sys/security/mac_ddb/mac_ddb.c
--- a/sys/security/mac_ddb/mac_ddb.c
+++ b/sys/security/mac_ddb/mac_ddb.c
@@ -358,6 +358,21 @@
return (EACCES);
}
+static int
+mac_ddb_check_sysctl(struct sysctl_oid *oid __diagused,
+ struct sysctl_req *req __unused)
+{
+
+ KASSERT((oid->oid_kind & CTLFLAG_KDB_SECURE) != 0,
+ ("%s: unhandled OID %p", __func__, oid));
+
+ /*
+ * It's ok to enable access to DDB since it cannot be used to modify the
+ * system securelevel when this policy is loaded.
+ */
+ return (0);
+}
+
/*
* Register functions with MAC Framework policy entry points.
*/
@@ -369,5 +384,6 @@
.mpo_ddb_command_exec = mac_ddb_command_exec,
.mpo_kdb_check_backend = mac_ddb_check_backend,
+ .mpo_kdb_check_sysctl = mac_ddb_check_sysctl,
};
MAC_POLICY_SET(&mac_ddb_ops, mac_ddb, "MAC/DDB", 0, NULL);
diff --git a/sys/security/mac_stub/mac_stub.c b/sys/security/mac_stub/mac_stub.c
--- a/sys/security/mac_stub/mac_stub.c
+++ b/sys/security/mac_stub/mac_stub.c
@@ -502,6 +502,13 @@
return (0);
}
+static int
+stub_kdb_check_sysctl(struct sysctl_oid *oidp, struct sysctl_req *req)
+{
+
+ return (0);
+}
+
static int
stub_kenv_check_dump(struct ucred *cred)
{
@@ -1756,6 +1763,7 @@
.mpo_ipq_reassemble = stub_ipq_reassemble,
.mpo_kdb_check_backend = stub_kdb_check_backend,
+ .mpo_kdb_check_sysctl = stub_kdb_check_sysctl,
.mpo_kenv_check_dump = stub_kenv_check_dump,
.mpo_kenv_check_get = stub_kenv_check_get,
diff --git a/sys/security/mac_test/mac_test.c b/sys/security/mac_test/mac_test.c
--- a/sys/security/mac_test/mac_test.c
+++ b/sys/security/mac_test/mac_test.c
@@ -902,6 +902,16 @@
return (0);
}
+COUNTER_DECL(kdb_sysctl_check);
+static int
+test_kdb_check_sysctl(struct sysctl_oid *oid, struct sysctl_req *req)
+{
+
+ COUNTER_INC(kdb_sysctl_check);
+
+ return (0);
+}
+
COUNTER_DECL(kenv_check_dump);
static int
test_kenv_check_dump(struct ucred *cred)
@@ -3116,6 +3126,7 @@
.mpo_ipq_update = test_ipq_update,
.mpo_kdb_check_backend = test_kdb_check_backend,
+ .mpo_kdb_check_sysctl = test_kdb_check_sysctl,
.mpo_kenv_check_dump = test_kenv_check_dump,
.mpo_kenv_check_get = test_kenv_check_get,
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -96,16 +96,23 @@
#define CTLFLAG_DYING 0x00010000 /* Oid is being removed */
#define CTLFLAG_CAPRD 0x00008000 /* Can be read in capability mode */
#define CTLFLAG_CAPWR 0x00004000 /* Can be written in capability mode */
+#define CTLFLAG_CAPRW (CTLFLAG_CAPRD|CTLFLAG_CAPWR)
#define CTLFLAG_STATS 0x00002000 /* Statistics, not a tuneable */
#define CTLFLAG_NOFETCH 0x00001000 /* Don't fetch tunable from getenv() */
-#define CTLFLAG_CAPRW (CTLFLAG_CAPRD|CTLFLAG_CAPWR)
/*
* This is transient flag to be used until all sysctl handlers are converted
* to not lock Giant.
* One, and only one of CTLFLAG_MPSAFE or CTLFLAG_NEEDGIANT is required
* for SYSCTL_PROC and SYSCTL_NODE.
*/
-#define CTLFLAG_NEEDGIANT 0x00000800 /* Handler require Giant */
+#define CTLFLAG_NEEDGIANT 0x00000800 /* Handler require Giant */
+/*
+ * sysctls with KDB_SECURE set allow a privileged user to break into the kernel
+ * debugger. Since KDB can be used to lower the system's securelevel, they are
+ * normally subject to the same restrictions as CTLFLAG_SECURE, except that
+ * MAC's KDB hooks may be used to override the securelevel check.
+ */
+#define CTLFLAG_KDB_SECURE 0x00000400 /* Enables KDB access */
/*
* Secure level. Note that CTLFLAG_SECURE == CTLFLAG_SECURE1.

File Metadata

Mime Type
text/plain
Expires
Thu, Aug 6, 2:58 AM (21 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36066059
Default Alt Text
D37106.diff (9 KB)

Event Timeline