Deleted Added
full compact
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed by Robert Watson for the TrustedBSD Project.
7 *
8 * This software was developed for the FreeBSD Project in part by NAI Labs,
9 * the Security Research Division of Network Associates, Inc. under
10 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
11 * CHATS research program.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. The names of the authors may not be used to endorse or promote
22 * products derived from this software without specific prior written
23 * permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * $FreeBSD: head/sys/security/mac_mls/mac_mls.c 104546 2002-10-06 02:46:26Z rwatson $
37 * $FreeBSD: head/sys/security/mac_mls/mac_mls.c 105606 2002-10-21 04:15:40Z rwatson $
38 */
39
40/*
41 * Developed by the TrustedBSD Project.
42 * MLS fixed label mandatory confidentiality policy.
43 */
44
45#include <sys/types.h>
46#include <sys/param.h>
47#include <sys/acl.h>
48#include <sys/conf.h>
49#include <sys/kernel.h>
50#include <sys/mac.h>
51#include <sys/malloc.h>
52#include <sys/mount.h>
53#include <sys/proc.h>
54#include <sys/systm.h>
55#include <sys/sysproto.h>
56#include <sys/sysent.h>
57#include <sys/vnode.h>
58#include <sys/file.h>
59#include <sys/socket.h>
60#include <sys/socketvar.h>
61#include <sys/pipe.h>
62#include <sys/sysctl.h>
63
64#include <fs/devfs/devfs.h>
65
66#include <net/bpfdesc.h>
67#include <net/if.h>
68#include <net/if_types.h>
69#include <net/if_var.h>
70
71#include <netinet/in.h>
72#include <netinet/ip_var.h>
73
74#include <vm/vm.h>
75
76#include <sys/mac_policy.h>
77
78#include <security/mac_mls/mac_mls.h>
79
80SYSCTL_DECL(_security_mac);
81
82SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
83 "TrustedBSD mac_mls policy controls");
84
85static int mac_mls_enabled = 0;
86SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW,
87 &mac_mls_enabled, 0, "Enforce MAC/MLS policy");
88TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled);
89
90static int destroyed_not_inited;
91SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
92 &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
93
94static int ptys_equal = 0;
95SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
96 &ptys_equal, 0, "Label pty devices as mls/equal on create");
97TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
98
99static int mac_mls_revocation_enabled = 0;
100SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
101 &mac_mls_revocation_enabled, 0, "Revoke access to objects on relabel");
102TUNABLE_INT("security.mac.mls.revocation_enabled",
103 &mac_mls_revocation_enabled);
104
105static int mac_mls_slot;
106#define SLOT(l) ((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr)
107
108MALLOC_DEFINE(M_MACMLS, "mls label", "MAC/MLS labels");
109
110static int mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
111 struct label *vnodelabel, mode_t acc_mode);
112
113static struct mac_mls *
114mls_alloc(int flag)
115{
116 struct mac_mls *mac_mls;
117
118 mac_mls = malloc(sizeof(struct mac_mls), M_MACMLS, M_ZERO | flag);
119
120 return (mac_mls);
121}
122
123static void
124mls_free(struct mac_mls *mac_mls)
125{
126
127 if (mac_mls != NULL)
128 free(mac_mls, M_MACMLS);
129 else
130 atomic_add_int(&destroyed_not_inited, 1);
131}
132
133static int
134mac_mls_dominate_element(struct mac_mls_element *a,
135 struct mac_mls_element *b)
136{
137
138 switch(a->mme_type) {
139 case MAC_MLS_TYPE_EQUAL:
140 case MAC_MLS_TYPE_HIGH:
141 return (1);
142
143 case MAC_MLS_TYPE_LOW:
144 switch (b->mme_type) {
145 case MAC_MLS_TYPE_LEVEL:
146 case MAC_MLS_TYPE_HIGH:
147 return (0);
148
149 case MAC_MLS_TYPE_EQUAL:
150 case MAC_MLS_TYPE_LOW:
151 return (1);
152
153 default:
154 panic("mac_mls_dominate_element: b->mme_type invalid");
155 }
156
157 case MAC_MLS_TYPE_LEVEL:
158 switch (b->mme_type) {
159 case MAC_MLS_TYPE_EQUAL:
160 case MAC_MLS_TYPE_LOW:
161 return (1);
162
163 case MAC_MLS_TYPE_HIGH:
164 return (0);
165
166 case MAC_MLS_TYPE_LEVEL:
167 return (a->mme_level >= b->mme_level);
168
169 default:
170 panic("mac_mls_dominate_element: b->mme_type invalid");
171 }
172
173 default:
174 panic("mac_mls_dominate_element: a->mme_type invalid");
175 }
176
177 return (0);
178}
179
180static int
181mac_mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
182{
183
184 return (mac_mls_dominate_element(&rangeb->mm_rangehigh,
185 &rangea->mm_rangehigh) &&
186 mac_mls_dominate_element(&rangea->mm_rangelow,
187 &rangeb->mm_rangelow));
188}
189
190static int
191mac_mls_single_in_range(struct mac_mls *single, struct mac_mls *range)
192{
193
194 KASSERT((single->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
195 ("mac_mls_single_in_range: a not single"));
196 KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
197 ("mac_mls_single_in_range: b not range"));
198
199 return (mac_mls_dominate_element(&range->mm_rangehigh,
200 &single->mm_single) &&
201 mac_mls_dominate_element(&single->mm_single,
202 &range->mm_rangelow));
203
204 return (1);
205}
206
207static int
208mac_mls_dominate_single(struct mac_mls *a, struct mac_mls *b)
209{
210 KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
211 ("mac_mls_dominate_single: a not single"));
212 KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
213 ("mac_mls_dominate_single: b not single"));
214
215 return (mac_mls_dominate_element(&a->mm_single, &b->mm_single));
216}
217
218static int
219mac_mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
220{
221
222 if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
223 b->mme_type == MAC_MLS_TYPE_EQUAL)
224 return (1);
225
226 return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
227}
228
229static int
230mac_mls_equal_single(struct mac_mls *a, struct mac_mls *b)
231{
232
233 KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
234 ("mac_mls_equal_single: a not single"));
235 KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
236 ("mac_mls_equal_single: b not single"));
237
238 return (mac_mls_equal_element(&a->mm_single, &b->mm_single));
239}
240
241static int
242mac_mls_valid(struct mac_mls *mac_mls)
243{
244
245 if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) {
246 switch (mac_mls->mm_single.mme_type) {
247 case MAC_MLS_TYPE_LEVEL:
248 break;
249
250 case MAC_MLS_TYPE_EQUAL:
251 case MAC_MLS_TYPE_HIGH:
252 case MAC_MLS_TYPE_LOW:
253 if (mac_mls->mm_single.mme_level != 0)
254 return (EINVAL);
255 break;
256
257 default:
258 return (EINVAL);
259 }
260 } else {
261 if (mac_mls->mm_single.mme_type != MAC_MLS_TYPE_UNDEF)
262 return (EINVAL);
263 }
264
265 if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
266 switch (mac_mls->mm_rangelow.mme_type) {
267 case MAC_MLS_TYPE_LEVEL:
268 break;
269
270 case MAC_MLS_TYPE_EQUAL:
271 case MAC_MLS_TYPE_HIGH:
272 case MAC_MLS_TYPE_LOW:
273 if (mac_mls->mm_rangelow.mme_level != 0)
274 return (EINVAL);
275 break;
276
277 default:
278 return (EINVAL);
279 }
280
281 switch (mac_mls->mm_rangehigh.mme_type) {
282 case MAC_MLS_TYPE_LEVEL:
283 break;
284
285 case MAC_MLS_TYPE_EQUAL:
286 case MAC_MLS_TYPE_HIGH:
287 case MAC_MLS_TYPE_LOW:
288 if (mac_mls->mm_rangehigh.mme_level != 0)
289 return (EINVAL);
290 break;
291
292 default:
293 return (EINVAL);
294 }
295 if (!mac_mls_dominate_element(&mac_mls->mm_rangehigh,
296 &mac_mls->mm_rangelow))
297 return (EINVAL);
298 } else {
299 if (mac_mls->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
300 mac_mls->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
301 return (EINVAL);
302 }
303
304 return (0);
305}
306
307static void
308mac_mls_set_range(struct mac_mls *mac_mls, u_short typelow,
309 u_short levellow, u_short typehigh, u_short levelhigh)
310{
311
312 mac_mls->mm_rangelow.mme_type = typelow;
313 mac_mls->mm_rangelow.mme_level = levellow;
314 mac_mls->mm_rangehigh.mme_type = typehigh;
315 mac_mls->mm_rangehigh.mme_level = levelhigh;
316 mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
317}
318
319static void
320mac_mls_set_single(struct mac_mls *mac_mls, u_short type, u_short level)
321{
322
323 mac_mls->mm_single.mme_type = type;
324 mac_mls->mm_single.mme_level = level;
325 mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE;
326}
327
328static void
329mac_mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
330{
331 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
332 ("mac_mls_copy_range: labelfrom not range"));
333
334 labelto->mm_rangelow = labelfrom->mm_rangelow;
335 labelto->mm_rangehigh = labelfrom->mm_rangehigh;
336 labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
337}
338
339static void
340mac_mls_copy_single(struct mac_mls *labelfrom, struct mac_mls *labelto)
341{
342
343 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
344 ("mac_mls_copy_single: labelfrom not single"));
345
346 labelto->mm_single = labelfrom->mm_single;
347 labelto->mm_flags |= MAC_MLS_FLAG_SINGLE;
348}
349
350static void
351mac_mls_copy_single_to_range(struct mac_mls *labelfrom,
352 struct mac_mls *labelto)
353{
354
355 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
356 ("mac_mls_copy_single_to_range: labelfrom not single"));
357
358 labelto->mm_rangelow = labelfrom->mm_single;
359 labelto->mm_rangehigh = labelfrom->mm_single;
360 labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
361}
362
363/*
364 * Policy module operations.
365 */
366static void
367mac_mls_destroy(struct mac_policy_conf *conf)
368{
369
370}
371
372static void
373mac_mls_init(struct mac_policy_conf *conf)
374{
375
376}
377
378/*
379 * Label operations.
380 */
381static void
382mac_mls_init_label(struct label *label)
383{
384
385 SLOT(label) = mls_alloc(M_WAITOK);
386}
387
388static int
389mac_mls_init_label_waitcheck(struct label *label, int flag)
390{
391
392 SLOT(label) = mls_alloc(flag);
393 if (SLOT(label) == NULL)
394 return (ENOMEM);
395
396 return (0);
397}
398
399static void
400mac_mls_destroy_label(struct label *label)
401{
402
403 mls_free(SLOT(label));
404 SLOT(label) = NULL;
405}
406
407static int
408mac_mls_externalize(struct label *label, struct mac *extmac)
409{
410 struct mac_mls *mac_mls;
411
412 mac_mls = SLOT(label);
413
414 if (mac_mls == NULL) {
415 printf("mac_mls_externalize: NULL pointer\n");
416 return (0);
417 }
418
419 extmac->m_mls = *mac_mls;
420
421 return (0);
422}
423
424static int
425mac_mls_internalize(struct label *label, struct mac *extmac)
426{
427 struct mac_mls *mac_mls;
428 int error;
429
430 mac_mls = SLOT(label);
431
432 error = mac_mls_valid(mac_mls);
433 if (error)
434 return (error);
435
436 *mac_mls = extmac->m_mls;
437
438 return (0);
439}
440
441/*
442 * Labeling event operations: file system objects, and things that look
443 * a lot like file system objects.
444 */
445static void
446mac_mls_create_devfs_device(dev_t dev, struct devfs_dirent *devfs_dirent,
447 struct label *label)
448{
449 struct mac_mls *mac_mls;
450 int mls_type;
451
452 mac_mls = SLOT(label);
453 if (strcmp(dev->si_name, "null") == 0 ||
454 strcmp(dev->si_name, "zero") == 0 ||
455 strcmp(dev->si_name, "random") == 0 ||
456 strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
457 mls_type = MAC_MLS_TYPE_EQUAL;
458 else if (strcmp(dev->si_name, "kmem") == 0 ||
459 strcmp(dev->si_name, "mem") == 0)
460 mls_type = MAC_MLS_TYPE_HIGH;
461 else if (ptys_equal &&
462 (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
463 strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
464 mls_type = MAC_MLS_TYPE_EQUAL;
465 else
466 mls_type = MAC_MLS_TYPE_LOW;
467 mac_mls_set_single(mac_mls, mls_type, 0);
468}
469
470static void
471mac_mls_create_devfs_directory(char *dirname, int dirnamelen,
472 struct devfs_dirent *devfs_dirent, struct label *label)
473{
474 struct mac_mls *mac_mls;
475
476 mac_mls = SLOT(label);
477 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0);
478}
479
480static void
481mac_mls_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
482 struct label *ddlabel, struct devfs_dirent *de, struct label *delabel)
483{
484 struct mac_mls *source, *dest;
485
486 source = SLOT(&cred->cr_label);
487 dest = SLOT(delabel);
488
489 mac_mls_copy_single(source, dest);
490}
491
492static void
493mac_mls_create_devfs_vnode(struct devfs_dirent *devfs_dirent,
494 struct label *direntlabel, struct vnode *vp, struct label *vnodelabel)
495{
496 struct mac_mls *source, *dest;
497
498 source = SLOT(direntlabel);
499 dest = SLOT(vnodelabel);
500 mac_mls_copy_single(source, dest);
501}
502
503static void
504mac_mls_create_vnode(struct ucred *cred, struct vnode *parent,
505 struct label *parentlabel, struct vnode *child, struct label *childlabel)
506{
507 struct mac_mls *source, *dest;
508
509 source = SLOT(&cred->cr_label);
510 dest = SLOT(childlabel);
511
512 mac_mls_copy_single(source, dest);
513}
514
515static void
516mac_mls_create_mount(struct ucred *cred, struct mount *mp,
517 struct label *mntlabel, struct label *fslabel)
518{
519 struct mac_mls *source, *dest;
520
521 source = SLOT(&cred->cr_label);
522 dest = SLOT(mntlabel);
523 mac_mls_copy_single(source, dest);
524 dest = SLOT(fslabel);
525 mac_mls_copy_single(source, dest);
526}
527
528static void
529mac_mls_create_root_mount(struct ucred *cred, struct mount *mp,
530 struct label *mntlabel, struct label *fslabel)
531{
532 struct mac_mls *mac_mls;
533
534 /* Always mount root as high integrity. */
535 mac_mls = SLOT(fslabel);
536 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0);
537 mac_mls = SLOT(mntlabel);
538 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0);
539}
540
541static void
542mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp,
543 struct label *vnodelabel, struct label *label)
544{
545 struct mac_mls *source, *dest;
546
547 source = SLOT(label);
548 dest = SLOT(vnodelabel);
549
550 mac_mls_copy_single(source, dest);
551}
552
553static void
554mac_mls_update_devfsdirent(struct devfs_dirent *devfs_dirent,
555 struct label *direntlabel, struct vnode *vp, struct label *vnodelabel)
556{
557 struct mac_mls *source, *dest;
558
559 source = SLOT(vnodelabel);
560 dest = SLOT(direntlabel);
561
562 mac_mls_copy_single(source, dest);
563}
564
565static void
566mac_mls_update_procfsvnode(struct vnode *vp, struct label *vnodelabel,
567 struct ucred *cred)
568{
569 struct mac_mls *source, *dest;
570
571 source = SLOT(&cred->cr_label);
572 dest = SLOT(vnodelabel);
573
574 /*
575 * Only copy the single, not the range, since vnodes only have
576 * a single.
577 */
578 mac_mls_copy_single(source, dest);
579}
580
581static int
582mac_mls_update_vnode_from_externalized(struct vnode *vp,
583 struct label *vnodelabel, struct mac *extmac)
584{
585 struct mac_mls *source, *dest;
586 int error;
587
588 source = &extmac->m_mls;
589 dest = SLOT(vnodelabel);
590
591 error = mac_mls_valid(source);
592 if (error)
593 return (error);
594
595 if ((source->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
596 return (EINVAL);
597
598 mac_mls_copy_single(source, dest);
599
600 return (0);
601}
602
603static void
604mac_mls_update_vnode_from_mount(struct vnode *vp, struct label *vnodelabel,
605 struct mount *mp, struct label *fslabel)
606{
607 struct mac_mls *source, *dest;
608
609 source = SLOT(fslabel);
610 dest = SLOT(vnodelabel);
611
612 mac_mls_copy_single(source, dest);
613}
614
615/*
616 * Labeling event operations: IPC object.
617 */
618static void
619mac_mls_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
620 struct mbuf *m, struct label *mbuflabel)
621{
622 struct mac_mls *source, *dest;
623
624 source = SLOT(socketlabel);
625 dest = SLOT(mbuflabel);
626
627 mac_mls_copy_single(source, dest);
628}
629
630static void
631mac_mls_create_socket(struct ucred *cred, struct socket *socket,
632 struct label *socketlabel)
633{
634 struct mac_mls *source, *dest;
635
636 source = SLOT(&cred->cr_label);
637 dest = SLOT(socketlabel);
638
639 mac_mls_copy_single(source, dest);
640 mac_mls_copy_single_to_range(source, dest);
641}
642
643static void
644mac_mls_create_pipe(struct ucred *cred, struct pipe *pipe,
645 struct label *pipelabel)
646{
647 struct mac_mls *source, *dest;
648
649 source = SLOT(&cred->cr_label);
650 dest = SLOT(pipelabel);
651
652 mac_mls_copy_single(source, dest);
653}
654
655static void
656mac_mls_create_socket_from_socket(struct socket *oldsocket,
657 struct label *oldsocketlabel, struct socket *newsocket,
658 struct label *newsocketlabel)
659{
660 struct mac_mls *source, *dest;
661
662 source = SLOT(oldsocketlabel);
663 dest = SLOT(newsocketlabel);
664
665 mac_mls_copy_single(source, dest);
666 mac_mls_copy_range(source, dest);
667}
668
669static void
670mac_mls_relabel_socket(struct ucred *cred, struct socket *socket,
671 struct label *socketlabel, struct label *newlabel)
672{
673 struct mac_mls *source, *dest;
674
675 source = SLOT(newlabel);
676 dest = SLOT(socketlabel);
677
678 mac_mls_copy_single(source, dest);
679 mac_mls_copy_range(source, dest);
680}
681
682static void
683mac_mls_relabel_pipe(struct ucred *cred, struct pipe *pipe,
684 struct label *pipelabel, struct label *newlabel)
685{
686 struct mac_mls *source, *dest;
687
688 source = SLOT(newlabel);
689 dest = SLOT(pipelabel);
690
691 mac_mls_copy_single(source, dest);
692}
693
694static void
695mac_mls_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
696 struct socket *socket, struct label *socketpeerlabel)
697{
698 struct mac_mls *source, *dest;
699
700 source = SLOT(mbuflabel);
701 dest = SLOT(socketpeerlabel);
702
703 mac_mls_copy_single(source, dest);
704}
705
706/*
707 * Labeling event operations: network objects.
708 */
709static void
710mac_mls_set_socket_peer_from_socket(struct socket *oldsocket,
711 struct label *oldsocketlabel, struct socket *newsocket,
712 struct label *newsocketpeerlabel)
713{
714 struct mac_mls *source, *dest;
715
716 source = SLOT(oldsocketlabel);
717 dest = SLOT(newsocketpeerlabel);
718
719 mac_mls_copy_single(source, dest);
720}
721
722static void
723mac_mls_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
724 struct label *bpflabel)
725{
726 struct mac_mls *source, *dest;
727
728 source = SLOT(&cred->cr_label);
729 dest = SLOT(bpflabel);
730
731 mac_mls_copy_single(source, dest);
732}
733
734static void
735mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
736{
737 struct mac_mls *dest;
738 int level;
739
740 dest = SLOT(ifnetlabel);
741
742 if (ifnet->if_type == IFT_LOOP)
743 level = MAC_MLS_TYPE_EQUAL;
744 else
745 level = MAC_MLS_TYPE_LOW;
746
747 mac_mls_set_single(dest, level, 0);
748 mac_mls_set_range(dest, level, 0, level, 0);
749}
750
751static void
752mac_mls_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
753 struct ipq *ipq, struct label *ipqlabel)
754{
755 struct mac_mls *source, *dest;
756
757 source = SLOT(fragmentlabel);
758 dest = SLOT(ipqlabel);
759
760 mac_mls_copy_single(source, dest);
761}
762
763static void
764mac_mls_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
765 struct mbuf *datagram, struct label *datagramlabel)
766{
767 struct mac_mls *source, *dest;
768
769 source = SLOT(ipqlabel);
770 dest = SLOT(datagramlabel);
771
772 /* Just use the head, since we require them all to match. */
773 mac_mls_copy_single(source, dest);
774}
775
776static void
777mac_mls_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
778 struct mbuf *fragment, struct label *fragmentlabel)
779{
780 struct mac_mls *source, *dest;
781
782 source = SLOT(datagramlabel);
783 dest = SLOT(fragmentlabel);
784
785 mac_mls_copy_single(source, dest);
786}
787
788static void
789mac_mls_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
790 struct label *oldmbuflabel, struct mbuf *newmbuf,
791 struct label *newmbuflabel)
792{
793 struct mac_mls *source, *dest;
794
795 source = SLOT(oldmbuflabel);
796 dest = SLOT(newmbuflabel);
797
798 mac_mls_copy_single(source, dest);
799}
800
801static void
802mac_mls_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
803 struct mbuf *mbuf, struct label *mbuflabel)
804{
805 struct mac_mls *dest;
806
807 dest = SLOT(mbuflabel);
808
809 mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0);
810}
811
812static void
813mac_mls_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
814 struct mbuf *mbuf, struct label *mbuflabel)
815{
816 struct mac_mls *source, *dest;
817
818 source = SLOT(bpflabel);
819 dest = SLOT(mbuflabel);
820
821 mac_mls_copy_single(source, dest);
822}
823
824static void
825mac_mls_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
826 struct mbuf *m, struct label *mbuflabel)
827{
828 struct mac_mls *source, *dest;
829
830 source = SLOT(ifnetlabel);
831 dest = SLOT(mbuflabel);
832
833 mac_mls_copy_single(source, dest);
834}
835
836static void
837mac_mls_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
838 struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
839 struct mbuf *newmbuf, struct label *newmbuflabel)
840{
841 struct mac_mls *source, *dest;
842
843 source = SLOT(oldmbuflabel);
844 dest = SLOT(newmbuflabel);
845
846 mac_mls_copy_single(source, dest);
847}
848
849static void
850mac_mls_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
851 struct mbuf *newmbuf, struct label *newmbuflabel)
852{
853 struct mac_mls *source, *dest;
854
855 source = SLOT(oldmbuflabel);
856 dest = SLOT(newmbuflabel);
857
858 mac_mls_copy_single(source, dest);
859}
860
861static int
862mac_mls_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
863 struct ipq *ipq, struct label *ipqlabel)
864{
865 struct mac_mls *a, *b;
866
867 a = SLOT(ipqlabel);
868 b = SLOT(fragmentlabel);
869
870 return (mac_mls_equal_single(a, b));
871}
872
873static void
874mac_mls_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
875 struct label *ifnetlabel, struct label *newlabel)
876{
877 struct mac_mls *source, *dest;
878
879 source = SLOT(newlabel);
880 dest = SLOT(ifnetlabel);
881
882 mac_mls_copy_single(source, dest);
883 mac_mls_copy_range(source, dest);
884}
885
886static void
887mac_mls_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
888 struct ipq *ipq, struct label *ipqlabel)
889{
890
891 /* NOOP: we only accept matching labels, so no need to update */
892}
893
894/*
895 * Labeling event operations: processes.
896 */
897static void
898mac_mls_create_cred(struct ucred *cred_parent, struct ucred *cred_child)
899{
900 struct mac_mls *source, *dest;
901
902 source = SLOT(&cred_parent->cr_label);
903 dest = SLOT(&cred_child->cr_label);
904
905 mac_mls_copy_single(source, dest);
906 mac_mls_copy_range(source, dest);
907}
908
909static void
910mac_mls_execve_transition(struct ucred *old, struct ucred *new,
911 struct vnode *vp, struct mac *vnodelabel)
912{
913 struct mac_mls *source, *dest;
914
915 source = SLOT(&old->cr_label);
916 dest = SLOT(&new->cr_label);
917
918 mac_mls_copy_single(source, dest);
919 mac_mls_copy_range(source, dest);
920}
921
922static int
923mac_mls_execve_will_transition(struct ucred *old, struct vnode *vp,
924 struct mac *vnodelabel)
925{
926
927 return (0);
928}
929
930static void
931mac_mls_create_proc0(struct ucred *cred)
932{
933 struct mac_mls *dest;
934
935 dest = SLOT(&cred->cr_label);
936
937 mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0);
938 mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, MAC_MLS_TYPE_HIGH, 0);
939}
940
941static void
942mac_mls_create_proc1(struct ucred *cred)
943{
944 struct mac_mls *dest;
945
946 dest = SLOT(&cred->cr_label);
947
948 mac_mls_set_single(dest, MAC_MLS_TYPE_LOW, 0);
949 mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, MAC_MLS_TYPE_HIGH, 0);
950}
951
952static void
953mac_mls_relabel_cred(struct ucred *cred, struct label *newlabel)
954{
955 struct mac_mls *source, *dest;
956
957 source = SLOT(newlabel);
958 dest = SLOT(&cred->cr_label);
959
960 mac_mls_copy_single(source, dest);
961 mac_mls_copy_range(source, dest);
962}
963
964/*
965 * Access control checks.
966 */
967static int
968mac_mls_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
969 struct ifnet *ifnet, struct label *ifnetlabel)
970{
971 struct mac_mls *a, *b;
972
973 if (!mac_mls_enabled)
974 return (0);
975
976 a = SLOT(bpflabel);
977 b = SLOT(ifnetlabel);
978
979 if (mac_mls_equal_single(a, b))
980 return (0);
981 return (EACCES);
982}
983
984static int
985mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel)
986{
987 struct mac_mls *subj, *new;
988
989 subj = SLOT(&cred->cr_label);
990 new = SLOT(newlabel);
991
992 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAGS_BOTH)
993 return (EINVAL);
994
995 /*
996 * XXX: Allow processes with root privilege to set labels outside
997 * their range, so suid things like "su" work. This WILL go away
998 * when we figure out the 'correct' solution...
999 */
1000 if (!suser_cred(cred, 0))
1001 return (0);
1002
1003 /*
1004 * The new single must be in the old range.
1005 */
1006 if (!mac_mls_single_in_range(new, subj))
1007 return (EPERM);
1008
1009 /*
1010 * The new range must be in the old range.
1011 */
1012 if (!mac_mls_range_in_range(new, subj))
1013 return (EPERM);
1014
1015 /*
1016 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1017 */
1018
1019 return (0);
1020}
1021
1022
1023static int
1024mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2)
1025{
1026 struct mac_mls *subj, *obj;
1027
1028 if (!mac_mls_enabled)
1029 return (0);
1030
1031 subj = SLOT(&u1->cr_label);
1032 obj = SLOT(&u2->cr_label);
1033
1034 /* XXX: range */
1035 if (!mac_mls_dominate_single(subj, obj))
1036 return (ESRCH);
1037
1038 return (0);
1039}
1040
1041static int
1042mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1043 struct label *ifnetlabel, struct label *newlabel)
1044{
1045 struct mac_mls *subj, *new;
1046
1047 subj = SLOT(&cred->cr_label);
1048 new = SLOT(newlabel);
1049
1050 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAGS_BOTH)
1051 return (EINVAL);
1052
1053 /* XXX: privilege model here? */
1054
1055 return (suser_cred(cred, 0));
1056}
1057
1058static int
1059mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1060 struct mbuf *m, struct label *mbuflabel)
1061{
1062 struct mac_mls *p, *i;
1063
1064 if (!mac_mls_enabled)
1065 return (0);
1066
1067 p = SLOT(mbuflabel);
1068 i = SLOT(ifnetlabel);
1069
1070 return (mac_mls_single_in_range(p, i) ? 0 : EACCES);
1071}
1072
1073static int
1074mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp,
1075 struct label *mntlabel)
1076{
1077 struct mac_mls *subj, *obj;
1078
1079 if (!mac_mls_enabled)
1080 return (0);
1081
1082 subj = SLOT(&cred->cr_label);
1083 obj = SLOT(mntlabel);
1084
1085 if (!mac_mls_dominate_single(subj, obj))
1086 return (EACCES);
1087
1088 return (0);
1089}
1090
1091static int
1092mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
1093 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1094{
1095
1096 if(!mac_mls_enabled)
1097 return (0);
1098
1099 /* XXX: This will be implemented soon... */
1100
1101 return (0);
1102}
1103
1104static int
1105mac_mls_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
1106 struct label *pipelabel)
1107{
1108 struct mac_mls *subj, *obj;
1109
1110 if (!mac_mls_enabled)
1111 return (0);
1112
1113 subj = SLOT(&cred->cr_label);
1114 obj = SLOT((pipelabel));
1115
1116 if (!mac_mls_dominate_single(subj, obj))
1117 return (EACCES);
1118
1119 return (0);
1120}
1121
1122static int
1123mac_mls_check_pipe_read(struct ucred *cred, struct pipe *pipe,
1124 struct label *pipelabel)
1125{
1126 struct mac_mls *subj, *obj;
1127
1128 if (!mac_mls_enabled)
1129 return (0);
1130
1131 subj = SLOT(&cred->cr_label);
1132 obj = SLOT((pipelabel));
1133
1134 if (!mac_mls_dominate_single(subj, obj))
1135 return (EACCES);
1136
1137 return (0);
1138}
1139
1140static int
1141mac_mls_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
1142 struct label *pipelabel, struct label *newlabel)
1143{
1144 struct mac_mls *subj, *obj, *new;
1145
1146 new = SLOT(newlabel);
1147 subj = SLOT(&cred->cr_label);
1148 obj = SLOT(pipelabel);
1149
1150 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
1151 return (EINVAL);
1152
1153 /*
1154 * To relabel a pipe, the old pipe label must be in the subject
1155 * range.
1156 */
1157 if (!mac_mls_single_in_range(obj, subj))
1158 return (EPERM);
1159
1160 /*
1161 * To relabel a pipe, the new pipe label must be in the subject
1162 * range.
1163 */
1164 if (!mac_mls_single_in_range(new, subj))
1165 return (EPERM);
1166
1167 /*
1168 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1169 */
1170
1171 return (0);
1172}
1173
1174static int
1175mac_mls_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
1176 struct label *pipelabel)
1177{
1178 struct mac_mls *subj, *obj;
1179
1180 if (!mac_mls_enabled)
1181 return (0);
1182
1183 subj = SLOT(&cred->cr_label);
1184 obj = SLOT((pipelabel));
1185
1186 if (!mac_mls_dominate_single(subj, obj))
1187 return (EACCES);
1188
1189 return (0);
1190}
1191
1192static int
1193mac_mls_check_pipe_write(struct ucred *cred, struct pipe *pipe,
1194 struct label *pipelabel)
1195{
1196 struct mac_mls *subj, *obj;
1197
1198 if (!mac_mls_enabled)
1199 return (0);
1200
1201 subj = SLOT(&cred->cr_label);
1202 obj = SLOT((pipelabel));
1203
1204 if (!mac_mls_dominate_single(obj, subj))
1205 return (EACCES);
1206
1207 return (0);
1208}
1209
1210static int
1211mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc)
1212{
1213 struct mac_mls *subj, *obj;
1214
1215 if (!mac_mls_enabled)
1216 return (0);
1217
1218 subj = SLOT(&cred->cr_label);
1219 obj = SLOT(&proc->p_ucred->cr_label);
1220
1221 /* XXX: range checks */
1222 if (!mac_mls_dominate_single(subj, obj))
1223 return (ESRCH);
1224 if (!mac_mls_dominate_single(obj, subj))
1225 return (EACCES);
1226
1227 return (0);
1228}
1229
1230static int
1231mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc)
1232{
1233 struct mac_mls *subj, *obj;
1234
1235 if (!mac_mls_enabled)
1236 return (0);
1237
1238 subj = SLOT(&cred->cr_label);
1239 obj = SLOT(&proc->p_ucred->cr_label);
1240
1241 /* XXX: range checks */
1242 if (!mac_mls_dominate_single(subj, obj))
1243 return (ESRCH);
1244 if (!mac_mls_dominate_single(obj, subj))
1245 return (EACCES);
1246
1247 return (0);
1248}
1249
1250static int
1251mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1252{
1253 struct mac_mls *subj, *obj;
1254
1255 if (!mac_mls_enabled)
1256 return (0);
1257
1258 subj = SLOT(&cred->cr_label);
1259 obj = SLOT(&proc->p_ucred->cr_label);
1260
1261 /* XXX: range checks */
1262 if (!mac_mls_dominate_single(subj, obj))
1263 return (ESRCH);
1264 if (!mac_mls_dominate_single(obj, subj))
1265 return (EACCES);
1266
1267 return (0);
1268}
1269
1270static int
1271mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel,
1272 struct mbuf *m, struct label *mbuflabel)
1273{
1274 struct mac_mls *p, *s;
1275
1276 if (!mac_mls_enabled)
1277 return (0);
1278
1279 p = SLOT(mbuflabel);
1280 s = SLOT(socketlabel);
1281
1282 return (mac_mls_equal_single(p, s) ? 0 : EACCES);
1283}
1284
1285static int
1286mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket,
1287 struct label *socketlabel, struct label *newlabel)
1288{
1289 struct mac_mls *subj, *obj, *new;
1290
1291 new = SLOT(newlabel);
1292 subj = SLOT(&cred->cr_label);
1293 obj = SLOT(socketlabel);
1294
1295 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
1296 return (EINVAL);
1297
1298 /*
1299 * To relabel a socket, the old socket label must be in the subject
1300 * range.
1301 */
1302 if (!mac_mls_single_in_range(obj, subj))
1303 return (EPERM);
1304
1305 /*
1306 * To relabel a socket, the new socket label must be in the subject
1307 * range.
1308 */
1309 if (!mac_mls_single_in_range(new, subj))
1310 return (EPERM);
1311
1312 /*
1313 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1314 */
1315
1316 return (0);
1317}
1318
1319static int
1320mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket,
1321 struct label *socketlabel)
1322{
1323 struct mac_mls *subj, *obj;
1324
1325 if (!mac_mls_enabled)
1326 return (0);
1327
1328 subj = SLOT(&cred->cr_label);
1329 obj = SLOT(socketlabel);
1330
1331 if (!mac_mls_dominate_single(subj, obj))
1332 return (ENOENT);
1333
1334 return (0);
1335}
1336
1337static int
1338mac_mls_check_vnode_access(struct ucred *cred, struct vnode *vp,
1339 struct label *label, mode_t flags)
1340{
1341
1342 return (mac_mls_check_vnode_open(cred, vp, label, flags));
1343}
1344
1345static int
1346mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
1347 struct label *dlabel)
1348{
1349 struct mac_mls *subj, *obj;
1350
1351 if (!mac_mls_enabled)
1352 return (0);
1353
1354 subj = SLOT(&cred->cr_label);
1355 obj = SLOT(dlabel);
1356
1357 if (!mac_mls_dominate_single(subj, obj))
1358 return (EACCES);
1359
1360 return (0);
1361}
1362
1363static int
1364mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
1365 struct label *dlabel)
1366{
1367 struct mac_mls *subj, *obj;
1368
1369 if (!mac_mls_enabled)
1370 return (0);
1371
1372 subj = SLOT(&cred->cr_label);
1373 obj = SLOT(dlabel);
1374
1375 if (!mac_mls_dominate_single(subj, obj))
1376 return (EACCES);
1377
1378 return (0);
1379}
1380
1381static int
1382mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1383 struct label *dlabel, struct componentname *cnp, struct vattr *vap)
1384{
1385 struct mac_mls *subj, *obj;
1386
1387 if (!mac_mls_enabled)
1388 return (0);
1389
1390 subj = SLOT(&cred->cr_label);
1391 obj = SLOT(dlabel);
1392
1393 if (!mac_mls_dominate_single(obj, subj))
1394 return (EACCES);
1395
1396 return (0);
1397}
1398
1399static int
1400mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
1401 struct label *dlabel, struct vnode *vp, struct label *label,
1402 struct componentname *cnp)
1403{
1404 struct mac_mls *subj, *obj;
1405
1406 if (!mac_mls_enabled)
1407 return (0);
1408
1409 subj = SLOT(&cred->cr_label);
1410 obj = SLOT(dlabel);
1411
1412 if (!mac_mls_dominate_single(obj, subj))
1413 return (EACCES);
1414
1415 obj = SLOT(label);
1416
1417 if (!mac_mls_dominate_single(obj, subj))
1418 return (EACCES);
1419
1420 return (0);
1421}
1422
1423static int
1424mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1425 struct label *label, acl_type_t type)
1426{
1427 struct mac_mls *subj, *obj;
1428
1429 if (!mac_mls_enabled)
1430 return (0);
1431
1432 subj = SLOT(&cred->cr_label);
1433 obj = SLOT(label);
1434
1435 if (!mac_mls_dominate_single(obj, subj))
1436 return (EACCES);
1437
1438 return (0);
1439}
1440
1441static int
1442mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1443 struct label *label)
1444{
1445 struct mac_mls *subj, *obj;
1446
1447 if (!mac_mls_enabled)
1448 return (0);
1449
1450 subj = SLOT(&cred->cr_label);
1451 obj = SLOT(label);
1452
1453 if (!mac_mls_dominate_single(subj, obj))
1454 return (EACCES);
1455
1456 return (0);
1457}
1458
1459static int
1460mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
1461 struct label *label, acl_type_t type)
1462{
1463 struct mac_mls *subj, *obj;
1464
1465 if (!mac_mls_enabled)
1466 return (0);
1467
1468 subj = SLOT(&cred->cr_label);
1469 obj = SLOT(label);
1470
1471 if (!mac_mls_dominate_single(subj, obj))
1472 return (EACCES);
1473
1474 return (0);
1475}
1476
1477static int
1478mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1479 struct label *label, int attrnamespace, const char *name, struct uio *uio)
1480{
1481 struct mac_mls *subj, *obj;
1482
1483 if (!mac_mls_enabled)
1484 return (0);
1485
1486 subj = SLOT(&cred->cr_label);
1487 obj = SLOT(label);
1488
1489 if (!mac_mls_dominate_single(subj, obj))
1490 return (EACCES);
1491
1492 return (0);
1493}
1494
1495static int
1496mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1497 struct label *dlabel, struct vnode *vp, struct label *label,
1498 struct componentname *cnp)
1499{
1500 struct mac_mls *subj, *obj;
1501
1502 if (!mac_mls_enabled)
1503 return (0);
1504
1505 subj = SLOT(&cred->cr_label);
1506 obj = SLOT(dlabel);
1507
1508 if (!mac_mls_dominate_single(obj, subj))
1509 return (EACCES);
1510
1511 obj = SLOT(dlabel);
1512 if (!mac_mls_dominate_single(obj, subj))
1513 return (EACCES);
1514
1515 return (0);
1516}
1517
1518static int
1519mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1520 struct label *dlabel, struct componentname *cnp)
1521{
1522 struct mac_mls *subj, *obj;
1523
1524 if (!mac_mls_enabled)
1525 return (0);
1526
1527 subj = SLOT(&cred->cr_label);
1528 obj = SLOT(dlabel);
1529
1530 if (!mac_mls_dominate_single(subj, obj))
1531 return (EACCES);
1532
1533 return (0);
1534}
1535
1536static int
1537mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
1538 struct label *label, int prot)
1539{
1540 struct mac_mls *subj, *obj;
1541
1542 /*
1543 * Rely on the use of open()-time protections to handle
1544 * non-revocation cases.
1545 */
1546 if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1547 return (0);
1548
1549 subj = SLOT(&cred->cr_label);
1550 obj = SLOT(label);
1551
1552 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
1553 if (!mac_mls_dominate_single(subj, obj))
1554 return (EACCES);
1555 }
1556 if (prot & VM_PROT_WRITE) {
1557 if (!mac_mls_dominate_single(obj, subj))
1558 return (EACCES);
1559 }
1560
1561 return (0);
1562}
1563
1564static int
1565mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
1566 struct label *vnodelabel, mode_t acc_mode)
1567{
1568 struct mac_mls *subj, *obj;
1569
1570 if (!mac_mls_enabled)
1571 return (0);
1572
1573 subj = SLOT(&cred->cr_label);
1574 obj = SLOT(vnodelabel);
1575
1576 /* XXX privilege override for admin? */
1577 if (acc_mode & (VREAD | VEXEC | VSTAT)) {
1578 if (!mac_mls_dominate_single(subj, obj))
1579 return (EACCES);
1580 }
1581 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
1582 if (!mac_mls_dominate_single(obj, subj))
1583 return (EACCES);
1584 }
1585
1586 return (0);
1587}
1588
1589static int
1590mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1591 struct vnode *vp, struct label *label)
1592{
1593 struct mac_mls *subj, *obj;
1594
1595 if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1596 return (0);
1597
1598 subj = SLOT(&active_cred->cr_label);
1599 obj = SLOT(label);
1600
1601 if (!mac_mls_dominate_single(subj, obj))
1602 return (EACCES);
1603
1604 return (0);
1605}
1606
1607static int
1608mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1609 struct vnode *vp, struct label *label)
1610{
1611 struct mac_mls *subj, *obj;
1612
1613 if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1614 return (0);
1615
1616 subj = SLOT(&active_cred->cr_label);
1617 obj = SLOT(label);
1618
1619 if (!mac_mls_dominate_single(subj, obj))
1620 return (EACCES);
1621
1622 return (0);
1623}
1624
1625static int
1626mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
1627 struct label *dlabel)
1628{
1629 struct mac_mls *subj, *obj;
1630
1631 if (!mac_mls_enabled)
1632 return (0);
1633
1634 subj = SLOT(&cred->cr_label);
1635 obj = SLOT(dlabel);
1636
1637 if (!mac_mls_dominate_single(subj, obj))
1638 return (EACCES);
1639
1640 return (0);
1641}
1642
1643static int
1644mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
1645 struct label *vnodelabel)
1646{
1647 struct mac_mls *subj, *obj;
1648
1649 if (!mac_mls_enabled)
1650 return (0);
1651
1652 subj = SLOT(&cred->cr_label);
1653 obj = SLOT(vnodelabel);
1654
1655 if (!mac_mls_dominate_single(subj, obj))
1656 return (EACCES);
1657
1658 return (0);
1659}
1660
1661static int
1662mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1663 struct label *vnodelabel, struct label *newlabel)
1664{
1665 struct mac_mls *old, *new, *subj;
1666
1667 old = SLOT(vnodelabel);
1668 new = SLOT(newlabel);
1669 subj = SLOT(&cred->cr_label);
1670
1671 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
1672 return (EINVAL);
1673
1674 /*
1675 * To relabel a vnode, the old vnode label must be in the subject
1676 * range.
1677 */
1678 if (!mac_mls_single_in_range(old, subj))
1679 return (EPERM);
1680
1681 /*
1682 * To relabel a vnode, the new vnode label must be in the subject
1683 * range.
1684 */
1685 if (!mac_mls_single_in_range(new, subj))
1686 return (EPERM);
1687
1688 /*
1689 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1690 */
1691
1692 return (suser_cred(cred, 0));
1693}
1694
1695
1696static int
1697mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1698 struct label *dlabel, struct vnode *vp, struct label *label,
1699 struct componentname *cnp)
1700{
1701 struct mac_mls *subj, *obj;
1702
1703 if (!mac_mls_enabled)
1704 return (0);
1705
1706 subj = SLOT(&cred->cr_label);
1707 obj = SLOT(dlabel);
1708
1709 if (!mac_mls_dominate_single(obj, subj))
1710 return (EACCES);
1711
1712 obj = SLOT(label);
1713
1714 if (!mac_mls_dominate_single(obj, subj))
1715 return (EACCES);
1716
1717 return (0);
1718}
1719
1720static int
1721mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1722 struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
1723 struct componentname *cnp)
1724{
1725 struct mac_mls *subj, *obj;
1726
1727 if (!mac_mls_enabled)
1728 return (0);
1729
1730 subj = SLOT(&cred->cr_label);
1731 obj = SLOT(dlabel);
1732
1733 if (!mac_mls_dominate_single(obj, subj))
1734 return (EACCES);
1735
1736 if (vp != NULL) {
1737 obj = SLOT(label);
1738
1739 if (!mac_mls_dominate_single(obj, subj))
1740 return (EACCES);
1741 }
1742
1743 return (0);
1744}
1745
1746static int
1747mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
1748 struct label *label)
1749{
1750 struct mac_mls *subj, *obj;
1751
1752 if (!mac_mls_enabled)
1753 return (0);
1754
1755 subj = SLOT(&cred->cr_label);
1756 obj = SLOT(label);
1757
1758 if (!mac_mls_dominate_single(obj, subj))
1759 return (EACCES);
1760
1761 return (0);
1762}
1763
1764static int
1765mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
1766 struct label *label, acl_type_t type, struct acl *acl)
1767{
1768 struct mac_mls *subj, *obj;
1769
1770 if (!mac_mls_enabled)
1771 return (0);
1772
1773 subj = SLOT(&cred->cr_label);
1774 obj = SLOT(label);
1775
1776 if (!mac_mls_dominate_single(obj, subj))
1777 return (EACCES);
1778
1779 return (0);
1780}
1781
1782static int
1783mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1784 struct label *vnodelabel, int attrnamespace, const char *name,
1785 struct uio *uio)
1786{
1787 struct mac_mls *subj, *obj;
1788
1789 if (!mac_mls_enabled)
1790 return (0);
1791
1792 subj = SLOT(&cred->cr_label);
1793 obj = SLOT(vnodelabel);
1794
1795 if (!mac_mls_dominate_single(obj, subj))
1796 return (EACCES);
1797
1798 /* XXX: protect the MAC EA in a special way? */
1799
1800 return (0);
1801}
1802
1803static int
1804mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
1805 struct label *vnodelabel, u_long flags)
1806{
1807 struct mac_mls *subj, *obj;
1808
1809 if (!mac_mls_enabled)
1810 return (0);
1811
1812 subj = SLOT(&cred->cr_label);
1813 obj = SLOT(vnodelabel);
1814
1815 if (!mac_mls_dominate_single(obj, subj))
1816 return (EACCES);
1817
1818 return (0);
1819}
1820
1821static int
1822mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
1823 struct label *vnodelabel, mode_t mode)
1824{
1825 struct mac_mls *subj, *obj;
1826
1827 if (!mac_mls_enabled)
1828 return (0);
1829
1830 subj = SLOT(&cred->cr_label);
1831 obj = SLOT(vnodelabel);
1832
1833 if (!mac_mls_dominate_single(obj, subj))
1834 return (EACCES);
1835
1836 return (0);
1837}
1838
1839static int
1840mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
1841 struct label *vnodelabel, uid_t uid, gid_t gid)
1842{
1843 struct mac_mls *subj, *obj;
1844
1845 if (!mac_mls_enabled)
1846 return (0);
1847
1848 subj = SLOT(&cred->cr_label);
1849 obj = SLOT(vnodelabel);
1850
1851 if (!mac_mls_dominate_single(obj, subj))
1852 return (EACCES);
1853
1854 return (0);
1855}
1856
1857static int
1858mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1859 struct label *vnodelabel, struct timespec atime, struct timespec mtime)
1860{
1861 struct mac_mls *subj, *obj;
1862
1863 if (!mac_mls_enabled)
1864 return (0);
1865
1866 subj = SLOT(&cred->cr_label);
1867 obj = SLOT(vnodelabel);
1868
1869 if (!mac_mls_dominate_single(obj, subj))
1870 return (EACCES);
1871
1872 return (0);
1873}
1874
1875static int
1876mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
1877 struct vnode *vp, struct label *vnodelabel)
1878{
1879 struct mac_mls *subj, *obj;
1880
1881 if (!mac_mls_enabled)
1882 return (0);
1883
1884 subj = SLOT(&active_cred->cr_label);
1885 obj = SLOT(vnodelabel);
1886
1887 if (!mac_mls_dominate_single(subj, obj))
1888 return (EACCES);
1889
1890 return (0);
1891}
1892
1893static int
1894mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
1895 struct vnode *vp, struct label *label)
1896{
1897 struct mac_mls *subj, *obj;
1898
1899 if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1900 return (0);
1901
1902 subj = SLOT(&active_cred->cr_label);
1903 obj = SLOT(label);
1904
1905 if (!mac_mls_dominate_single(obj, subj))
1906 return (EACCES);
1907
1908 return (0);
1909}
1910
1911static struct mac_policy_op_entry mac_mls_ops[] =
1912{
1913 { MAC_DESTROY,
1914 (macop_t)mac_mls_destroy },
1915 { MAC_INIT,
1916 (macop_t)mac_mls_init },
1917 { MAC_INIT_BPFDESC_LABEL,
1918 (macop_t)mac_mls_init_label },
1919 { MAC_INIT_CRED_LABEL,
1920 (macop_t)mac_mls_init_label },
1921 { MAC_INIT_DEVFSDIRENT_LABEL,
1922 (macop_t)mac_mls_init_label },
1923 { MAC_INIT_IFNET_LABEL,
1924 (macop_t)mac_mls_init_label },
1925 { MAC_INIT_IPQ_LABEL,
1926 (macop_t)mac_mls_init_label },
1927 { MAC_INIT_MBUF_LABEL,
1928 (macop_t)mac_mls_init_label_waitcheck },
1929 { MAC_INIT_MOUNT_LABEL,
1930 (macop_t)mac_mls_init_label },
1931 { MAC_INIT_MOUNT_FS_LABEL,
1932 (macop_t)mac_mls_init_label },
1933 { MAC_INIT_PIPE_LABEL,
1934 (macop_t)mac_mls_init_label },
1935 { MAC_INIT_SOCKET_LABEL,
1936 (macop_t)mac_mls_init_label_waitcheck },
1937 { MAC_INIT_SOCKET_PEER_LABEL,
1938 (macop_t)mac_mls_init_label_waitcheck },
1939 { MAC_INIT_TEMP_LABEL,
1940 (macop_t)mac_mls_init_label },
1941 { MAC_INIT_VNODE_LABEL,
1942 (macop_t)mac_mls_init_label },
1943 { MAC_DESTROY_BPFDESC_LABEL,
1944 (macop_t)mac_mls_destroy_label },
1945 { MAC_DESTROY_CRED_LABEL,
1946 (macop_t)mac_mls_destroy_label },
1947 { MAC_DESTROY_DEVFSDIRENT_LABEL,
1948 (macop_t)mac_mls_destroy_label },
1949 { MAC_DESTROY_IFNET_LABEL,
1950 (macop_t)mac_mls_destroy_label },
1951 { MAC_DESTROY_IPQ_LABEL,
1952 (macop_t)mac_mls_destroy_label },
1953 { MAC_DESTROY_MBUF_LABEL,
1954 (macop_t)mac_mls_destroy_label },
1955 { MAC_DESTROY_MOUNT_LABEL,
1956 (macop_t)mac_mls_destroy_label },
1957 { MAC_DESTROY_MOUNT_FS_LABEL,
1958 (macop_t)mac_mls_destroy_label },
1959 { MAC_DESTROY_PIPE_LABEL,
1960 (macop_t)mac_mls_destroy_label },
1961 { MAC_DESTROY_SOCKET_LABEL,
1962 (macop_t)mac_mls_destroy_label },
1963 { MAC_DESTROY_SOCKET_PEER_LABEL,
1964 (macop_t)mac_mls_destroy_label },
1965 { MAC_DESTROY_TEMP_LABEL,
1966 (macop_t)mac_mls_destroy_label },
1967 { MAC_DESTROY_VNODE_LABEL,
1968 (macop_t)mac_mls_destroy_label },
1969 { MAC_EXTERNALIZE,
1970 (macop_t)mac_mls_externalize },
1971 { MAC_INTERNALIZE,
1972 (macop_t)mac_mls_internalize },
1973 { MAC_CREATE_DEVFS_DEVICE,
1974 (macop_t)mac_mls_create_devfs_device },
1975 { MAC_CREATE_DEVFS_DIRECTORY,
1976 (macop_t)mac_mls_create_devfs_directory },
1977 { MAC_CREATE_DEVFS_SYMLINK,
1978 (macop_t)mac_mls_create_devfs_symlink },
1979 { MAC_CREATE_DEVFS_VNODE,
1980 (macop_t)mac_mls_create_devfs_vnode },
1981 { MAC_CREATE_VNODE,
1982 (macop_t)mac_mls_create_vnode },
1983 { MAC_CREATE_MOUNT,
1984 (macop_t)mac_mls_create_mount },
1985 { MAC_CREATE_ROOT_MOUNT,
1986 (macop_t)mac_mls_create_root_mount },
1987 { MAC_RELABEL_VNODE,
1988 (macop_t)mac_mls_relabel_vnode },
1989 { MAC_UPDATE_DEVFSDIRENT,
1990 (macop_t)mac_mls_update_devfsdirent },
1991 { MAC_UPDATE_PROCFSVNODE,
1992 (macop_t)mac_mls_update_procfsvnode },
1993 { MAC_UPDATE_VNODE_FROM_EXTERNALIZED,
1994 (macop_t)mac_mls_update_vnode_from_externalized },
1995 { MAC_UPDATE_VNODE_FROM_MOUNT,
1996 (macop_t)mac_mls_update_vnode_from_mount },
1997 { MAC_CREATE_MBUF_FROM_SOCKET,
1998 (macop_t)mac_mls_create_mbuf_from_socket },
1999 { MAC_CREATE_PIPE,
2000 (macop_t)mac_mls_create_pipe },
2001 { MAC_CREATE_SOCKET,
2002 (macop_t)mac_mls_create_socket },
2003 { MAC_CREATE_SOCKET_FROM_SOCKET,
2004 (macop_t)mac_mls_create_socket_from_socket },
2005 { MAC_RELABEL_PIPE,
2006 (macop_t)mac_mls_relabel_pipe },
2007 { MAC_RELABEL_SOCKET,
2008 (macop_t)mac_mls_relabel_socket },
2009 { MAC_SET_SOCKET_PEER_FROM_MBUF,
2010 (macop_t)mac_mls_set_socket_peer_from_mbuf },
2011 { MAC_SET_SOCKET_PEER_FROM_SOCKET,
2012 (macop_t)mac_mls_set_socket_peer_from_socket },
2013 { MAC_CREATE_BPFDESC,
2014 (macop_t)mac_mls_create_bpfdesc },
2015 { MAC_CREATE_DATAGRAM_FROM_IPQ,
2016 (macop_t)mac_mls_create_datagram_from_ipq },
2017 { MAC_CREATE_FRAGMENT,
2018 (macop_t)mac_mls_create_fragment },
2019 { MAC_CREATE_IFNET,
2020 (macop_t)mac_mls_create_ifnet },
2021 { MAC_CREATE_IPQ,
2022 (macop_t)mac_mls_create_ipq },
2023 { MAC_CREATE_MBUF_FROM_MBUF,
2024 (macop_t)mac_mls_create_mbuf_from_mbuf },
2025 { MAC_CREATE_MBUF_LINKLAYER,
2026 (macop_t)mac_mls_create_mbuf_linklayer },
2027 { MAC_CREATE_MBUF_FROM_BPFDESC,
2028 (macop_t)mac_mls_create_mbuf_from_bpfdesc },
2029 { MAC_CREATE_MBUF_FROM_IFNET,
2030 (macop_t)mac_mls_create_mbuf_from_ifnet },
2031 { MAC_CREATE_MBUF_MULTICAST_ENCAP,
2032 (macop_t)mac_mls_create_mbuf_multicast_encap },
2033 { MAC_CREATE_MBUF_NETLAYER,
2034 (macop_t)mac_mls_create_mbuf_netlayer },
2035 { MAC_FRAGMENT_MATCH,
2036 (macop_t)mac_mls_fragment_match },
2037 { MAC_RELABEL_IFNET,
2038 (macop_t)mac_mls_relabel_ifnet },
2039 { MAC_UPDATE_IPQ,
2040 (macop_t)mac_mls_update_ipq },
2041 { MAC_CREATE_CRED,
2042 (macop_t)mac_mls_create_cred },
2043 { MAC_EXECVE_TRANSITION,
2044 (macop_t)mac_mls_execve_transition },
2045 { MAC_EXECVE_WILL_TRANSITION,
2046 (macop_t)mac_mls_execve_will_transition },
2047 { MAC_CREATE_PROC0,
2048 (macop_t)mac_mls_create_proc0 },
2049 { MAC_CREATE_PROC1,
2050 (macop_t)mac_mls_create_proc1 },
2051 { MAC_RELABEL_CRED,
2052 (macop_t)mac_mls_relabel_cred },
2053 { MAC_CHECK_BPFDESC_RECEIVE,
2054 (macop_t)mac_mls_check_bpfdesc_receive },
2055 { MAC_CHECK_CRED_RELABEL,
2056 (macop_t)mac_mls_check_cred_relabel },
2057 { MAC_CHECK_CRED_VISIBLE,
2058 (macop_t)mac_mls_check_cred_visible },
2059 { MAC_CHECK_IFNET_RELABEL,
2060 (macop_t)mac_mls_check_ifnet_relabel },
2061 { MAC_CHECK_IFNET_TRANSMIT,
2062 (macop_t)mac_mls_check_ifnet_transmit },
2063 { MAC_CHECK_MOUNT_STAT,
2064 (macop_t)mac_mls_check_mount_stat },
2065 { MAC_CHECK_PIPE_IOCTL,
2066 (macop_t)mac_mls_check_pipe_ioctl },
2067 { MAC_CHECK_PIPE_POLL,
2068 (macop_t)mac_mls_check_pipe_poll },
2069 { MAC_CHECK_PIPE_READ,
2070 (macop_t)mac_mls_check_pipe_read },
2071 { MAC_CHECK_PIPE_RELABEL,
2072 (macop_t)mac_mls_check_pipe_relabel },
2073 { MAC_CHECK_PIPE_STAT,
2074 (macop_t)mac_mls_check_pipe_stat },
2075 { MAC_CHECK_PIPE_WRITE,
2076 (macop_t)mac_mls_check_pipe_write },
2077 { MAC_CHECK_PROC_DEBUG,
2078 (macop_t)mac_mls_check_proc_debug },
2079 { MAC_CHECK_PROC_SCHED,
2080 (macop_t)mac_mls_check_proc_sched },
2081 { MAC_CHECK_PROC_SIGNAL,
2082 (macop_t)mac_mls_check_proc_signal },
2083 { MAC_CHECK_SOCKET_DELIVER,
2084 (macop_t)mac_mls_check_socket_deliver },
2085 { MAC_CHECK_SOCKET_RELABEL,
2086 (macop_t)mac_mls_check_socket_relabel },
2087 { MAC_CHECK_SOCKET_VISIBLE,
2088 (macop_t)mac_mls_check_socket_visible },
2089 { MAC_CHECK_VNODE_ACCESS,
2090 (macop_t)mac_mls_check_vnode_access },
2091 { MAC_CHECK_VNODE_CHDIR,
2092 (macop_t)mac_mls_check_vnode_chdir },
2093 { MAC_CHECK_VNODE_CHROOT,
2094 (macop_t)mac_mls_check_vnode_chroot },
2095 { MAC_CHECK_VNODE_CREATE,
2096 (macop_t)mac_mls_check_vnode_create },
2097 { MAC_CHECK_VNODE_DELETE,
2098 (macop_t)mac_mls_check_vnode_delete },
2099 { MAC_CHECK_VNODE_DELETEACL,
2100 (macop_t)mac_mls_check_vnode_deleteacl },
2101 { MAC_CHECK_VNODE_EXEC,
2102 (macop_t)mac_mls_check_vnode_exec },
2103 { MAC_CHECK_VNODE_GETACL,
2104 (macop_t)mac_mls_check_vnode_getacl },
2105 { MAC_CHECK_VNODE_GETEXTATTR,
2106 (macop_t)mac_mls_check_vnode_getextattr },
2107 { MAC_CHECK_VNODE_LINK,
2108 (macop_t)mac_mls_check_vnode_link },
2109 { MAC_CHECK_VNODE_LOOKUP,
2110 (macop_t)mac_mls_check_vnode_lookup },
2111 { MAC_CHECK_VNODE_MMAP,
2112 (macop_t)mac_mls_check_vnode_mmap },
2113 { MAC_CHECK_VNODE_MPROTECT,
2114 (macop_t)mac_mls_check_vnode_mmap },
2115 { MAC_CHECK_VNODE_OPEN,
2116 (macop_t)mac_mls_check_vnode_open },
2117 { MAC_CHECK_VNODE_POLL,
2118 (macop_t)mac_mls_check_vnode_poll },
2119 { MAC_CHECK_VNODE_READ,
2120 (macop_t)mac_mls_check_vnode_read },
2121 { MAC_CHECK_VNODE_READDIR,
2122 (macop_t)mac_mls_check_vnode_readdir },
2123 { MAC_CHECK_VNODE_READLINK,
2124 (macop_t)mac_mls_check_vnode_readlink },
2125 { MAC_CHECK_VNODE_RELABEL,
2126 (macop_t)mac_mls_check_vnode_relabel },
2127 { MAC_CHECK_VNODE_RENAME_FROM,
2128 (macop_t)mac_mls_check_vnode_rename_from },
2129 { MAC_CHECK_VNODE_RENAME_TO,
2130 (macop_t)mac_mls_check_vnode_rename_to },
2131 { MAC_CHECK_VNODE_REVOKE,
2132 (macop_t)mac_mls_check_vnode_revoke },
2133 { MAC_CHECK_VNODE_SETACL,
2134 (macop_t)mac_mls_check_vnode_setacl },
2135 { MAC_CHECK_VNODE_SETEXTATTR,
2136 (macop_t)mac_mls_check_vnode_setextattr },
2137 { MAC_CHECK_VNODE_SETFLAGS,
2138 (macop_t)mac_mls_check_vnode_setflags },
2139 { MAC_CHECK_VNODE_SETMODE,
2140 (macop_t)mac_mls_check_vnode_setmode },
2141 { MAC_CHECK_VNODE_SETOWNER,
2142 (macop_t)mac_mls_check_vnode_setowner },
2143 { MAC_CHECK_VNODE_SETUTIMES,
2144 (macop_t)mac_mls_check_vnode_setutimes },
2145 { MAC_CHECK_VNODE_STAT,
2146 (macop_t)mac_mls_check_vnode_stat },
2147 { MAC_CHECK_VNODE_WRITE,
2148 (macop_t)mac_mls_check_vnode_write },
2149 { MAC_OP_LAST, NULL }
2150};
2151
2152MAC_POLICY_SET(mac_mls_ops, trustedbsd_mac_mls, "TrustedBSD MAC/MLS",
2153 MPC_LOADTIME_FLAG_NOTLATE, &mac_mls_slot);