Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163197219
D35371.id106516.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D35371.id106516.diff
View Options
Index: sys/ddb/ddb.h
===================================================================
--- sys/ddb/ddb.h
+++ sys/ddb/ddb.h
@@ -99,6 +99,7 @@
extern struct db_command_table db_cmd_table;
extern struct db_command_table db_show_table;
extern struct db_command_table db_show_all_table;
+extern struct db_command_table db_show_active_table;
/*
* Type signature for a function implementing a ddb command.
Index: sys/modules/Makefile
===================================================================
--- sys/modules/Makefile
+++ sys/modules/Makefile
@@ -218,6 +218,7 @@
lpt \
${_mac_biba} \
${_mac_bsdextended} \
+ ${_mac_ddb} \
${_mac_ifoff} \
${_mac_lomac} \
${_mac_mls} \
@@ -545,6 +546,9 @@
.if ${KERN_OPTS:MMAC} || defined(ALL_MODULES)
_mac_biba= mac_biba
_mac_bsdextended= mac_bsdextended
+.if ${KERN_OPTS:MDDB} || defined(ALL_MODULES)
+_mac_ddb= mac_ddb
+.endif
_mac_ifoff= mac_ifoff
_mac_lomac= mac_lomac
_mac_mls= mac_mls
Index: sys/modules/mac_ddb/Makefile
===================================================================
--- /dev/null
+++ sys/modules/mac_ddb/Makefile
@@ -0,0 +1,6 @@
+.PATH: ${SRCTOP}/sys/security/mac_ddb
+
+KMOD= mac_ddb
+SRCS= mac_ddb.c
+
+.include <bsd.kmod.mk>
Index: sys/security/mac_ddb/mac_ddb.c
===================================================================
--- /dev/null
+++ sys/security/mac_ddb/mac_ddb.c
@@ -0,0 +1,351 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021-2022 Juniper Networks
+ *
+ * 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 <sys/param.h>
+#include <sys/kdb.h>
+#include <sys/module.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+
+#include <ddb/ddb.h>
+
+#include <security/mac/mac_policy.h>
+
+/*
+ * This module provides a limited interface to the ddb(4) kernel debugger. The
+ * intent is to allow execution of useful debugging commands while disallowing
+ * the execution of commands which may be used to inspect/modify arbitrary
+ * system memory.
+ *
+ * Commands which are deterministic in their output or effect will be flagged
+ * as safe for execution via the DB_CMD_SAFE flag.
+ *
+ * Other commands are valid within this context so long as there is some
+ * constraint placed on their input arguments. This applies to most 'show'
+ * commands which accept an arbitrary address. If the provided address can be
+ * validated as a real instance of the object (e.g. the 'show proc' address
+ * points to a real struct proc in the process list), then the command may be
+ * executed. Commands requiring this must register a validation function, and
+ * will be flagged with the DB_CMD_VALIDATE flag.
+ *
+ * Any other commands not appearing in the allow-lists below are either
+ * considered to be unsafe for execution or are unrecognized by this module.
+ * Their execution will be disallowed.
+ *
+ * All commands under the 'show all' or 'show active' tables are considered to
+ * be safe for execution.
+ */
+
+#define DB_CMD_SAFE DB_MAC1
+#define DB_CMD_VALIDATE DB_MAC2
+
+typedef int db_validation_fn_t(db_expr_t addr, bool have_addr, db_expr_t count,
+ char *modif);
+
+struct cmd_list_item {
+ const char *name;
+ db_validation_fn_t *validate_fn;
+};
+
+/* List of top-level ddb(4) commands which are allowed by this policy. */
+static const struct cmd_list_item command_list[] = {
+ { "acttrace", NULL },
+ { "alltrace", NULL },
+ { "b", NULL },
+ { "break", NULL },
+ { "bt", NULL },
+ { "c", NULL },
+ { "capture", NULL },
+ { "continue", NULL },
+ { "d", NULL },
+ { "delete", NULL },
+ { "dhwatch", NULL },
+ { "dump", NULL },
+ { "dwatch", NULL },
+ { "halt", NULL },
+ { "hwatch", NULL },
+ { "kill", NULL },
+ { "kldstat", NULL },
+ { "next", NULL },
+ { "panic", NULL },
+ { "ps", NULL },
+ { "reboot", NULL },
+ { "reset", NULL },
+ { "run", NULL },
+ { "s", NULL },
+ { "script", NULL },
+ { "scripts", NULL },
+ { "set", NULL },
+ { "step", NULL },
+ { "sysctl", NULL },
+ { "t", NULL },
+ { "textdump", NULL },
+ { "trace", NULL },
+ { "unscript", NULL },
+ { "until", NULL },
+ { "watch", NULL },
+ { "watchdog", NULL },
+ { "where", NULL },
+};
+
+/* List of ddb(4) 'show' commands which are allowed by this policy. */
+static const struct cmd_list_item show_command_list[] = {
+ { "allchains", NULL },
+ { "alllocks", NULL },
+ { "allrman", NULL },
+ { "apic", NULL },
+ { "breaks", NULL },
+ { "callout_last", NULL },
+ { "conifhk", NULL },
+ { "cpusets", NULL },
+ { "crypto", NULL },
+ { "devmap", NULL },
+ { "dmar", NULL },
+ { "dmars", NULL },
+ { "domainsets", NULL },
+ { "dpcpu_off", NULL },
+ { "files", NULL },
+ { "freepages", NULL },
+ { "idt", NULL },
+ { "intr", NULL },
+ { "intrcnt", NULL },
+ { "ioapic", NULL },
+ { "irqs", NULL },
+ { "ktr", NULL },
+ { "lapic", NULL },
+ { "lock", NULL },
+ { "lockedbufs", NULL },
+ { "lockedvnods", NULL },
+ { "locktree", NULL },
+ { "malloc", NULL },
+ { "msgbuf", NULL },
+ { "page", NULL },
+ { "pageq", NULL },
+ { "panic", NULL },
+ { "pciregs", NULL },
+ { "pcpu", NULL },
+ { "pgrpdump", NULL },
+ { "physmem", NULL },
+ { "registers", NULL },
+ { "rmans", NULL },
+ { "routetable", NULL },
+ { "rtc", NULL },
+ { "sysinit", NULL },
+ { "sysregs", NULL },
+ { "threads", NULL },
+ { "turnstile", NULL },
+ { "uma", NULL },
+ { "umacache", NULL },
+ { "vmochk", NULL },
+ { "vmopag", NULL },
+ { "vnet_sysinit", NULL },
+ { "vnet_sysuninit", NULL },
+ { "watches", NULL },
+ { "witness", NULL },
+};
+
+static int
+command_match(struct db_command *cmd, struct cmd_list_item item)
+{
+ db_validation_fn_t *vfn;
+ int n;
+
+ n = strcmp(cmd->name, item.name);
+ if (n != 0)
+ return (n);
+
+ /* Got an exact match. Update the command struct */
+ vfn = item.validate_fn;
+ if (vfn != NULL) {
+ cmd->flag |= DB_CMD_VALIDATE;
+ cmd->mac_priv = vfn;
+ } else {
+ cmd->flag |= DB_CMD_SAFE;
+ }
+ return (0);
+}
+
+static void
+mac_ddb_init(struct mac_policy_conf *conf)
+{
+ struct db_command *cmd, *prev;
+ int i, n;
+
+ /* The command lists are sorted lexographically, as are our arrays. */
+
+ /* Register basic commands. */
+ for (i = 0, cmd = prev = NULL; i < nitems(command_list); i++) {
+ LIST_FOREACH_FROM(cmd, &db_cmd_table, next) {
+ n = command_match(cmd, command_list[i]);
+ if (n == 0) {
+ /* Got an exact match. */
+ prev = cmd;
+ break;
+ } else if (n > 0) {
+ /* Desired command is not registered. */
+ break;
+ }
+ }
+
+ /* Next search begins at the previous match. */
+ cmd = prev;
+ }
+
+ /* Register 'show' commands which require validation. */
+ for (i = 0, cmd = prev = NULL; i < nitems(show_command_list); i++) {
+ LIST_FOREACH_FROM(cmd, &db_show_table, next) {
+ n = command_match(cmd, show_command_list[i]);
+ if (n == 0) {
+ /* Got an exact match. */
+ prev = cmd;
+ break;
+ } else if (n > 0) {
+ /* Desired command is not registered. */
+ break;
+ }
+ }
+
+ /* Next search begins at the previous match. */
+ cmd = prev;
+ }
+
+ /* All commands in the 'show all' and 'show active' tables are safe. */
+ LIST_FOREACH(cmd, &db_show_all_table, next)
+ cmd->flag |= DB_CMD_SAFE;
+ LIST_FOREACH(cmd, &db_show_active_table, next)
+ cmd->flag |= DB_CMD_SAFE;
+
+#ifdef INVARIANTS
+ /*
+ * Verify the lists are sorted correctly. Do this at the end of the
+ * function to allow reset.
+ */
+ const char *a, *b;
+
+ for (i = 0; i < nitems(command_list) - 1; i++) {
+ a = command_list[i].name;
+ b = command_list[i + 1].name;
+ if (strcmp(a, b) > 0)
+ panic("%s: command_list[] not alphabetical: %s,%s",
+ __func__, a, b);
+ }
+ for (i = 0; i < nitems(show_command_list) - 1; i++) {
+ a = show_command_list[i].name;
+ b = show_command_list[i + 1].name;
+ if (strcmp(a, b) > 0)
+ panic("%s: show_command_list[] not alphabetical: %s,%s",
+ __func__, a, b);
+ }
+
+#endif
+}
+
+static int
+mac_ddb_command_register(struct db_command_table *table,
+ struct db_command *cmd)
+{
+ int i, n;
+
+ /* These commands are always safe. */
+ if (table == &db_show_all_table || table == &db_show_active_table) {
+ cmd->flag |= DB_CMD_SAFE;
+ return (0);
+ }
+
+ /* For other commands, search the allow-lists. */
+ if (table == &db_show_table) {
+ for (i = 0; i < nitems(show_command_list); i++) {
+ n = command_match(cmd, show_command_list[i]);
+ if (n == 0)
+ /* Got an exact match. */
+ return (0);
+ else if (n > 0)
+ /* Command is not in the policy list. */
+ break;
+ }
+ } else if (table == &db_cmd_table) {
+ for (i = 0; i < nitems(command_list); i++) {
+ n = command_match(cmd, command_list[i]);
+ if (n == 0)
+ /* Got an exact match. */
+ return (0);
+ else if (n > 0)
+ /* Command is not in the policy list. */
+ break;
+ }
+
+ }
+
+ /* The command will not be registered. */
+ return (EACCES);
+}
+
+static int
+mac_ddb_command_exec(struct db_command *cmd, db_expr_t addr,
+ bool have_addr, db_expr_t count, char *modif)
+{
+ db_validation_fn_t *vfn = cmd->mac_priv;
+
+ /* Validate the command and args based on policy. */
+ if ((cmd->flag & DB_CMD_VALIDATE) != 0) {
+ MPASS(vfn != NULL);
+ if (vfn(addr, have_addr, count, modif) == 0)
+ return (0);
+ } else if ((cmd->flag & DB_CMD_SAFE) != 0)
+ return (0);
+
+ return (EACCES);
+}
+
+static int
+mac_ddb_check_backend(struct kdb_dbbe *be)
+{
+
+ /* Only allow DDB backend to execute. */
+ if (strcmp(be->dbbe_name, "ddb") == 0)
+ return (0);
+
+ return (EACCES);
+}
+
+/*
+ * Register functions with MAC Framework policy entry points.
+ */
+static struct mac_policy_ops mac_ddb_ops =
+{
+ .mpo_init = mac_ddb_init,
+
+ .mpo_ddb_command_register = mac_ddb_command_register,
+ .mpo_ddb_command_exec = mac_ddb_command_exec,
+
+ .mpo_kdb_check_backend = mac_ddb_check_backend,
+};
+MAC_POLICY_SET(&mac_ddb_ops, mac_ddb, "MAC/DDB", 0, NULL);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jul 21, 11:30 PM (5 m, 19 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35337436
Default Alt Text
D35371.id106516.diff (10 KB)
Attached To
Mode
D35371: mac: add new mac_ddb(4) policy
Attached
Detach File
Event Timeline
Log In to Comment