xref: /freebsd/sys/security/mac_ddb/mac_ddb.c (revision 3a3af6b2)
1287d467cSMitchell Horne /*-
2287d467cSMitchell Horne  * SPDX-License-Identifier: BSD-2-Clause
3287d467cSMitchell Horne  *
4287d467cSMitchell Horne  * Copyright (c) 2021-2022 Klara Systems
5287d467cSMitchell Horne  *
6287d467cSMitchell Horne  * This software was developed by Mitchell Horne <mhorne@FreeBSD.org>
7287d467cSMitchell Horne  * under sponsorship from Juniper Networks and Klara Systems.
8287d467cSMitchell Horne  *
9287d467cSMitchell Horne  * Redistribution and use in source and binary forms, with or without
10287d467cSMitchell Horne  * modification, are permitted provided that the following conditions
11287d467cSMitchell Horne  * are met:
12287d467cSMitchell Horne  *
13287d467cSMitchell Horne  * 1. Redistributions of source code must retain the above copyright
14287d467cSMitchell Horne  *    notice, this list of conditions and the following disclaimer.
15287d467cSMitchell Horne  * 2. Redistributions in binary form must reproduce the above copyright
16287d467cSMitchell Horne  *    notice, this list of conditions and the following disclaimer in the
17287d467cSMitchell Horne  *    documentation and/or other materials provided with the distribution.
18287d467cSMitchell Horne  *
19287d467cSMitchell Horne  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20287d467cSMitchell Horne  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21287d467cSMitchell Horne  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22287d467cSMitchell Horne  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23287d467cSMitchell Horne  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24287d467cSMitchell Horne  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25287d467cSMitchell Horne  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26287d467cSMitchell Horne  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27287d467cSMitchell Horne  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28287d467cSMitchell Horne  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29287d467cSMitchell Horne  */
30287d467cSMitchell Horne 
31287d467cSMitchell Horne #include <sys/param.h>
324e2121c1SMitchell Horne #include <sys/jail.h>
33287d467cSMitchell Horne #include <sys/kdb.h>
34287d467cSMitchell Horne #include <sys/module.h>
354e2121c1SMitchell Horne #include <sys/mount.h>
36287d467cSMitchell Horne #include <sys/proc.h>
374e2121c1SMitchell Horne #include <sys/queue.h>
384e2121c1SMitchell Horne #include <sys/rman.h>
39287d467cSMitchell Horne #include <sys/sysctl.h>
40287d467cSMitchell Horne 
414e2121c1SMitchell Horne #include <net/vnet.h>
424e2121c1SMitchell Horne 
43287d467cSMitchell Horne #include <ddb/ddb.h>
44287d467cSMitchell Horne #include <ddb/db_command.h>
45287d467cSMitchell Horne 
46287d467cSMitchell Horne #include <security/mac/mac_policy.h>
47287d467cSMitchell Horne 
48287d467cSMitchell Horne /*
49287d467cSMitchell Horne  * This module provides a limited interface to the ddb(4) kernel debugger. The
50287d467cSMitchell Horne  * intent is to allow execution of useful debugging commands while disallowing
51287d467cSMitchell Horne  * the execution of commands which may be used to inspect/modify arbitrary
52287d467cSMitchell Horne  * system memory.
53287d467cSMitchell Horne  *
54287d467cSMitchell Horne  * Commands which are deterministic in their output or effect and that have
55287d467cSMitchell Horne  * been flagged with DB_CMD_MEMSAFE in their definition will be allowed.
56287d467cSMitchell Horne  *
57287d467cSMitchell Horne  * Other commands are valid within this context so long as there is some
58287d467cSMitchell Horne  * constraint placed on their input arguments. This applies to most 'show'
59287d467cSMitchell Horne  * commands which accept an arbitrary address. If the provided address can be
60287d467cSMitchell Horne  * validated as a real instance of the object (e.g. the 'show proc' address
61287d467cSMitchell Horne  * points to a real struct proc in the process list), then the command may be
62287d467cSMitchell Horne  * executed. This module defines several validation functions which are used to
63287d467cSMitchell Horne  * conditionally allow or block the execution of some commands. For these
64287d467cSMitchell Horne  * commands we define and apply the DB_CMD_VALIDATE flag.
65287d467cSMitchell Horne  *
66287d467cSMitchell Horne  * Any other commands not flagged with DM_CMD_MEMSAFE or DB_CMD_VALIDATE are
67287d467cSMitchell Horne  * considered unsafe for execution.
68287d467cSMitchell Horne  */
69287d467cSMitchell Horne 
70287d467cSMitchell Horne #define	DB_CMD_VALIDATE		DB_MAC1
71287d467cSMitchell Horne 
72287d467cSMitchell Horne typedef int db_validation_fn_t(db_expr_t addr, bool have_addr, db_expr_t count,
73287d467cSMitchell Horne     char *modif);
74287d467cSMitchell Horne 
75287d467cSMitchell Horne static db_validation_fn_t	db_thread_valid;
764e2121c1SMitchell Horne static db_validation_fn_t	db_show_ffs_valid;
774e2121c1SMitchell Horne static db_validation_fn_t	db_show_prison_valid;
784e2121c1SMitchell Horne static db_validation_fn_t	db_show_proc_valid;
794e2121c1SMitchell Horne static db_validation_fn_t	db_show_rman_valid;
80b43b8f81SJohn Baldwin #ifdef VIMAGE
814e2121c1SMitchell Horne static db_validation_fn_t	db_show_vnet_valid;
82b43b8f81SJohn Baldwin #endif
83287d467cSMitchell Horne 
84287d467cSMitchell Horne struct cmd_list_item {
85287d467cSMitchell Horne 	const char *name;
86287d467cSMitchell Horne 	db_validation_fn_t *validate_fn;
87287d467cSMitchell Horne };
88287d467cSMitchell Horne 
89287d467cSMitchell Horne /* List of top-level ddb(4) commands which are allowed by this policy. */
90287d467cSMitchell Horne static const struct cmd_list_item command_list[] = {
91287d467cSMitchell Horne 	{ "thread",	db_thread_valid },
92287d467cSMitchell Horne };
93287d467cSMitchell Horne 
94287d467cSMitchell Horne /* List of ddb(4) 'show' commands which are allowed by this policy. */
95287d467cSMitchell Horne static const struct cmd_list_item show_command_list[] = {
964e2121c1SMitchell Horne 	{ "ffs",	db_show_ffs_valid },
974e2121c1SMitchell Horne 	{ "prison",	db_show_prison_valid },
984e2121c1SMitchell Horne 	{ "proc",	db_show_proc_valid },
994e2121c1SMitchell Horne 	{ "rman",	db_show_rman_valid },
100287d467cSMitchell Horne 	{ "thread",	db_thread_valid },
101b43b8f81SJohn Baldwin #ifdef VIMAGE
1024e2121c1SMitchell Horne 	{ "vnet",	db_show_vnet_valid },
103b43b8f81SJohn Baldwin #endif
104287d467cSMitchell Horne };
105287d467cSMitchell Horne 
106287d467cSMitchell Horne static int
db_thread_valid(db_expr_t addr,bool have_addr,db_expr_t count,char * modif)107287d467cSMitchell Horne db_thread_valid(db_expr_t addr, bool have_addr, db_expr_t count, char *modif)
108287d467cSMitchell Horne {
109287d467cSMitchell Horne 	struct thread *thr;
110287d467cSMitchell Horne 	lwpid_t tid;
111287d467cSMitchell Horne 
112287d467cSMitchell Horne 	/* Default will show the current proc. */
113287d467cSMitchell Horne 	if (!have_addr)
114287d467cSMitchell Horne 		return (0);
115287d467cSMitchell Horne 
116287d467cSMitchell Horne 	/* Validate the provided addr OR tid against the thread list. */
117287d467cSMitchell Horne 	tid = db_hex2dec(addr);
118287d467cSMitchell Horne 	for (thr = kdb_thr_first(); thr != NULL; thr = kdb_thr_next(thr)) {
119287d467cSMitchell Horne 		if ((void *)thr == (void *)addr || tid == thr->td_tid)
120287d467cSMitchell Horne 			return (0);
121287d467cSMitchell Horne 	}
122287d467cSMitchell Horne 
123287d467cSMitchell Horne 	return (EACCES);
124287d467cSMitchell Horne }
125287d467cSMitchell Horne 
126287d467cSMitchell Horne static int
db_show_ffs_valid(db_expr_t addr,bool have_addr,db_expr_t count,char * modif)1274e2121c1SMitchell Horne db_show_ffs_valid(db_expr_t addr, bool have_addr, db_expr_t count, char *modif)
1284e2121c1SMitchell Horne {
1294e2121c1SMitchell Horne 	struct mount *mp;
1304e2121c1SMitchell Horne 
1314e2121c1SMitchell Horne 	/* No addr will show all mounts. */
1324e2121c1SMitchell Horne 	if (!have_addr)
1334e2121c1SMitchell Horne 		return (0);
1344e2121c1SMitchell Horne 
1354e2121c1SMitchell Horne 	TAILQ_FOREACH(mp, &mountlist, mnt_list)
1364e2121c1SMitchell Horne 		if ((void *)mp == (void *)addr)
1374e2121c1SMitchell Horne 			return (0);
1384e2121c1SMitchell Horne 
1394e2121c1SMitchell Horne 	return (EACCES);
1404e2121c1SMitchell Horne }
1414e2121c1SMitchell Horne 
1424e2121c1SMitchell Horne static int
db_show_prison_valid(db_expr_t addr,bool have_addr,db_expr_t count,char * modif)1434e2121c1SMitchell Horne db_show_prison_valid(db_expr_t addr, bool have_addr, db_expr_t count,
1444e2121c1SMitchell Horne     char *modif)
1454e2121c1SMitchell Horne {
1464e2121c1SMitchell Horne 	struct prison *pr;
1474e2121c1SMitchell Horne 	int pr_id;
1484e2121c1SMitchell Horne 
1494e2121c1SMitchell Horne 	if (!have_addr || addr == 0)
1504e2121c1SMitchell Horne 		return (0);
1514e2121c1SMitchell Horne 
1524e2121c1SMitchell Horne 	/* prison can match by pointer address or ID. */
1534e2121c1SMitchell Horne 	pr_id = (int)addr;
1544e2121c1SMitchell Horne 	TAILQ_FOREACH(pr, &allprison, pr_list)
1554e2121c1SMitchell Horne 		if (pr->pr_id == pr_id || (void *)pr == (void *)addr)
1564e2121c1SMitchell Horne 			return (0);
1574e2121c1SMitchell Horne 
1584e2121c1SMitchell Horne 	return (EACCES);
1594e2121c1SMitchell Horne }
1604e2121c1SMitchell Horne 
1614e2121c1SMitchell Horne static int
db_show_proc_valid(db_expr_t addr,bool have_addr,db_expr_t count,char * modif)1624e2121c1SMitchell Horne db_show_proc_valid(db_expr_t addr, bool have_addr, db_expr_t count,
1634e2121c1SMitchell Horne     char *modif)
1644e2121c1SMitchell Horne {
1654e2121c1SMitchell Horne 	struct proc *p;
1664e2121c1SMitchell Horne 	int i;
1674e2121c1SMitchell Horne 
1684e2121c1SMitchell Horne 	/* Default will show the current proc. */
1694e2121c1SMitchell Horne 	if (!have_addr)
1704e2121c1SMitchell Horne 		return (0);
1714e2121c1SMitchell Horne 
1724e2121c1SMitchell Horne 	for (i = 0; i <= pidhash; i++) {
1734e2121c1SMitchell Horne 		LIST_FOREACH(p, &pidhashtbl[i], p_hash) {
1744e2121c1SMitchell Horne 			if ((void *)p == (void *)addr)
1754e2121c1SMitchell Horne 				return (0);
1764e2121c1SMitchell Horne 		}
1774e2121c1SMitchell Horne 	}
1784e2121c1SMitchell Horne 
1794e2121c1SMitchell Horne 	return (EACCES);
1804e2121c1SMitchell Horne }
1814e2121c1SMitchell Horne 
1824e2121c1SMitchell Horne static int
db_show_rman_valid(db_expr_t addr,bool have_addr,db_expr_t count,char * modif)1834e2121c1SMitchell Horne db_show_rman_valid(db_expr_t addr, bool have_addr, db_expr_t count, char *modif)
1844e2121c1SMitchell Horne {
1854e2121c1SMitchell Horne 	struct rman *rm;
1864e2121c1SMitchell Horne 
1874e2121c1SMitchell Horne 	TAILQ_FOREACH(rm, &rman_head, rm_link) {
1883a3af6b2SJohn Baldwin 		if ((void *)rm == (void *)addr)
1894e2121c1SMitchell Horne 			return (0);
1904e2121c1SMitchell Horne 	}
1914e2121c1SMitchell Horne 
1924e2121c1SMitchell Horne 	return (EACCES);
1934e2121c1SMitchell Horne }
1944e2121c1SMitchell Horne 
195b43b8f81SJohn Baldwin #ifdef VIMAGE
1964e2121c1SMitchell Horne static int
db_show_vnet_valid(db_expr_t addr,bool have_addr,db_expr_t count,char * modif)1974e2121c1SMitchell Horne db_show_vnet_valid(db_expr_t addr, bool have_addr, db_expr_t count, char *modif)
1984e2121c1SMitchell Horne {
1994e2121c1SMitchell Horne 	VNET_ITERATOR_DECL(vnet);
2004e2121c1SMitchell Horne 
2014e2121c1SMitchell Horne 	if (!have_addr)
2024e2121c1SMitchell Horne 		return (0);
2034e2121c1SMitchell Horne 
2044e2121c1SMitchell Horne 	VNET_FOREACH(vnet) {
2054e2121c1SMitchell Horne 		if ((void *)vnet == (void *)addr)
2064e2121c1SMitchell Horne 			return (0);
2074e2121c1SMitchell Horne 	}
2084e2121c1SMitchell Horne 
2094e2121c1SMitchell Horne 	return (EACCES);
2104e2121c1SMitchell Horne }
211b43b8f81SJohn Baldwin #endif
2124e2121c1SMitchell Horne 
2134e2121c1SMitchell Horne static int
command_match(struct db_command * cmd,struct cmd_list_item item)214287d467cSMitchell Horne command_match(struct db_command *cmd, struct cmd_list_item item)
215287d467cSMitchell Horne {
216287d467cSMitchell Horne 	db_validation_fn_t *vfn;
217287d467cSMitchell Horne 	int n;
218287d467cSMitchell Horne 
219287d467cSMitchell Horne 	n = strcmp(cmd->name, item.name);
220287d467cSMitchell Horne 	if (n != 0)
221287d467cSMitchell Horne 		return (n);
222287d467cSMitchell Horne 
223287d467cSMitchell Horne 	/* Got an exact match. Update the command struct */
224287d467cSMitchell Horne 	vfn = item.validate_fn;
225287d467cSMitchell Horne 	if (vfn != NULL) {
226287d467cSMitchell Horne 		cmd->flag |= DB_CMD_VALIDATE;
227287d467cSMitchell Horne 		cmd->mac_priv = vfn;
228287d467cSMitchell Horne 	}
229287d467cSMitchell Horne 	return (0);
230287d467cSMitchell Horne }
231287d467cSMitchell Horne 
232287d467cSMitchell Horne static void
mac_ddb_init(struct mac_policy_conf * conf)233287d467cSMitchell Horne mac_ddb_init(struct mac_policy_conf *conf)
234287d467cSMitchell Horne {
235287d467cSMitchell Horne 	struct db_command *cmd, *prev;
236287d467cSMitchell Horne 	int i, n;
237287d467cSMitchell Horne 
238287d467cSMitchell Horne 	/* The command lists are sorted lexographically, as are our arrays. */
239287d467cSMitchell Horne 
240287d467cSMitchell Horne 	/* Register basic commands. */
241287d467cSMitchell Horne 	for (i = 0, cmd = prev = NULL; i < nitems(command_list); i++) {
242287d467cSMitchell Horne 		LIST_FOREACH_FROM(cmd, &db_cmd_table, next) {
243287d467cSMitchell Horne 			n = command_match(cmd, command_list[i]);
244287d467cSMitchell Horne 			if (n == 0) {
245287d467cSMitchell Horne 				/* Got an exact match. */
246287d467cSMitchell Horne 				prev = cmd;
247287d467cSMitchell Horne 				break;
248287d467cSMitchell Horne 			} else if (n > 0) {
249287d467cSMitchell Horne 				/* Desired command is not registered. */
250287d467cSMitchell Horne 				break;
251287d467cSMitchell Horne 			}
252287d467cSMitchell Horne 		}
253287d467cSMitchell Horne 
254287d467cSMitchell Horne 		/* Next search begins at the previous match. */
255287d467cSMitchell Horne 		cmd = prev;
256287d467cSMitchell Horne 	}
257287d467cSMitchell Horne 
258287d467cSMitchell Horne 	/* Register 'show' commands which require validation. */
259287d467cSMitchell Horne 	for (i = 0, cmd = prev = NULL; i < nitems(show_command_list); i++) {
260287d467cSMitchell Horne 		LIST_FOREACH_FROM(cmd, &db_show_table, next) {
261287d467cSMitchell Horne 			n = command_match(cmd, show_command_list[i]);
262287d467cSMitchell Horne 			if (n == 0) {
263287d467cSMitchell Horne 				/* Got an exact match. */
264287d467cSMitchell Horne 				prev = cmd;
265287d467cSMitchell Horne 				break;
266287d467cSMitchell Horne 			} else if (n > 0) {
267287d467cSMitchell Horne 				/* Desired command is not registered. */
268287d467cSMitchell Horne 				break;
269287d467cSMitchell Horne 			}
270287d467cSMitchell Horne 		}
271287d467cSMitchell Horne 
272287d467cSMitchell Horne 		/* Next search begins at the previous match. */
273287d467cSMitchell Horne 		cmd = prev;
274287d467cSMitchell Horne 	}
275287d467cSMitchell Horne 
276287d467cSMitchell Horne #ifdef INVARIANTS
277287d467cSMitchell Horne 	/* Verify the lists are sorted correctly. */
278287d467cSMitchell Horne 	const char *a, *b;
279287d467cSMitchell Horne 
280287d467cSMitchell Horne 	for (i = 0; i < nitems(command_list) - 1; i++) {
281287d467cSMitchell Horne 		a = command_list[i].name;
282287d467cSMitchell Horne 		b = command_list[i + 1].name;
283287d467cSMitchell Horne 		if (strcmp(a, b) > 0)
284287d467cSMitchell Horne 			panic("%s: command_list[] not alphabetical: %s,%s",
285287d467cSMitchell Horne 			    __func__, a, b);
286287d467cSMitchell Horne 	}
287287d467cSMitchell Horne 	for (i = 0; i < nitems(show_command_list) - 1; i++) {
288287d467cSMitchell Horne 		a = show_command_list[i].name;
289287d467cSMitchell Horne 		b = show_command_list[i + 1].name;
290287d467cSMitchell Horne 		if (strcmp(a, b) > 0)
291287d467cSMitchell Horne 			panic("%s: show_command_list[] not alphabetical: %s,%s",
292287d467cSMitchell Horne 			    __func__, a, b);
293287d467cSMitchell Horne 	}
294287d467cSMitchell Horne #endif
295287d467cSMitchell Horne }
296287d467cSMitchell Horne 
297287d467cSMitchell Horne static int
mac_ddb_command_register(struct db_command_table * table,struct db_command * cmd)298287d467cSMitchell Horne mac_ddb_command_register(struct db_command_table *table,
299287d467cSMitchell Horne     struct db_command *cmd)
300287d467cSMitchell Horne {
301287d467cSMitchell Horne 	int i, n;
302287d467cSMitchell Horne 
303287d467cSMitchell Horne 	if ((cmd->flag & DB_CMD_MEMSAFE) != 0)
304287d467cSMitchell Horne 		return (0);
305287d467cSMitchell Horne 
306287d467cSMitchell Horne 	/* For other commands, search the allow-lists. */
307287d467cSMitchell Horne 	if (table == &db_show_table) {
308287d467cSMitchell Horne 		for (i = 0; i < nitems(show_command_list); i++) {
309287d467cSMitchell Horne 			n = command_match(cmd, show_command_list[i]);
310287d467cSMitchell Horne 			if (n == 0)
311287d467cSMitchell Horne 				/* Got an exact match. */
312287d467cSMitchell Horne 				return (0);
313287d467cSMitchell Horne 			else if (n > 0)
314287d467cSMitchell Horne 				/* Command is not in the policy list. */
315287d467cSMitchell Horne 				break;
316287d467cSMitchell Horne 		}
317287d467cSMitchell Horne 	} else if (table == &db_cmd_table) {
318287d467cSMitchell Horne 		for (i = 0; i < nitems(command_list); i++) {
319287d467cSMitchell Horne 			n = command_match(cmd, command_list[i]);
320287d467cSMitchell Horne 			if (n == 0)
321287d467cSMitchell Horne 				/* Got an exact match. */
322287d467cSMitchell Horne 				return (0);
323287d467cSMitchell Horne 			else if (n > 0)
324287d467cSMitchell Horne 				/* Command is not in the policy list. */
325287d467cSMitchell Horne 				break;
326287d467cSMitchell Horne 		}
327287d467cSMitchell Horne 	}
328287d467cSMitchell Horne 
329287d467cSMitchell Horne 	/* The command will not be registered. */
330287d467cSMitchell Horne 	return (EACCES);
331287d467cSMitchell Horne }
332287d467cSMitchell Horne 
333287d467cSMitchell Horne static int
mac_ddb_command_exec(struct db_command * cmd,db_expr_t addr,bool have_addr,db_expr_t count,char * modif)334287d467cSMitchell Horne mac_ddb_command_exec(struct db_command *cmd, db_expr_t addr,
335287d467cSMitchell Horne     bool have_addr, db_expr_t count, char *modif)
336287d467cSMitchell Horne {
337287d467cSMitchell Horne 	db_validation_fn_t *vfn = cmd->mac_priv;
338287d467cSMitchell Horne 
339287d467cSMitchell Horne 	/* Validate the command and args based on policy. */
340287d467cSMitchell Horne 	if ((cmd->flag & DB_CMD_VALIDATE) != 0) {
341287d467cSMitchell Horne 		MPASS(vfn != NULL);
342287d467cSMitchell Horne 		if (vfn(addr, have_addr, count, modif) == 0)
343287d467cSMitchell Horne 			return (0);
344287d467cSMitchell Horne 	} else if ((cmd->flag & DB_CMD_MEMSAFE) != 0)
345287d467cSMitchell Horne 		return (0);
346287d467cSMitchell Horne 
347287d467cSMitchell Horne 	return (EACCES);
348287d467cSMitchell Horne }
349287d467cSMitchell Horne 
350287d467cSMitchell Horne static int
mac_ddb_check_backend(struct kdb_dbbe * be)351287d467cSMitchell Horne mac_ddb_check_backend(struct kdb_dbbe *be)
352287d467cSMitchell Horne {
353287d467cSMitchell Horne 
354287d467cSMitchell Horne 	/* Only allow DDB backend to execute. */
355287d467cSMitchell Horne 	if (strcmp(be->dbbe_name, "ddb") == 0)
356287d467cSMitchell Horne 		return (0);
357287d467cSMitchell Horne 
358287d467cSMitchell Horne 	return (EACCES);
359287d467cSMitchell Horne }
360287d467cSMitchell Horne 
361287d467cSMitchell Horne /*
362287d467cSMitchell Horne  * Register functions with MAC Framework policy entry points.
363287d467cSMitchell Horne  */
364287d467cSMitchell Horne static struct mac_policy_ops mac_ddb_ops =
365287d467cSMitchell Horne {
366287d467cSMitchell Horne 	.mpo_init = mac_ddb_init,
367287d467cSMitchell Horne 
368287d467cSMitchell Horne 	.mpo_ddb_command_register = mac_ddb_command_register,
369287d467cSMitchell Horne 	.mpo_ddb_command_exec = mac_ddb_command_exec,
370287d467cSMitchell Horne 
371287d467cSMitchell Horne 	.mpo_kdb_check_backend = mac_ddb_check_backend,
372287d467cSMitchell Horne };
373287d467cSMitchell Horne MAC_POLICY_SET(&mac_ddb_ops, mac_ddb, "MAC/DDB", 0, NULL);
374