xref: /freebsd/sys/security/mac/mac_framework.c (revision fc1f75e512df3ae08ea50c496cd6c7e89780b201)
1 /*-
2  * Copyright (c) 1999-2002, 2006, 2009 Robert N. M. Watson
3  * Copyright (c) 2001 Ilmar S. Habibulin
4  * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
5  * Copyright (c) 2005-2006 SPARTA, Inc.
6  * Copyright (c) 2008-2009 Apple Inc.
7  * All rights reserved.
8  *
9  * This software was developed by Robert Watson and Ilmar Habibulin for the
10  * TrustedBSD Project.
11  *
12  * This software was developed for the FreeBSD Project in part by Network
13  * Associates Laboratories, the Security Research Division of Network
14  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
15  * as part of the DARPA CHATS research program.
16  *
17  * This software was enhanced by SPARTA ISSO under SPAWAR contract
18  * N66001-04-C-6019 ("SEFOS").
19  *
20  * This software was developed at the University of Cambridge Computer
21  * Laboratory with support from a grant from Google, Inc.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the above copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  *
32  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42  * SUCH DAMAGE.
43  */
44 
45 /*-
46  * Framework for extensible kernel access control.  This file contains core
47  * kernel infrastructure for the TrustedBSD MAC Framework, including policy
48  * registration, versioning, locking, error composition operator, and system
49  * calls.
50  *
51  * The MAC Framework implements three programming interfaces:
52  *
53  * - The kernel MAC interface, defined in mac_framework.h, and invoked
54  *   throughout the kernel to request security decisions, notify of security
55  *   related events, etc.
56  *
57  * - The MAC policy module interface, defined in mac_policy.h, which is
58  *   implemented by MAC policy modules and invoked by the MAC Framework to
59  *   forward kernel security requests and notifications to policy modules.
60  *
61  * - The user MAC API, defined in mac.h, which allows user programs to query
62  *   and set label state on objects.
63  *
64  * The majority of the MAC Framework implementation may be found in
65  * src/sys/security/mac.  Sample policy modules may be found in
66  * src/sys/security/mac_*.
67  */
68 
69 #include "opt_kdtrace.h"
70 #include "opt_mac.h"
71 
72 #include <sys/cdefs.h>
73 __FBSDID("$FreeBSD$");
74 
75 #include <sys/param.h>
76 #include <sys/condvar.h>
77 #include <sys/kernel.h>
78 #include <sys/lock.h>
79 #include <sys/mutex.h>
80 #include <sys/mac.h>
81 #include <sys/module.h>
82 #include <sys/sdt.h>
83 #include <sys/systm.h>
84 #include <sys/sysctl.h>
85 
86 #include <security/mac/mac_framework.h>
87 #include <security/mac/mac_internal.h>
88 #include <security/mac/mac_policy.h>
89 
90 /*
91  * DTrace SDT providers for MAC.
92  */
93 SDT_PROVIDER_DEFINE(mac);
94 SDT_PROVIDER_DEFINE(mac_framework);
95 
96 SDT_PROBE_DEFINE2(mac, kernel, policy, modevent, "int",
97     "struct mac_policy_conf *mpc");
98 SDT_PROBE_DEFINE1(mac, kernel, policy, register, "struct mac_policy_conf *");
99 SDT_PROBE_DEFINE1(mac, kernel, policy, unregister, "struct mac_policy_conf *");
100 
101 /*
102  * Root sysctl node for all MAC and MAC policy controls.
103  */
104 SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
105     "TrustedBSD MAC policy controls");
106 
107 /*
108  * Declare that the kernel provides MAC support, version 3 (FreeBSD 7.x).
109  * This permits modules to refuse to be loaded if the necessary support isn't
110  * present, even if it's pre-boot.
111  */
112 MODULE_VERSION(kernel_mac_support, MAC_VERSION);
113 
114 static unsigned int	mac_version = MAC_VERSION;
115 SYSCTL_UINT(_security_mac, OID_AUTO, version, CTLFLAG_RD, &mac_version, 0,
116     "");
117 
118 /*
119  * Labels consist of a indexed set of "slots", which are allocated policies
120  * as required.  The MAC Framework maintains a bitmask of slots allocated so
121  * far to prevent reuse.  Slots cannot be reused, as the MAC Framework
122  * guarantees that newly allocated slots in labels will be NULL unless
123  * otherwise initialized, and because we do not have a mechanism to garbage
124  * collect slots on policy unload.  As labeled policies tend to be statically
125  * loaded during boot, and not frequently unloaded and reloaded, this is not
126  * generally an issue.
127  */
128 #if MAC_MAX_SLOTS > 32
129 #error "MAC_MAX_SLOTS too large"
130 #endif
131 
132 static unsigned int mac_max_slots = MAC_MAX_SLOTS;
133 static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
134 SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, &mac_max_slots,
135     0, "");
136 
137 /*
138  * Has the kernel started generating labeled objects yet?  All read/write
139  * access to this variable is serialized during the boot process.  Following
140  * the end of serialization, we don't update this flag; no locking.
141  */
142 static int	mac_late = 0;
143 
144 /*
145  * Each policy declares a mask of object types requiring labels to be
146  * allocated for them.  For convenience, we combine and cache the bitwise or
147  * of the per-policy object flags to track whether we will allocate a label
148  * for an object type at run-time.
149  */
150 uint64_t	mac_labeled;
151 SYSCTL_QUAD(_security_mac, OID_AUTO, labeled, CTLFLAG_RD, &mac_labeled, 0,
152     "Mask of object types being labeled");
153 
154 MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
155 
156 /*
157  * mac_static_policy_list holds a list of policy modules that are not loaded
158  * while the system is "live", and cannot be unloaded.  These policies can be
159  * invoked without holding the busy count.
160  *
161  * mac_policy_list stores the list of dynamic policies.  A busy count is
162  * maintained for the list, stored in mac_policy_busy.  The busy count is
163  * protected by mac_policy_mtx; the list may be modified only while the busy
164  * count is 0, requiring that the lock be held to prevent new references to
165  * the list from being acquired.  For almost all operations, incrementing the
166  * busy count is sufficient to guarantee consistency, as the list cannot be
167  * modified while the busy count is elevated.  For a few special operations
168  * involving a change to the list of active policies, the mtx itself must be
169  * held.  A condition variable, mac_policy_cv, is used to signal potential
170  * exclusive consumers that they should try to acquire the lock if a first
171  * attempt at exclusive access fails.
172  *
173  * This design intentionally avoids fairness, and may starve attempts to
174  * acquire an exclusive lock on a busy system.  This is required because we
175  * do not ever want acquiring a read reference to perform an unbounded length
176  * sleep.  Read references are acquired in ithreads, network isrs, etc, and
177  * any unbounded blocking could lead quickly to deadlock.
178  *
179  * Another reason for never blocking on read references is that the MAC
180  * Framework may recurse: if a policy calls a VOP, for example, this might
181  * lead to vnode life cycle operations (such as init/destroy).
182  *
183  * If the kernel option MAC_STATIC has been compiled in, all locking becomes
184  * a no-op, and the global list of policies is not allowed to change after
185  * early boot.
186  *
187  * XXXRW: Currently, we signal mac_policy_cv every time the framework becomes
188  * unbusy and there is a thread waiting to enter it exclusively.  Since it
189  * may take some time before the thread runs, we may issue a lot of signals.
190  * We should instead keep track of the fact that we've signalled, taking into
191  * account that the framework may be busy again by the time the thread runs,
192  * requiring us to re-signal.
193  */
194 #ifndef MAC_STATIC
195 static struct mtx mac_policy_mtx;
196 static struct cv mac_policy_cv;
197 static int mac_policy_count;
198 static int mac_policy_wait;
199 #endif
200 struct mac_policy_list_head mac_policy_list;
201 struct mac_policy_list_head mac_static_policy_list;
202 
203 /*
204  * We manually invoke WITNESS_WARN() to allow Witness to generate warnings
205  * even if we don't end up ever triggering the wait at run-time.  The
206  * consumer of the exclusive interface must not hold any locks (other than
207  * potentially Giant) since we may sleep for long (potentially indefinite)
208  * periods of time waiting for the framework to become quiescent so that a
209  * policy list change may be made.
210  */
211 void
212 mac_policy_grab_exclusive(void)
213 {
214 
215 #ifndef MAC_STATIC
216 	if (!mac_late)
217 		return;
218 
219 	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
220  	    "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
221 	mtx_lock(&mac_policy_mtx);
222 	while (mac_policy_count != 0) {
223 		mac_policy_wait++;
224 		cv_wait(&mac_policy_cv, &mac_policy_mtx);
225 		mac_policy_wait--;
226 	}
227 #endif
228 }
229 
230 void
231 mac_policy_assert_exclusive(void)
232 {
233 
234 #ifndef MAC_STATIC
235 	if (!mac_late)
236 		return;
237 
238 	mtx_assert(&mac_policy_mtx, MA_OWNED);
239 	KASSERT(mac_policy_count == 0,
240 	    ("mac_policy_assert_exclusive(): not exclusive"));
241 #endif
242 }
243 
244 void
245 mac_policy_release_exclusive(void)
246 {
247 #ifndef MAC_STATIC
248 	int dowakeup;
249 
250 	if (!mac_late)
251 		return;
252 
253 	KASSERT(mac_policy_count == 0,
254 	    ("mac_policy_release_exclusive(): not exclusive"));
255 	dowakeup = (mac_policy_wait != 0);
256 	mtx_unlock(&mac_policy_mtx);
257 	if (dowakeup)
258 		cv_signal(&mac_policy_cv);
259 #endif
260 }
261 
262 void
263 mac_policy_list_busy(void)
264 {
265 
266 #ifndef MAC_STATIC
267 	if (!mac_late)
268 		return;
269 
270 	mtx_lock(&mac_policy_mtx);
271 	mac_policy_count++;
272 	mtx_unlock(&mac_policy_mtx);
273 #endif
274 }
275 
276 int
277 mac_policy_list_conditional_busy(void)
278 {
279 #ifndef MAC_STATIC
280 	int ret;
281 
282 	if (!mac_late)
283 		return (1);
284 
285 	mtx_lock(&mac_policy_mtx);
286 	if (!LIST_EMPTY(&mac_policy_list)) {
287 		mac_policy_count++;
288 		ret = 1;
289 	} else
290 		ret = 0;
291 	mtx_unlock(&mac_policy_mtx);
292 	return (ret);
293 #else
294 	return (1);
295 #endif
296 }
297 
298 void
299 mac_policy_list_unbusy(void)
300 {
301 #ifndef MAC_STATIC
302 	int dowakeup;
303 
304 	if (!mac_late)
305 		return;
306 
307 	mtx_lock(&mac_policy_mtx);
308 	mac_policy_count--;
309 	KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
310 	dowakeup = (mac_policy_count == 0 && mac_policy_wait != 0);
311 	mtx_unlock(&mac_policy_mtx);
312 
313 	if (dowakeup)
314 		cv_signal(&mac_policy_cv);
315 #endif
316 }
317 
318 /*
319  * Initialize the MAC subsystem, including appropriate SMP locks.
320  */
321 static void
322 mac_init(void)
323 {
324 
325 	LIST_INIT(&mac_static_policy_list);
326 	LIST_INIT(&mac_policy_list);
327 	mac_labelzone_init();
328 
329 #ifndef MAC_STATIC
330 	mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
331 	cv_init(&mac_policy_cv, "mac_policy_cv");
332 #endif
333 }
334 
335 /*
336  * For the purposes of modules that want to know if they were loaded "early",
337  * set the mac_late flag once we've processed modules either linked into the
338  * kernel, or loaded before the kernel startup.
339  */
340 static void
341 mac_late_init(void)
342 {
343 
344 	mac_late = 1;
345 }
346 
347 /*
348  * Given a policy, derive from its set of non-NULL label init methods what
349  * object types the policy is interested in.
350  */
351 static uint64_t
352 mac_policy_getlabeled(struct mac_policy_conf *mpc)
353 {
354 	uint64_t labeled;
355 
356 #define	MPC_FLAG(method, flag)					\
357 	if (mpc->mpc_ops->mpo_ ## method != NULL)			\
358 		labeled |= (flag);					\
359 
360 	labeled = 0;
361 	MPC_FLAG(cred_init_label, MPC_OBJECT_CRED);
362 	MPC_FLAG(proc_init_label, MPC_OBJECT_PROC);
363 	MPC_FLAG(vnode_init_label, MPC_OBJECT_VNODE);
364 	MPC_FLAG(inpcb_init_label, MPC_OBJECT_INPCB);
365 	MPC_FLAG(socket_init_label, MPC_OBJECT_SOCKET);
366 	MPC_FLAG(devfs_init_label, MPC_OBJECT_DEVFS);
367 	MPC_FLAG(mbuf_init_label, MPC_OBJECT_MBUF);
368 	MPC_FLAG(ipq_init_label, MPC_OBJECT_IPQ);
369 	MPC_FLAG(ifnet_init_label, MPC_OBJECT_IFNET);
370 	MPC_FLAG(bpfdesc_init_label, MPC_OBJECT_BPFDESC);
371 	MPC_FLAG(pipe_init_label, MPC_OBJECT_PIPE);
372 	MPC_FLAG(mount_init_label, MPC_OBJECT_MOUNT);
373 	MPC_FLAG(posixsem_init_label, MPC_OBJECT_POSIXSEM);
374 	MPC_FLAG(posixshm_init_label, MPC_OBJECT_POSIXSHM);
375 	MPC_FLAG(sysvmsg_init_label, MPC_OBJECT_SYSVMSG);
376 	MPC_FLAG(sysvmsq_init_label, MPC_OBJECT_SYSVMSQ);
377 	MPC_FLAG(sysvsem_init_label, MPC_OBJECT_SYSVSEM);
378 	MPC_FLAG(sysvshm_init_label, MPC_OBJECT_SYSVSHM);
379 	MPC_FLAG(syncache_init_label, MPC_OBJECT_SYNCACHE);
380 	MPC_FLAG(ip6q_init_label, MPC_OBJECT_IP6Q);
381 
382 #undef MPC_FLAG
383 	return (labeled);
384 }
385 
386 /*
387  * When policies are loaded or unloaded, walk the list of registered policies
388  * and built mac_labeled, a bitmask representing the union of all objects
389  * requiring labels across all policies.
390  */
391 static void
392 mac_policy_updateflags(void)
393 {
394 	struct mac_policy_conf *mpc;
395 
396 	mac_policy_assert_exclusive();
397 
398 	mac_labeled = 0;
399 	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list)
400 		mac_labeled |= mac_policy_getlabeled(mpc);
401 	LIST_FOREACH(mpc, &mac_policy_list, mpc_list)
402 		mac_labeled |= mac_policy_getlabeled(mpc);
403 }
404 
405 static int
406 mac_policy_register(struct mac_policy_conf *mpc)
407 {
408 	struct mac_policy_conf *tmpc;
409 	int error, slot, static_entry;
410 
411 	error = 0;
412 
413 	/*
414 	 * We don't technically need exclusive access while !mac_late, but
415 	 * hold it for assertion consistency.
416 	 */
417 	mac_policy_grab_exclusive();
418 
419 	/*
420 	 * If the module can potentially be unloaded, or we're loading late,
421 	 * we have to stick it in the non-static list and pay an extra
422 	 * performance overhead.  Otherwise, we can pay a light locking cost
423 	 * and stick it in the static list.
424 	 */
425 	static_entry = (!mac_late &&
426 	    !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
427 
428 	if (static_entry) {
429 		LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
430 			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
431 				error = EEXIST;
432 				goto out;
433 			}
434 		}
435 	} else {
436 		LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
437 			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
438 				error = EEXIST;
439 				goto out;
440 			}
441 		}
442 	}
443 	if (mpc->mpc_field_off != NULL) {
444 		slot = ffs(mac_slot_offsets_free);
445 		if (slot == 0) {
446 			error = ENOMEM;
447 			goto out;
448 		}
449 		slot--;
450 		mac_slot_offsets_free &= ~(1 << slot);
451 		*mpc->mpc_field_off = slot;
452 	}
453 	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
454 
455 	/*
456 	 * If we're loading a MAC module after the framework has initialized,
457 	 * it has to go into the dynamic list.  If we're loading it before
458 	 * we've finished initializing, it can go into the static list with
459 	 * weaker locker requirements.
460 	 */
461 	if (static_entry)
462 		LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
463 	else
464 		LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
465 
466 	/*
467 	 * Per-policy initialization.  Currently, this takes place under the
468 	 * exclusive lock, so policies must not sleep in their init method.
469 	 * In the future, we may want to separate "init" from "start", with
470 	 * "init" occuring without the lock held.  Likewise, on tear-down,
471 	 * breaking out "stop" from "destroy".
472 	 */
473 	if (mpc->mpc_ops->mpo_init != NULL)
474 		(*(mpc->mpc_ops->mpo_init))(mpc);
475 	mac_policy_updateflags();
476 
477 	SDT_PROBE(mac, kernel, policy, register, mpc, 0, 0, 0, 0);
478 	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
479 	    mpc->mpc_name);
480 
481 out:
482 	mac_policy_release_exclusive();
483 	return (error);
484 }
485 
486 static int
487 mac_policy_unregister(struct mac_policy_conf *mpc)
488 {
489 
490 	/*
491 	 * If we fail the load, we may get a request to unload.  Check to see
492 	 * if we did the run-time registration, and if not, silently succeed.
493 	 */
494 	mac_policy_grab_exclusive();
495 	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
496 		mac_policy_release_exclusive();
497 		return (0);
498 	}
499 #if 0
500 	/*
501 	 * Don't allow unloading modules with private data.
502 	 */
503 	if (mpc->mpc_field_off != NULL) {
504 		MAC_POLICY_LIST_UNLOCK();
505 		return (EBUSY);
506 	}
507 #endif
508 	/*
509 	 * Only allow the unload to proceed if the module is unloadable by
510 	 * its own definition.
511 	 */
512 	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
513 		mac_policy_release_exclusive();
514 		return (EBUSY);
515 	}
516 	if (mpc->mpc_ops->mpo_destroy != NULL)
517 		(*(mpc->mpc_ops->mpo_destroy))(mpc);
518 
519 	LIST_REMOVE(mpc, mpc_list);
520 	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
521 	mac_policy_updateflags();
522 
523 	mac_policy_release_exclusive();
524 
525 	SDT_PROBE(mac, kernel, policy, unregister, mpc, 0, 0, 0, 0);
526 	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
527 	    mpc->mpc_name);
528 
529 	return (0);
530 }
531 
532 /*
533  * Allow MAC policy modules to register during boot, etc.
534  */
535 int
536 mac_policy_modevent(module_t mod, int type, void *data)
537 {
538 	struct mac_policy_conf *mpc;
539 	int error;
540 
541 	error = 0;
542 	mpc = (struct mac_policy_conf *) data;
543 
544 #ifdef MAC_STATIC
545 	if (mac_late) {
546 		printf("mac_policy_modevent: MAC_STATIC and late\n");
547 		return (EBUSY);
548 	}
549 #endif
550 
551 	SDT_PROBE(mac, kernel, policy, modevent, type, mpc, 0, 0, 0);
552 	switch (type) {
553 	case MOD_LOAD:
554 		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
555 		    mac_late) {
556 			printf("mac_policy_modevent: can't load %s policy "
557 			    "after booting\n", mpc->mpc_name);
558 			error = EBUSY;
559 			break;
560 		}
561 		error = mac_policy_register(mpc);
562 		break;
563 	case MOD_UNLOAD:
564 		/* Don't unregister the module if it was never registered. */
565 		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
566 		    != 0)
567 			error = mac_policy_unregister(mpc);
568 		else
569 			error = 0;
570 		break;
571 	default:
572 		error = EOPNOTSUPP;
573 		break;
574 	}
575 
576 	return (error);
577 }
578 
579 /*
580  * Define an error value precedence, and given two arguments, selects the
581  * value with the higher precedence.
582  */
583 int
584 mac_error_select(int error1, int error2)
585 {
586 
587 	/* Certain decision-making errors take top priority. */
588 	if (error1 == EDEADLK || error2 == EDEADLK)
589 		return (EDEADLK);
590 
591 	/* Invalid arguments should be reported where possible. */
592 	if (error1 == EINVAL || error2 == EINVAL)
593 		return (EINVAL);
594 
595 	/* Precedence goes to "visibility", with both process and file. */
596 	if (error1 == ESRCH || error2 == ESRCH)
597 		return (ESRCH);
598 
599 	if (error1 == ENOENT || error2 == ENOENT)
600 		return (ENOENT);
601 
602 	/* Precedence goes to DAC/MAC protections. */
603 	if (error1 == EACCES || error2 == EACCES)
604 		return (EACCES);
605 
606 	/* Precedence goes to privilege. */
607 	if (error1 == EPERM || error2 == EPERM)
608 		return (EPERM);
609 
610 	/* Precedence goes to error over success; otherwise, arbitrary. */
611 	if (error1 != 0)
612 		return (error1);
613 	return (error2);
614 }
615 
616 int
617 mac_check_structmac_consistent(struct mac *mac)
618 {
619 
620 	if (mac->m_buflen < 0 ||
621 	    mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
622 		return (EINVAL);
623 
624 	return (0);
625 }
626 
627 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
628 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
629