aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchell Horne <mhorne@FreeBSD.org>2022-07-18 21:23:16 +0000
committerAllan Jude <allanjude@FreeBSD.org>2022-07-18 22:06:13 +0000
commit2449b9e5fe565be757a4b29093fd1c9c6ffcf3c9 (patch)
tree305ce3103d0aff04757876d9e78ca2b5591636d2
parenta305b20ead13bb29880e15ff20c3bb83b5397a82 (diff)
downloadsrc-2449b9e5fe565be757a4b29093fd1c9c6ffcf3c9.tar.gz
src-2449b9e5fe565be757a4b29093fd1c9c6ffcf3c9.zip
mac: kdb/ddb framework hooks
Add three simple hooks to the debugger allowing for a loaded MAC policy to intervene if desired: 1. Before invoking the kdb backend 2. Before ddb command registration 3. Before ddb command execution We extend struct db_command with a private pointer and two flag bits reserved for policy use. Reviewed by: markj Sponsored by: Juniper Networks, Inc. Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D35370
-rw-r--r--sys/conf/files1
-rw-r--r--sys/ddb/db_command.c16
-rw-r--r--sys/ddb/ddb.h3
-rw-r--r--sys/kern/subr_kdb.c11
-rw-r--r--sys/security/mac/mac_framework.h10
-rw-r--r--sys/security/mac/mac_kdb.c69
-rw-r--r--sys/security/mac/mac_policy.h17
-rw-r--r--sys/security/mac_stub/mac_stub.c31
-rw-r--r--sys/security/mac_test/mac_test.c39
9 files changed, 197 insertions, 0 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 30cd9eb7e741..4e1279adc073 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -5118,6 +5118,7 @@ security/audit/bsm_socket_type.c optional audit
security/audit/bsm_token.c optional audit
security/mac/mac_audit.c optional mac audit
security/mac/mac_cred.c optional mac
+security/mac/mac_kdb.c optional mac
security/mac/mac_framework.c optional mac
security/mac/mac_inet.c optional mac inet | mac inet6
security/mac/mac_inet6.c optional mac inet6
diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c
index 71e9b039d7a9..ab7bec8f2ffc 100644
--- a/sys/ddb/db_command.c
+++ b/sys/ddb/db_command.c
@@ -59,6 +59,8 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/setjmp.h>
+#include <security/mac/mac_framework.h>
+
/*
* Exported global variables
*/
@@ -236,6 +238,13 @@ db_command_register(struct db_command_table *list, struct db_command *cmd)
{
struct db_command *c, *last;
+#ifdef MAC
+ if (mac_ddb_command_register(list, cmd)) {
+ printf("%s: MAC policy refused registration of command %s\n",
+ __func__, cmd->name);
+ return;
+ }
+#endif
last = NULL;
LIST_FOREACH(c, list, next) {
int n = strcmp(cmd->name, c->name);
@@ -480,6 +489,13 @@ db_command(struct db_command **last_cmdp, struct db_command_table *cmd_table,
*last_cmdp = cmd;
if (cmd != NULL) {
+#ifdef MAC
+ if (mac_ddb_command_exec(cmd, addr, have_addr, count, modif)) {
+ db_printf("MAC prevented execution of command %s\n",
+ cmd->name);
+ return;
+ }
+#endif
/*
* Execute the command.
*/
diff --git a/sys/ddb/ddb.h b/sys/ddb/ddb.h
index dce4e80ac117..4c8a4f165461 100644
--- a/sys/ddb/ddb.h
+++ b/sys/ddb/ddb.h
@@ -119,8 +119,11 @@ struct db_command {
#define CS_SET_DOT 0x100 /* set dot after command */
#define DB_CMD_MEMSAFE 0x1000 /* Command does not allow reads or writes to
* arbitrary memory. */
+#define DB_MAC1 0x10000 /* For MAC policy use */
+#define DB_MAC2 0x20000
struct db_command_table *more; /* another level of command */
LIST_ENTRY(db_command) next; /* next entry in the command table */
+ void *mac_priv; /* For MAC policy use */
};
/*
diff --git a/sys/kern/subr_kdb.c b/sys/kern/subr_kdb.c
index 6aa8bd17e048..b1bf197be3dc 100644
--- a/sys/kern/subr_kdb.c
+++ b/sys/kern/subr_kdb.c
@@ -53,6 +53,8 @@ __FBSDID("$FreeBSD$");
#include <machine/smp.h>
#endif
+#include <security/mac/mac_framework.h>
+
u_char __read_frequently kdb_active = 0;
static void *kdb_jmpbufp = NULL;
struct kdb_dbbe *kdb_dbbe = NULL;
@@ -731,6 +733,15 @@ kdb_trap(int type, int code, struct trapframe *tf)
cngrab();
for (;;) {
+#ifdef MAC
+ if (mac_kdb_check_backend(be) != 0) {
+ printf("MAC prevented execution of KDB backend: %s\n",
+ be->dbbe_name);
+ /* Unhandled breakpoint traps are fatal. */
+ handled = 1;
+ break;
+ }
+#endif
handled = be->dbbe_trap(type, code);
if (be == kdb_dbbe)
break;
diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h
index 7a46fbedb28d..78a991fe10fe 100644
--- a/sys/security/mac/mac_framework.h
+++ b/sys/security/mac/mac_framework.h
@@ -65,6 +65,7 @@ struct image_params;
struct inpcb;
struct ip6q;
struct ipq;
+struct kdb_dbbe;
struct ksem;
struct label;
struct m_tag;
@@ -92,6 +93,8 @@ struct vop_setlabel_args;
#include <sys/acl.h> /* XXX acl_type_t */
#include <sys/types.h> /* accmode_t */
+#include <ddb/ddb.h> /* db_expr_t */
+
/*
* Entry points to the TrustedBSD MAC Framework from the remainder of the
* kernel: entry points are named based on a principle object type and an
@@ -130,6 +133,11 @@ void mac_cred_create_swapper(struct ucred *cred);
void mac_cred_destroy(struct ucred *);
void mac_cred_init(struct ucred *);
+int mac_ddb_command_register(struct db_command_table *table,
+ struct db_command *cmd);
+int mac_ddb_command_exec(struct db_command *cmd, db_expr_t addr,
+ bool have_addr, db_expr_t count, char *modif);
+
void mac_devfs_create_device(struct ucred *cred, struct mount *mp,
struct cdev *dev, struct devfs_dirent *de);
void mac_devfs_create_directory(struct mount *mp, char *dirname,
@@ -205,6 +213,8 @@ int mac_ipq_match(struct mbuf *m, struct ipq *q);
void mac_ipq_reassemble(struct ipq *q, struct mbuf *m);
void mac_ipq_update(struct mbuf *m, struct ipq *q);
+int mac_kdb_check_backend(struct kdb_dbbe *be);
+
int mac_kenv_check_dump(struct ucred *cred);
int mac_kenv_check_get(struct ucred *cred, char *name);
int mac_kenv_check_set(struct ucred *cred, char *name, char *value);
diff --git a/sys/security/mac/mac_kdb.c b/sys/security/mac/mac_kdb.c
new file mode 100644
index 000000000000..9082ec7d4580
--- /dev/null
+++ b/sys/security/mac/mac_kdb.c
@@ -0,0 +1,69 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021-2022 Klara Systems
+ *
+ * This software was developed by Mitchell Horne <mhorne@FreeBSD.org>
+ * under sponsorship from Juniper Networks and Klara Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "opt_mac.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <ddb/ddb.h>
+
+#include <security/mac/mac_framework.h>
+#include <security/mac/mac_internal.h>
+#include <security/mac/mac_policy.h>
+
+int
+mac_kdb_check_backend(struct kdb_dbbe *be)
+{
+ int error = 0;
+
+ MAC_POLICY_CHECK_NOSLEEP(kdb_check_backend, be);
+ return (error);
+}
+
+int
+mac_ddb_command_register(struct db_command_table *table, struct db_command *cmd)
+{
+ int error = 0;
+
+ MAC_POLICY_CHECK_NOSLEEP(ddb_command_register, table, cmd);
+ return (error);
+}
+
+int
+mac_ddb_command_exec(struct db_command *cmd, db_expr_t addr,
+ bool have_addr, db_expr_t count, char *modif)
+{
+ int error = 0;
+
+ MAC_POLICY_CHECK_NOSLEEP(ddb_command_exec, cmd, addr, have_addr,
+ count, modif);
+ return (error);
+}
diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h
index b875e6eb5487..97b3522abf51 100644
--- a/sys/security/mac/mac_policy.h
+++ b/sys/security/mac/mac_policy.h
@@ -66,18 +66,22 @@
#include <sys/acl.h> /* XXX acl_type_t */
#include <sys/types.h> /* XXX accmode_t */
+#include <ddb/ddb.h> /* XXX db_expr_t */
+
struct acl;
struct auditinfo;
struct auditinfo_addr;
struct bpf_d;
struct cdev;
struct componentname;
+struct db_command;
struct devfs_dirent;
struct ifnet;
struct image_params;
struct inpcb;
struct ip6q;
struct ipq;
+struct kdb_dbbe;
struct ksem;
struct label;
struct mac_policy_conf;
@@ -168,6 +172,12 @@ typedef int (*mpo_cred_internalize_label_t)(struct label *label,
typedef void (*mpo_cred_relabel_t)(struct ucred *cred,
struct label *newlabel);
+typedef int (*mpo_ddb_command_register_t)(struct db_command_table *table,
+ struct db_command *cmd);
+typedef int (*mpo_ddb_command_exec_t)(struct db_command *cmd,
+ db_expr_t addr, bool have_addr, db_expr_t count,
+ char *modif);
+
typedef void (*mpo_devfs_create_device_t)(struct ucred *cred,
struct mount *mp, struct cdev *dev,
struct devfs_dirent *de, struct label *delabel);
@@ -249,6 +259,8 @@ typedef void (*mpo_ipq_reassemble)(struct ipq *q, struct label *qlabel,
typedef void (*mpo_ipq_update_t)(struct mbuf *m, struct label *mlabel,
struct ipq *q, struct label *qlabel);
+typedef int (*mpo_kdb_check_backend_t)(struct kdb_dbbe *be);
+
typedef int (*mpo_kenv_check_dump_t)(struct ucred *cred);
typedef int (*mpo_kenv_check_get_t)(struct ucred *cred, char *name);
typedef int (*mpo_kenv_check_set_t)(struct ucred *cred, char *name,
@@ -720,6 +732,9 @@ struct mac_policy_ops {
mpo_cred_internalize_label_t mpo_cred_internalize_label;
mpo_cred_relabel_t mpo_cred_relabel;
+ mpo_ddb_command_register_t mpo_ddb_command_register;
+ mpo_ddb_command_exec_t mpo_ddb_command_exec;
+
mpo_devfs_create_device_t mpo_devfs_create_device;
mpo_devfs_create_directory_t mpo_devfs_create_directory;
mpo_devfs_create_symlink_t mpo_devfs_create_symlink;
@@ -761,6 +776,8 @@ struct mac_policy_ops {
mpo_ipq_reassemble mpo_ipq_reassemble;
mpo_ipq_update_t mpo_ipq_update;
+ mpo_kdb_check_backend_t mpo_kdb_check_backend;
+
mpo_kenv_check_dump_t mpo_kenv_check_dump;
mpo_kenv_check_get_t mpo_kenv_check_get;
mpo_kenv_check_set_t mpo_kenv_check_set;
diff --git a/sys/security/mac_stub/mac_stub.c b/sys/security/mac_stub/mac_stub.c
index 8174345f073a..6b32408b92fe 100644
--- a/sys/security/mac_stub/mac_stub.c
+++ b/sys/security/mac_stub/mac_stub.c
@@ -54,6 +54,7 @@
#include <sys/acl.h>
#include <sys/conf.h>
#include <sys/extattr.h>
+#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/ksem.h>
#include <sys/mount.h>
@@ -72,6 +73,8 @@
#include <sys/sem.h>
#include <sys/shm.h>
+#include <ddb/ddb.h>
+
#include <fs/devfs/devfs.h>
#include <net/bpfdesc.h>
@@ -314,6 +317,22 @@ stub_cred_relabel(struct ucred *cred, struct label *newlabel)
}
+static int
+stub_ddb_command_exec(struct db_command *cmd, db_expr_t addr, bool have_addr,
+ db_expr_t count, char *modif)
+{
+
+ return (0);
+}
+
+static int
+stub_ddb_command_register(struct db_command_table *table,
+ struct db_command *cmd)
+{
+
+ return (0);
+}
+
static void
stub_devfs_create_device(struct ucred *cred, struct mount *mp,
struct cdev *dev, struct devfs_dirent *de, struct label *delabel)
@@ -477,6 +496,13 @@ stub_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
}
static int
+stub_kdb_check_backend(struct kdb_dbbe *be)
+{
+
+ return (0);
+}
+
+static int
stub_kenv_check_dump(struct ucred *cred)
{
@@ -1685,6 +1711,9 @@ static struct mac_policy_ops stub_ops =
.mpo_cred_internalize_label = stub_internalize_label,
.mpo_cred_relabel= stub_cred_relabel,
+ .mpo_ddb_command_exec = stub_ddb_command_exec,
+ .mpo_ddb_command_register = stub_ddb_command_register,
+
.mpo_devfs_create_device = stub_devfs_create_device,
.mpo_devfs_create_directory = stub_devfs_create_directory,
.mpo_devfs_create_symlink = stub_devfs_create_symlink,
@@ -1726,6 +1755,8 @@ static struct mac_policy_ops stub_ops =
.mpo_ipq_update = stub_ipq_update,
.mpo_ipq_reassemble = stub_ipq_reassemble,
+ .mpo_kdb_check_backend = stub_kdb_check_backend,
+
.mpo_kenv_check_dump = stub_kenv_check_dump,
.mpo_kenv_check_get = stub_kenv_check_get,
.mpo_kenv_check_set = stub_kenv_check_set,
diff --git a/sys/security/mac_test/mac_test.c b/sys/security/mac_test/mac_test.c
index 12291fbd37d9..48c8fe782909 100644
--- a/sys/security/mac_test/mac_test.c
+++ b/sys/security/mac_test/mac_test.c
@@ -69,6 +69,8 @@
#include <sys/sx.h>
#include <sys/sysctl.h>
+#include <ddb/ddb.h>
+
#include <fs/devfs/devfs.h>
#include <net/bpfdesc.h>
@@ -453,6 +455,28 @@ test_cred_relabel(struct ucred *cred, struct label *newlabel)
COUNTER_INC(cred_relabel);
}
+COUNTER_DECL(ddb_command_exec);
+static int
+test_ddb_command_exec(struct db_command *cmd, db_expr_t addr, bool have_addr,
+ db_expr_t count, char *modif)
+{
+
+ COUNTER_INC(ddb_command_exec);
+
+ return (0);
+}
+
+COUNTER_DECL(ddb_command_register);
+static int
+test_ddb_command_register(struct db_command_table *table,
+ struct db_command *cmd)
+{
+
+ COUNTER_INC(ddb_command_register);
+
+ return (0);
+}
+
COUNTER_DECL(devfs_create_device);
static void
test_devfs_create_device(struct ucred *cred, struct mount *mp,
@@ -868,6 +892,16 @@ test_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
COUNTER_INC(ipq_update);
}
+COUNTER_DECL(kdb_backend_check);
+static int
+test_kdb_check_backend(struct kdb_dbbe *be)
+{
+
+ COUNTER_INC(kdb_backend_check);
+
+ return (0);
+}
+
COUNTER_DECL(kenv_check_dump);
static int
test_kenv_check_dump(struct ucred *cred)
@@ -3022,6 +3056,9 @@ static struct mac_policy_ops test_ops =
.mpo_cred_internalize_label = test_cred_internalize_label,
.mpo_cred_relabel = test_cred_relabel,
+ .mpo_ddb_command_exec = test_ddb_command_exec,
+ .mpo_ddb_command_register = test_ddb_command_register,
+
.mpo_devfs_create_device = test_devfs_create_device,
.mpo_devfs_create_directory = test_devfs_create_directory,
.mpo_devfs_create_symlink = test_devfs_create_symlink,
@@ -3078,6 +3115,8 @@ static struct mac_policy_ops test_ops =
.mpo_ipq_reassemble = test_ipq_reassemble,
.mpo_ipq_update = test_ipq_update,
+ .mpo_kdb_check_backend = test_kdb_check_backend,
+
.mpo_kenv_check_dump = test_kenv_check_dump,
.mpo_kenv_check_get = test_kenv_check_get,
.mpo_kenv_check_set = test_kenv_check_set,