Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164956703
D37106.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D37106.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D37106: kdb: Conditionally permit breaking to DDB with a raised securelevel
Attached
Detach File
Event Timeline
Log In to Comment