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
This commit is contained in:
Mitchell Horne 2022-07-18 17:23:16 -04:00 committed by Allan Jude
parent a305b20ead
commit 2449b9e5fe
9 changed files with 197 additions and 0 deletions

View File

@ -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

View File

@ -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.
*/

View File

@ -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 */
};
/*

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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)
@ -476,6 +495,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,

View File

@ -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,