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