Index: sys/conf/files =================================================================== --- sys/conf/files +++ sys/conf/files @@ -5115,6 +5115,7 @@ 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_debugger.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 Index: sys/ddb/db_command.c =================================================================== --- sys/ddb/db_command.c +++ sys/ddb/db_command.c @@ -59,6 +59,8 @@ #include #include +#include + /* * Exported global variables */ @@ -223,6 +225,13 @@ { 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); @@ -467,6 +476,12 @@ *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. */ Index: sys/ddb/ddb.h =================================================================== --- sys/ddb/ddb.h +++ sys/ddb/ddb.h @@ -117,8 +117,11 @@ #define CS_MORE 0x2 /* standard syntax, but may have other words * at end */ #define CS_SET_DOT 0x100 /* set dot after command */ +#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 */ }; /* Index: sys/kern/subr_kdb.c =================================================================== --- sys/kern/subr_kdb.c +++ sys/kern/subr_kdb.c @@ -53,6 +53,8 @@ #include #endif +#include + u_char __read_frequently kdb_active = 0; static void *kdb_jmpbufp = NULL; struct kdb_dbbe *kdb_dbbe = NULL; @@ -731,6 +733,15 @@ 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; Index: sys/security/mac/mac_debugger.c =================================================================== --- /dev/null +++ sys/security/mac/mac_debugger.c @@ -0,0 +1,69 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021-2022 Juniper Networks + * + * This software was developed by Mitchell Horne + * 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 +#include +#include + +#include + +#include +#include +#include + +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); +} Index: sys/security/mac/mac_framework.h =================================================================== --- sys/security/mac/mac_framework.h +++ sys/security/mac/mac_framework.h @@ -65,6 +65,7 @@ struct inpcb; struct ip6q; struct ipq; +struct kdb_dbbe; struct ksem; struct label; struct m_tag; @@ -92,6 +93,8 @@ #include /* XXX acl_type_t */ #include /* accmode_t */ +#include /* 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_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 @@ 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); Index: sys/security/mac/mac_policy.h =================================================================== --- sys/security/mac/mac_policy.h +++ sys/security/mac/mac_policy.h @@ -72,12 +72,14 @@ 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 +170,12 @@ 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 +257,8 @@ 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 +730,9 @@ 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 +774,8 @@ 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; Index: sys/security/mac_stub/mac_stub.c =================================================================== --- sys/security/mac_stub/mac_stub.c +++ sys/security/mac_stub/mac_stub.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,8 @@ #include #include +#include + #include #include @@ -314,6 +317,22 @@ } +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) @@ -476,6 +495,13 @@ } +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 @@ .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 @@ .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, Index: sys/security/mac_test/mac_test.c =================================================================== --- sys/security/mac_test/mac_test.c +++ sys/security/mac_test/mac_test.c @@ -69,6 +69,8 @@ #include #include +#include + #include #include @@ -453,6 +455,28 @@ 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 @@ 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 @@ .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 @@ .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,