1/*-
2 * Copyright (c) 1999-2002 Robert N. M. Watson
3 * Copyright (c) 2001-2003 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 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $FreeBSD: head/sys/security/mac_lomac/mac_lomac.c 126097 2004-02-22 00:33:12Z rwatson $
35 */
36
37/*
38 * Developed by the TrustedBSD Project.
39 * Low-watermark floating label mandatory integrity policy.
40 */
41
42#include <sys/types.h>
43#include <sys/param.h>
44#include <sys/acl.h>
45#include <sys/conf.h>
46#include <sys/extattr.h>
47#include <sys/kernel.h>
48#include <sys/mac.h>
49#include <sys/malloc.h>
50#include <sys/mount.h>
51#include <sys/proc.h>
52#include <sys/sbuf.h>
53#include <sys/systm.h>
54#include <sys/sysproto.h>
55#include <sys/sysent.h>
56#include <sys/systm.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#include <sys/syslog.h>
64
65#include <fs/devfs/devfs.h>
66
67#include <net/bpfdesc.h>
68#include <net/if.h>
69#include <net/if_types.h>
70#include <net/if_var.h>
71
72#include <netinet/in.h>
73#include <netinet/in_pcb.h>
74#include <netinet/ip_var.h>
75
76#include <vm/vm.h>
77
78#include <sys/mac_policy.h>
79
80#include <security/mac_lomac/mac_lomac.h>
81
82struct mac_lomac_proc {
83 struct mac_lomac mac_lomac;
84 struct mtx mtx;
85};
86
87SYSCTL_DECL(_security_mac);
88
89SYSCTL_NODE(_security_mac, OID_AUTO, lomac, CTLFLAG_RW, 0,
90 "TrustedBSD mac_lomac policy controls");
91
92static int mac_lomac_label_size = sizeof(struct mac_lomac);
93SYSCTL_INT(_security_mac_lomac, OID_AUTO, label_size, CTLFLAG_RD,
94 &mac_lomac_label_size, 0, "Size of struct mac_lomac");
95
96static int mac_lomac_enabled = 1;
97SYSCTL_INT(_security_mac_lomac, OID_AUTO, enabled, CTLFLAG_RW,
98 &mac_lomac_enabled, 0, "Enforce MAC/LOMAC policy");
99TUNABLE_INT("security.mac.lomac.enabled", &mac_lomac_enabled);
100
101static int destroyed_not_inited;
102SYSCTL_INT(_security_mac_lomac, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
103 &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
104
105static int trust_all_interfaces = 0;
106SYSCTL_INT(_security_mac_lomac, OID_AUTO, trust_all_interfaces, CTLFLAG_RD,
107 &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/LOMAC");
108TUNABLE_INT("security.mac.lomac.trust_all_interfaces", &trust_all_interfaces);
109
110static char trusted_interfaces[128];
111SYSCTL_STRING(_security_mac_lomac, OID_AUTO, trusted_interfaces, CTLFLAG_RD,
112 trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/LOMAC");
113TUNABLE_STR("security.mac.lomac.trusted_interfaces", trusted_interfaces,
114 sizeof(trusted_interfaces));
115
116static int ptys_equal = 0;
117SYSCTL_INT(_security_mac_lomac, OID_AUTO, ptys_equal, CTLFLAG_RW,
118 &ptys_equal, 0, "Label pty devices as lomac/equal on create");
119TUNABLE_INT("security.mac.lomac.ptys_equal", &ptys_equal);
120
121static int revocation_enabled = 1;
122SYSCTL_INT(_security_mac_lomac, OID_AUTO, revocation_enabled, CTLFLAG_RW,
123 &revocation_enabled, 0, "Revoke access to objects on relabel");
124TUNABLE_INT("security.mac.lomac.revocation_enabled", &revocation_enabled);
125
126static int mac_lomac_slot;
127#define SLOT(l) ((struct mac_lomac *)LABEL_TO_SLOT((l), mac_lomac_slot).l_ptr)
128#define PSLOT(l) ((struct mac_lomac_proc *) \
129 LABEL_TO_SLOT((l), mac_lomac_slot).l_ptr)
130
131MALLOC_DEFINE(M_MACLOMAC, "lomac label", "MAC/LOMAC labels");
132
133static struct mac_lomac *
134lomac_alloc(int flag)
135{
136 struct mac_lomac *mac_lomac;
137
138 mac_lomac = malloc(sizeof(struct mac_lomac), M_MACLOMAC, M_ZERO | flag);
139
140 return (mac_lomac);
141}
142
143static void
144lomac_free(struct mac_lomac *mac_lomac)
145{
146
147 if (mac_lomac != NULL)
148 free(mac_lomac, M_MACLOMAC);
149 else
150 atomic_add_int(&destroyed_not_inited, 1);
151}
152
153static int
154lomac_atmostflags(struct mac_lomac *mac_lomac, int flags)
155{
156
157 if ((mac_lomac->ml_flags & flags) != mac_lomac->ml_flags)
158 return (EINVAL);
159 return (0);
160}
161
162static int
163mac_lomac_dominate_element(struct mac_lomac_element *a,
164 struct mac_lomac_element *b)
165{
166
167 switch (a->mle_type) {
168 case MAC_LOMAC_TYPE_EQUAL:
169 case MAC_LOMAC_TYPE_HIGH:
170 return (1);
171
172 case MAC_LOMAC_TYPE_LOW:
173 switch (b->mle_type) {
174 case MAC_LOMAC_TYPE_GRADE:
175 case MAC_LOMAC_TYPE_HIGH:
176 return (0);
177
178 case MAC_LOMAC_TYPE_EQUAL:
179 case MAC_LOMAC_TYPE_LOW:
180 return (1);
181
182 default:
183 panic("mac_lomac_dominate_element: b->mle_type invalid");
184 }
185
186 case MAC_LOMAC_TYPE_GRADE:
187 switch (b->mle_type) {
188 case MAC_LOMAC_TYPE_EQUAL:
189 case MAC_LOMAC_TYPE_LOW:
190 return (1);
191
192 case MAC_LOMAC_TYPE_HIGH:
193 return (0);
194
195 case MAC_LOMAC_TYPE_GRADE:
196 return (a->mle_grade >= b->mle_grade);
197
198 default:
199 panic("mac_lomac_dominate_element: b->mle_type invalid");
200 }
201
202 default:
203 panic("mac_lomac_dominate_element: a->mle_type invalid");
204 }
205}
206
207static int
208mac_lomac_range_in_range(struct mac_lomac *rangea, struct mac_lomac *rangeb)
209{
210
211 return (mac_lomac_dominate_element(&rangeb->ml_rangehigh,
212 &rangea->ml_rangehigh) &&
213 mac_lomac_dominate_element(&rangea->ml_rangelow,
214 &rangeb->ml_rangelow));
215}
216
217static int
218mac_lomac_single_in_range(struct mac_lomac *single, struct mac_lomac *range)
219{
220
221 KASSERT((single->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
222 ("mac_lomac_single_in_range: a not single"));
223 KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
224 ("mac_lomac_single_in_range: b not range"));
225
226 return (mac_lomac_dominate_element(&range->ml_rangehigh,
227 &single->ml_single) &&
228 mac_lomac_dominate_element(&single->ml_single,
229 &range->ml_rangelow));
230}
231
232static int
233mac_lomac_auxsingle_in_range(struct mac_lomac *single, struct mac_lomac *range)
234{
235
236 KASSERT((single->ml_flags & MAC_LOMAC_FLAG_AUX) != 0,
237 ("mac_lomac_single_in_range: a not auxsingle"));
238 KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
239 ("mac_lomac_single_in_range: b not range"));
240
241 return (mac_lomac_dominate_element(&range->ml_rangehigh,
242 &single->ml_auxsingle) &&
243 mac_lomac_dominate_element(&single->ml_auxsingle,
244 &range->ml_rangelow));
245}
246
247static int
248mac_lomac_dominate_single(struct mac_lomac *a, struct mac_lomac *b)
249{
250 KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
251 ("mac_lomac_dominate_single: a not single"));
252 KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
253 ("mac_lomac_dominate_single: b not single"));
254
255 return (mac_lomac_dominate_element(&a->ml_single, &b->ml_single));
256}
257
258static int
259mac_lomac_subject_dominate(struct mac_lomac *a, struct mac_lomac *b)
260{
261 KASSERT((~a->ml_flags &
262 (MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_RANGE)) == 0,
263 ("mac_lomac_dominate_single: a not subject"));
264 KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
265 ("mac_lomac_dominate_single: b not single"));
266
267 return (mac_lomac_dominate_element(&a->ml_rangehigh,
268 &b->ml_single));
269}
270
271static int
272mac_lomac_equal_element(struct mac_lomac_element *a, struct mac_lomac_element *b)
273{
274
275 if (a->mle_type == MAC_LOMAC_TYPE_EQUAL ||
276 b->mle_type == MAC_LOMAC_TYPE_EQUAL)
277 return (1);
278
279 return (a->mle_type == b->mle_type && a->mle_grade == b->mle_grade);
280}
281
282static int
283mac_lomac_equal_single(struct mac_lomac *a, struct mac_lomac *b)
284{
285
286 KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
287 ("mac_lomac_equal_single: a not single"));
288 KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
289 ("mac_lomac_equal_single: b not single"));
290
291 return (mac_lomac_equal_element(&a->ml_single, &b->ml_single));
292}
293
294static int
295mac_lomac_contains_equal(struct mac_lomac *mac_lomac)
296{
297
298 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE)
299 if (mac_lomac->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL)
300 return (1);
301 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_AUX)
302 if (mac_lomac->ml_auxsingle.mle_type == MAC_LOMAC_TYPE_EQUAL)
303 return (1);
304
305 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_RANGE) {
306 if (mac_lomac->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL)
307 return (1);
308 if (mac_lomac->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL)
309 return (1);
310 }
311
312 return (0);
313}
314
315static int
316mac_lomac_subject_privileged(struct mac_lomac *mac_lomac)
317{
318
319 KASSERT((mac_lomac->ml_flags & MAC_LOMAC_FLAGS_BOTH) ==
320 MAC_LOMAC_FLAGS_BOTH,
321 ("mac_lomac_subject_privileged: subject doesn't have both labels"));
322
323 /* If the single is EQUAL, it's ok. */
324 if (mac_lomac->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL)
325 return (0);
326
327 /* If either range endpoint is EQUAL, it's ok. */
328 if (mac_lomac->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL ||
329 mac_lomac->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL)
330 return (0);
331
332 /* If the range is low-high, it's ok. */
333 if (mac_lomac->ml_rangelow.mle_type == MAC_LOMAC_TYPE_LOW &&
334 mac_lomac->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_HIGH)
335 return (0);
336
337 /* It's not ok. */
338 return (EPERM);
339}
340
341static int
342mac_lomac_high_single(struct mac_lomac *mac_lomac)
343{
344
345 KASSERT((mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
346 ("mac_lomac_high_single: mac_lomac not single"));
347
348 return (mac_lomac->ml_single.mle_type == MAC_LOMAC_TYPE_HIGH);
349}
350
351static int
352mac_lomac_valid(struct mac_lomac *mac_lomac)
353{
354
355 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
356 switch (mac_lomac->ml_single.mle_type) {
357 case MAC_LOMAC_TYPE_GRADE:
358 case MAC_LOMAC_TYPE_EQUAL:
359 case MAC_LOMAC_TYPE_HIGH:
360 case MAC_LOMAC_TYPE_LOW:
361 break;
362
363 default:
364 return (EINVAL);
365 }
366 } else {
367 if (mac_lomac->ml_single.mle_type != MAC_LOMAC_TYPE_UNDEF)
368 return (EINVAL);
369 }
370
371 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_AUX) {
372 switch (mac_lomac->ml_auxsingle.mle_type) {
373 case MAC_LOMAC_TYPE_GRADE:
374 case MAC_LOMAC_TYPE_EQUAL:
375 case MAC_LOMAC_TYPE_HIGH:
376 case MAC_LOMAC_TYPE_LOW:
377 break;
378
379 default:
380 return (EINVAL);
381 }
382 } else {
383 if (mac_lomac->ml_auxsingle.mle_type != MAC_LOMAC_TYPE_UNDEF)
384 return (EINVAL);
385 }
386
387 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_RANGE) {
388 switch (mac_lomac->ml_rangelow.mle_type) {
389 case MAC_LOMAC_TYPE_GRADE:
390 case MAC_LOMAC_TYPE_EQUAL:
391 case MAC_LOMAC_TYPE_HIGH:
392 case MAC_LOMAC_TYPE_LOW:
393 break;
394
395 default:
396 return (EINVAL);
397 }
398
399 switch (mac_lomac->ml_rangehigh.mle_type) {
400 case MAC_LOMAC_TYPE_GRADE:
401 case MAC_LOMAC_TYPE_EQUAL:
402 case MAC_LOMAC_TYPE_HIGH:
403 case MAC_LOMAC_TYPE_LOW:
404 break;
405
406 default:
407 return (EINVAL);
408 }
409 if (!mac_lomac_dominate_element(&mac_lomac->ml_rangehigh,
410 &mac_lomac->ml_rangelow))
411 return (EINVAL);
412 } else {
413 if (mac_lomac->ml_rangelow.mle_type != MAC_LOMAC_TYPE_UNDEF ||
414 mac_lomac->ml_rangehigh.mle_type != MAC_LOMAC_TYPE_UNDEF)
415 return (EINVAL);
416 }
417
418 return (0);
419}
420
421static void
422mac_lomac_set_range(struct mac_lomac *mac_lomac, u_short typelow,
423 u_short gradelow, u_short typehigh, u_short gradehigh)
424{
425
426 mac_lomac->ml_rangelow.mle_type = typelow;
427 mac_lomac->ml_rangelow.mle_grade = gradelow;
428 mac_lomac->ml_rangehigh.mle_type = typehigh;
429 mac_lomac->ml_rangehigh.mle_grade = gradehigh;
430 mac_lomac->ml_flags |= MAC_LOMAC_FLAG_RANGE;
431}
432
433static void
434mac_lomac_set_single(struct mac_lomac *mac_lomac, u_short type, u_short grade)
435{
436
437 mac_lomac->ml_single.mle_type = type;
438 mac_lomac->ml_single.mle_grade = grade;
439 mac_lomac->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
440}
441
442static void
443mac_lomac_copy_range(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
444{
445
446 KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
447 ("mac_lomac_copy_range: labelfrom not range"));
448
449 labelto->ml_rangelow = labelfrom->ml_rangelow;
450 labelto->ml_rangehigh = labelfrom->ml_rangehigh;
451 labelto->ml_flags |= MAC_LOMAC_FLAG_RANGE;
452}
453
454static void
455mac_lomac_copy_single(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
456{
457
458 KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
459 ("mac_lomac_copy_single: labelfrom not single"));
460
461 labelto->ml_single = labelfrom->ml_single;
462 labelto->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
463}
464
465static void
466mac_lomac_copy_auxsingle(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
467{
468
469 KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_AUX) != 0,
470 ("mac_lomac_copy_auxsingle: labelfrom not auxsingle"));
471
472 labelto->ml_auxsingle = labelfrom->ml_auxsingle;
473 labelto->ml_flags |= MAC_LOMAC_FLAG_AUX;
474}
475
476static void
477mac_lomac_copy(struct mac_lomac *source, struct mac_lomac *dest)
478{
479
480 if (source->ml_flags & MAC_LOMAC_FLAG_SINGLE)
481 mac_lomac_copy_single(source, dest);
482 if (source->ml_flags & MAC_LOMAC_FLAG_AUX)
483 mac_lomac_copy_auxsingle(source, dest);
484 if (source->ml_flags & MAC_LOMAC_FLAG_RANGE)
485 mac_lomac_copy_range(source, dest);
486}
487
488static int mac_lomac_to_string(struct sbuf *sb,
489 struct mac_lomac *mac_lomac);
490
491static int
492maybe_demote(struct mac_lomac *subjlabel, struct mac_lomac *objlabel,
493 const char *actionname, const char *objname, struct vnode *vpq)
494{
495 struct sbuf subjlabel_sb, subjtext_sb, objlabel_sb;
496 char *subjlabeltext, *objlabeltext, *subjtext;
497 struct mac_lomac cached_subjlabel;
498 struct mac_lomac_proc *subj;
499 struct vattr va;
500 struct proc *p;
501 pid_t pgid;
502
503 subj = PSLOT(curthread->td_proc->p_label);
504
505 p = curthread->td_proc;
506 mtx_lock(&subj->mtx);
507 if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
508 /*
509 * Check to see if the pending demotion would be more or
510 * less severe than this one, and keep the more severe.
511 * This can only happen for a multi-threaded application.
512 */
513 if (mac_lomac_dominate_single(objlabel, &subj->mac_lomac)) {
514 mtx_unlock(&subj->mtx);
515 return (0);
516 }
517 }
518 bzero(&subj->mac_lomac, sizeof(subj->mac_lomac));
519 /*
520 * Always demote the single label.
521 */
522 mac_lomac_copy_single(objlabel, &subj->mac_lomac);
523 /*
524 * Start with the original range, then minimize each side of
525 * the range to the point of not dominating the object. The
526 * high side will always be demoted, of course.
527 */
528 mac_lomac_copy_range(subjlabel, &subj->mac_lomac);
529 if (!mac_lomac_dominate_element(&objlabel->ml_single,
530 &subj->mac_lomac.ml_rangelow))
531 subj->mac_lomac.ml_rangelow = objlabel->ml_single;
532 subj->mac_lomac.ml_rangehigh = objlabel->ml_single;
533 subj->mac_lomac.ml_flags |= MAC_LOMAC_FLAG_UPDATE;
534 mtx_lock_spin(&sched_lock);
535 curthread->td_flags |= TDF_ASTPENDING;
536 curthread->td_proc->p_sflag |= PS_MACPEND;
537 mtx_unlock_spin(&sched_lock);
538
539 /*
540 * Avoid memory allocation while holding a mutex; cache the
541 * label.
542 */
543 mac_lomac_copy_single(&subj->mac_lomac, &cached_subjlabel);
544 mtx_unlock(&subj->mtx);
545
546 sbuf_new(&subjlabel_sb, NULL, 0, SBUF_AUTOEXTEND);
547 mac_lomac_to_string(&subjlabel_sb, subjlabel);
548 sbuf_finish(&subjlabel_sb);
549 subjlabeltext = sbuf_data(&subjlabel_sb);
550
551 sbuf_new(&subjtext_sb, NULL, 0, SBUF_AUTOEXTEND);
552 mac_lomac_to_string(&subjtext_sb, &subj->mac_lomac);
553 sbuf_finish(&subjtext_sb);
554 subjtext = sbuf_data(&subjtext_sb);
555
556 sbuf_new(&objlabel_sb, NULL, 0, SBUF_AUTOEXTEND);
557 mac_lomac_to_string(&objlabel_sb, objlabel);
558 sbuf_finish(&objlabel_sb);
559 objlabeltext = sbuf_data(&objlabel_sb);
560
561 pgid = p->p_pgrp->pg_id; /* XXX could be stale? */
562 if (vpq != NULL && VOP_GETATTR(vpq, &va, curthread->td_ucred,
563 curthread) == 0) {
564 log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to"
565 " level %s after %s a level-%s %s (inode=%ld, "
566 "mountpount=%s)\n",
567 subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid,
568 p->p_comm, subjtext, actionname, objlabeltext, objname,
569 va.va_fileid, vpq->v_mount->mnt_stat.f_mntonname);
570 } else {
571 log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to"
572 " level %s after %s a level-%s %s\n",
573 subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid,
574 p->p_comm, subjtext, actionname, objlabeltext, objname);
575 }
576
577 sbuf_delete(&subjlabel_sb);
578 sbuf_delete(&subjtext_sb);
579 sbuf_delete(&objlabel_sb);
580
581 return (0);
582}
583
584/*
585 * Relabel "to" to "from" only if "from" is a valid label (contains
586 * at least a single), as for a relabel operation which may or may
587 * not involve a relevant label.
588 */
589static void
590try_relabel(struct mac_lomac *from, struct mac_lomac *to)
591{
592
593 if (from->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
594 bzero(to, sizeof(*to));
595 mac_lomac_copy(from, to);
596 }
597}
598
599/*
600 * Policy module operations.
601 */
602static void
603mac_lomac_init(struct mac_policy_conf *conf)
604{
605
606}
607
608/*
609 * Label operations.
610 */
611static void
612mac_lomac_init_label(struct label *label)
613{
614
615 SLOT(label) = lomac_alloc(M_WAITOK);
616}
617
618static int
619mac_lomac_init_label_waitcheck(struct label *label, int flag)
620{
621
622 SLOT(label) = lomac_alloc(flag);
623 if (SLOT(label) == NULL)
624 return (ENOMEM);
625
626 return (0);
627}
628
629static void
630mac_lomac_init_proc_label(struct label *label)
631{
632
633 PSLOT(label) = malloc(sizeof(struct mac_lomac_proc), M_MACLOMAC,
634 M_ZERO | M_WAITOK);
635 mtx_init(&PSLOT(label)->mtx, "MAC/Lomac proc lock", NULL, MTX_DEF);
636}
637
638static void
639mac_lomac_destroy_label(struct label *label)
640{
641
642 lomac_free(SLOT(label));
643 SLOT(label) = NULL;
644}
645
646static void
647mac_lomac_destroy_proc_label(struct label *label)
648{
649
650 mtx_destroy(&PSLOT(label)->mtx);
651 FREE(PSLOT(label), M_MACLOMAC);
652 PSLOT(label) = NULL;
653}
654
655static int
656mac_lomac_element_to_string(struct sbuf *sb, struct mac_lomac_element *element)
657{
658
659 switch (element->mle_type) {
660 case MAC_LOMAC_TYPE_HIGH:
661 return (sbuf_printf(sb, "high"));
662
663 case MAC_LOMAC_TYPE_LOW:
664 return (sbuf_printf(sb, "low"));
665
666 case MAC_LOMAC_TYPE_EQUAL:
667 return (sbuf_printf(sb, "equal"));
668
669 case MAC_LOMAC_TYPE_GRADE:
670 return (sbuf_printf(sb, "%d", element->mle_grade));
671
672 default:
673 panic("mac_lomac_element_to_string: invalid type (%d)",
674 element->mle_type);
675 }
676}
677
678static int
679mac_lomac_to_string(struct sbuf *sb, struct mac_lomac *mac_lomac)
680{
681
682 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
683 if (mac_lomac_element_to_string(sb, &mac_lomac->ml_single)
684 == -1)
685 return (EINVAL);
686 }
687
688 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_AUX) {
689 if (sbuf_putc(sb, '[') == -1)
690 return (EINVAL);
691
692 if (mac_lomac_element_to_string(sb, &mac_lomac->ml_auxsingle)
693 == -1)
694 return (EINVAL);
695
696 if (sbuf_putc(sb, ']') == -1)
697 return (EINVAL);
698 }
699
700 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_RANGE) {
701 if (sbuf_putc(sb, '(') == -1)
702 return (EINVAL);
703
704 if (mac_lomac_element_to_string(sb, &mac_lomac->ml_rangelow)
705 == -1)
706 return (EINVAL);
707
708 if (sbuf_putc(sb, '-') == -1)
709 return (EINVAL);
710
711 if (mac_lomac_element_to_string(sb, &mac_lomac->ml_rangehigh)
712 == -1)
713 return (EINVAL);
714
715 if (sbuf_putc(sb, ')') == -1)
716 return (EINVAL);
717 }
718
719 return (0);
720}
721
722static int
723mac_lomac_externalize_label(struct label *label, char *element_name,
724 struct sbuf *sb, int *claimed)
725{
726 struct mac_lomac *mac_lomac;
727
728 if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0)
729 return (0);
730
731 (*claimed)++;
732
733 mac_lomac = SLOT(label);
734
735 return (mac_lomac_to_string(sb, mac_lomac));
736}
737
738static int
739mac_lomac_parse_element(struct mac_lomac_element *element, char *string)
740{
741
742 if (strcmp(string, "high") == 0 ||
743 strcmp(string, "hi") == 0) {
744 element->mle_type = MAC_LOMAC_TYPE_HIGH;
745 element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
746 } else if (strcmp(string, "low") == 0 ||
747 strcmp(string, "lo") == 0) {
748 element->mle_type = MAC_LOMAC_TYPE_LOW;
749 element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
750 } else if (strcmp(string, "equal") == 0 ||
751 strcmp(string, "eq") == 0) {
752 element->mle_type = MAC_LOMAC_TYPE_EQUAL;
753 element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
754 } else {
755 char *p0, *p1;
756 int d;
757
758 p0 = string;
759 d = strtol(p0, &p1, 10);
760
761 if (d < 0 || d > 65535)
762 return (EINVAL);
763 element->mle_type = MAC_LOMAC_TYPE_GRADE;
764 element->mle_grade = d;
765
766 if (p1 == p0 || *p1 != '\0')
767 return (EINVAL);
768 }
769
770 return (0);
771}
772
773/*
774 * Note: destructively consumes the string, make a local copy before
775 * calling if that's a problem.
776 */
777static int
778mac_lomac_parse(struct mac_lomac *mac_lomac, char *string)
779{
780 char *range, *rangeend, *rangehigh, *rangelow, *single, *auxsingle,
781 *auxsingleend;
782 int error;
783
784 /* Do we have a range? */
785 single = string;
786 range = index(string, '(');
787 if (range == single)
788 single = NULL;
789 auxsingle = index(string, '[');
790 if (auxsingle == single)
791 single = NULL;
792 if (range != NULL && auxsingle != NULL)
793 return (EINVAL);
794 rangelow = rangehigh = NULL;
795 if (range != NULL) {
796 /* Nul terminate the end of the single string. */
797 *range = '\0';
798 range++;
799 rangelow = range;
800 rangehigh = index(rangelow, '-');
801 if (rangehigh == NULL)
802 return (EINVAL);
803 rangehigh++;
804 if (*rangelow == '\0' || *rangehigh == '\0')
805 return (EINVAL);
806 rangeend = index(rangehigh, ')');
807 if (rangeend == NULL)
808 return (EINVAL);
809 if (*(rangeend + 1) != '\0')
810 return (EINVAL);
811 /* Nul terminate the ends of the ranges. */
812 *(rangehigh - 1) = '\0';
813 *rangeend = '\0';
814 }
815 KASSERT((rangelow != NULL && rangehigh != NULL) ||
816 (rangelow == NULL && rangehigh == NULL),
817 ("mac_lomac_internalize_label: range mismatch"));
818 if (auxsingle != NULL) {
819 /* Nul terminate the end of the single string. */
820 *auxsingle = '\0';
821 auxsingle++;
822 auxsingleend = index(auxsingle, ']');
823 if (auxsingleend == NULL)
824 return (EINVAL);
825 if (*(auxsingleend + 1) != '\0')
826 return (EINVAL);
827 /* Nul terminate the end of the auxsingle. */
828 *auxsingleend = '\0';
829 }
830
831 bzero(mac_lomac, sizeof(*mac_lomac));
832 if (single != NULL) {
833 error = mac_lomac_parse_element(&mac_lomac->ml_single, single);
834 if (error)
835 return (error);
836 mac_lomac->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
837 }
838
839 if (auxsingle != NULL) {
840 error = mac_lomac_parse_element(&mac_lomac->ml_auxsingle,
841 auxsingle);
842 if (error)
843 return (error);
844 mac_lomac->ml_flags |= MAC_LOMAC_FLAG_AUX;
845 }
846
847 if (rangelow != NULL) {
848 error = mac_lomac_parse_element(&mac_lomac->ml_rangelow,
849 rangelow);
850 if (error)
851 return (error);
852 error = mac_lomac_parse_element(&mac_lomac->ml_rangehigh,
853 rangehigh);
854 if (error)
855 return (error);
856 mac_lomac->ml_flags |= MAC_LOMAC_FLAG_RANGE;
857 }
858
859 error = mac_lomac_valid(mac_lomac);
860 if (error)
861 return (error);
862
863 return (0);
864}
865
866static int
867mac_lomac_internalize_label(struct label *label, char *element_name,
868 char *element_data, int *claimed)
869{
870 struct mac_lomac *mac_lomac, mac_lomac_temp;
871 int error;
872
873 if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0)
874 return (0);
875
876 (*claimed)++;
877
878 error = mac_lomac_parse(&mac_lomac_temp, element_data);
879 if (error)
880 return (error);
881
882 mac_lomac = SLOT(label);
883 *mac_lomac = mac_lomac_temp;
884
885 return (0);
886}
887
888static void
889mac_lomac_copy_label(struct label *src, struct label *dest)
890{
891
892 *SLOT(dest) = *SLOT(src);
893}
894
895/*
896 * Labeling event operations: file system objects, and things that look
897 * a lot like file system objects.
898 */
899static void
900mac_lomac_create_devfs_device(struct mount *mp, dev_t dev,
901 struct devfs_dirent *devfs_dirent, struct label *label)
902{
903 struct mac_lomac *mac_lomac;
904 int lomac_type;
905
906 mac_lomac = SLOT(label);
907 if (strcmp(dev->si_name, "null") == 0 ||
908 strcmp(dev->si_name, "zero") == 0 ||
909 strcmp(dev->si_name, "random") == 0 ||
910 strncmp(dev->si_name, "fd/", strlen("fd/")) == 0 ||
911 strncmp(dev->si_name, "ttyv", strlen("ttyv")) == 0)
912 lomac_type = MAC_LOMAC_TYPE_EQUAL;
913 else if (ptys_equal &&
914 (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
915 strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
916 lomac_type = MAC_LOMAC_TYPE_EQUAL;
917 else
918 lomac_type = MAC_LOMAC_TYPE_HIGH;
919 mac_lomac_set_single(mac_lomac, lomac_type, 0);
920}
921
922static void
923mac_lomac_create_devfs_directory(struct mount *mp, char *dirname,
924 int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label)
925{
926 struct mac_lomac *mac_lomac;
927
928 mac_lomac = SLOT(label);
929 mac_lomac_set_single(mac_lomac, MAC_LOMAC_TYPE_HIGH, 0);
930}
931
932static void
933mac_lomac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
934 struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
935 struct label *delabel)
936{
937 struct mac_lomac *source, *dest;
938
939 source = SLOT(cred->cr_label);
940 dest = SLOT(delabel);
941
942 mac_lomac_copy_single(source, dest);
943}
944
945static void
946mac_lomac_create_mount(struct ucred *cred, struct mount *mp,
947 struct label *mntlabel, struct label *fslabel)
948{
949 struct mac_lomac *source, *dest;
950
951 source = SLOT(cred->cr_label);
952 dest = SLOT(mntlabel);
953 mac_lomac_copy_single(source, dest);
954 dest = SLOT(fslabel);
955 mac_lomac_copy_single(source, dest);
956}
957
958static void
959mac_lomac_create_root_mount(struct ucred *cred, struct mount *mp,
960 struct label *mntlabel, struct label *fslabel)
961{
962 struct mac_lomac *mac_lomac;
963
964 /* Always mount root as high integrity. */
965 mac_lomac = SLOT(fslabel);
966 mac_lomac_set_single(mac_lomac, MAC_LOMAC_TYPE_HIGH, 0);
967 mac_lomac = SLOT(mntlabel);
968 mac_lomac_set_single(mac_lomac, MAC_LOMAC_TYPE_HIGH, 0);
969}
970
971static void
972mac_lomac_relabel_vnode(struct ucred *cred, struct vnode *vp,
973 struct label *vnodelabel, struct label *label)
974{
975 struct mac_lomac *source, *dest;
976
977 source = SLOT(label);
978 dest = SLOT(vnodelabel);
979
980 try_relabel(source, dest);
981}
982
983static void
984mac_lomac_update_devfsdirent(struct mount *mp,
985 struct devfs_dirent *devfs_dirent, struct label *direntlabel,
986 struct vnode *vp, struct label *vnodelabel)
987{
988 struct mac_lomac *source, *dest;
989
990 source = SLOT(vnodelabel);
991 dest = SLOT(direntlabel);
992
993 mac_lomac_copy(source, dest);
994}
995
996static void
997mac_lomac_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
998 struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
999 struct label *vlabel)
1000{
1001 struct mac_lomac *source, *dest;
1002
1003 source = SLOT(delabel);
1004 dest = SLOT(vlabel);
1005
1006 mac_lomac_copy_single(source, dest);
1007}
1008
1009static int
1010mac_lomac_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
1011 struct vnode *vp, struct label *vlabel)
1012{
1013 struct mac_lomac temp, *source, *dest;
1014 int buflen, error;
1015
1016 source = SLOT(fslabel);
1017 dest = SLOT(vlabel);
1018
1019 buflen = sizeof(temp);
1020 bzero(&temp, buflen);
1021
1022 error = vn_extattr_get(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
1023 MAC_LOMAC_EXTATTR_NAME, &buflen, (char *)&temp, curthread);
1024 if (error == ENOATTR || error == EOPNOTSUPP) {
1025 /* Fall back to the fslabel. */
1026 mac_lomac_copy_single(source, dest);
1027 return (0);
1028 } else if (error)
1029 return (error);
1030
1031 if (buflen != sizeof(temp)) {
1032 if (buflen != sizeof(temp) - sizeof(temp.ml_auxsingle)) {
1033 printf("mac_lomac_associate_vnode_extattr: bad size %d\n",
1034 buflen);
1035 return (EPERM);
1036 }
1037 bzero(&temp.ml_auxsingle, sizeof(temp.ml_auxsingle));
1038 buflen = sizeof(temp);
1039 (void)vn_extattr_set(vp, IO_NODELOCKED,
1040 MAC_LOMAC_EXTATTR_NAMESPACE, MAC_LOMAC_EXTATTR_NAME,
1041 buflen, (char *)&temp, curthread);
1042 }
1043 if (mac_lomac_valid(&temp) != 0) {
1044 printf("mac_lomac_associate_vnode_extattr: invalid\n");
1045 return (EPERM);
1046 }
1047 if ((temp.ml_flags & MAC_LOMAC_FLAGS_BOTH) != MAC_LOMAC_FLAG_SINGLE) {
1048 printf("mac_lomac_associate_vnode_extattr: not single\n");
1049 return (EPERM);
1050 }
1051
1052 mac_lomac_copy_single(&temp, dest);
1053 return (0);
1054}
1055
1056static void
1057mac_lomac_associate_vnode_singlelabel(struct mount *mp,
1058 struct label *fslabel, struct vnode *vp, struct label *vlabel)
1059{
1060 struct mac_lomac *source, *dest;
1061
1062 source = SLOT(fslabel);
1063 dest = SLOT(vlabel);
1064
1065 mac_lomac_copy_single(source, dest);
1066}
1067
1068static int
1069mac_lomac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1070 struct label *fslabel, struct vnode *dvp, struct label *dlabel,
1071 struct vnode *vp, struct label *vlabel, struct componentname *cnp)
1072{
1073 struct mac_lomac *source, *dest, *dir, temp;
1074 size_t buflen;
1075 int error;
1076
1077 buflen = sizeof(temp);
1078 bzero(&temp, buflen);
1079
1080 source = SLOT(cred->cr_label);
1081 dest = SLOT(vlabel);
1082 dir = SLOT(dlabel);
1083 if (dir->ml_flags & MAC_LOMAC_FLAG_AUX) {
1084 mac_lomac_copy_auxsingle(dir, &temp);
1085 mac_lomac_set_single(&temp, dir->ml_auxsingle.mle_type,
1086 dir->ml_auxsingle.mle_grade);
1087 } else {
1088 mac_lomac_copy_single(source, &temp);
1089 }
1090
1091 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
1092 MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
1093 if (error == 0)
1094 mac_lomac_copy(&temp, dest);
1095 return (error);
1096}
1097
1098static int
1099mac_lomac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1100 struct label *vlabel, struct label *intlabel)
1101{
1102 struct mac_lomac *source, temp;
1103 size_t buflen;
1104 int error;
1105
1106 buflen = sizeof(temp);
1107 bzero(&temp, buflen);
1108
1109 source = SLOT(intlabel);
1110 if ((source->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1111 return (0);
1112
1113 mac_lomac_copy_single(source, &temp);
1114 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
1115 MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
1116 return (error);
1117}
1118
1119/*
1120 * Labeling event operations: IPC object.
1121 */
1122static void
1123mac_lomac_create_inpcb_from_socket(struct socket *so, struct label *solabel,
1124 struct inpcb *inp, struct label *inplabel)
1125{
1126 struct mac_lomac *source, *dest;
1127
1128 source = SLOT(solabel);
1129 dest = SLOT(inplabel);
1130
1131 mac_lomac_copy_single(source, dest);
1132}
1133
1134static void
1135mac_lomac_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
1136 struct mbuf *m, struct label *mbuflabel)
1137{
1138 struct mac_lomac *source, *dest;
1139
1140 source = SLOT(socketlabel);
1141 dest = SLOT(mbuflabel);
1142
1143 mac_lomac_copy_single(source, dest);
1144}
1145
1146static void
1147mac_lomac_create_socket(struct ucred *cred, struct socket *socket,
1148 struct label *socketlabel)
1149{
1150 struct mac_lomac *source, *dest;
1151
1152 source = SLOT(cred->cr_label);
1153 dest = SLOT(socketlabel);
1154
1155 mac_lomac_copy_single(source, dest);
1156}
1157
1158static void
1159mac_lomac_create_pipe(struct ucred *cred, struct pipepair *pp,
1160 struct label *pipelabel)
1161{
1162 struct mac_lomac *source, *dest;
1163
1164 source = SLOT(cred->cr_label);
1165 dest = SLOT(pipelabel);
1166
1167 mac_lomac_copy_single(source, dest);
1168}
1169
1170static void
1171mac_lomac_create_socket_from_socket(struct socket *oldsocket,
1172 struct label *oldsocketlabel, struct socket *newsocket,
1173 struct label *newsocketlabel)
1174{
1175 struct mac_lomac *source, *dest;
1176
1177 source = SLOT(oldsocketlabel);
1178 dest = SLOT(newsocketlabel);
1179
1180 mac_lomac_copy_single(source, dest);
1181}
1182
1183static void
1184mac_lomac_relabel_socket(struct ucred *cred, struct socket *socket,
1185 struct label *socketlabel, struct label *newlabel)
1186{
1187 struct mac_lomac *source, *dest;
1188
1189 source = SLOT(newlabel);
1190 dest = SLOT(socketlabel);
1191
1192 try_relabel(source, dest);
1193}
1194
1195static void
1196mac_lomac_relabel_pipe(struct ucred *cred, struct pipepair *pp,
1197 struct label *pipelabel, struct label *newlabel)
1198{
1199 struct mac_lomac *source, *dest;
1200
1201 source = SLOT(newlabel);
1202 dest = SLOT(pipelabel);
1203
1204 try_relabel(source, dest);
1205}
1206
1207static void
1208mac_lomac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
1209 struct socket *socket, struct label *socketpeerlabel)
1210{
1211 struct mac_lomac *source, *dest;
1212
1213 source = SLOT(mbuflabel);
1214 dest = SLOT(socketpeerlabel);
1215
1216 mac_lomac_copy_single(source, dest);
1217}
1218
1219/*
1220 * Labeling event operations: network objects.
1221 */
1222static void
1223mac_lomac_set_socket_peer_from_socket(struct socket *oldsocket,
1224 struct label *oldsocketlabel, struct socket *newsocket,
1225 struct label *newsocketpeerlabel)
1226{
1227 struct mac_lomac *source, *dest;
1228
1229 source = SLOT(oldsocketlabel);
1230 dest = SLOT(newsocketpeerlabel);
1231
1232 mac_lomac_copy_single(source, dest);
1233}
1234
1235static void
1236mac_lomac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
1237 struct label *bpflabel)
1238{
1239 struct mac_lomac *source, *dest;
1240
1241 source = SLOT(cred->cr_label);
1242 dest = SLOT(bpflabel);
1243
1244 mac_lomac_copy_single(source, dest);
1245}
1246
1247static void
1248mac_lomac_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
1249{
1250 char tifname[IFNAMSIZ], *p, *q;
1251 char tiflist[sizeof(trusted_interfaces)];
1252 struct mac_lomac *dest;
1253 int len, grade;
1254
1255 dest = SLOT(ifnetlabel);
1256
1257 if (ifnet->if_type == IFT_LOOP) {
1258 grade = MAC_LOMAC_TYPE_EQUAL;
1259 goto set;
1260 }
1261
1262 if (trust_all_interfaces) {
1263 grade = MAC_LOMAC_TYPE_HIGH;
1264 goto set;
1265 }
1266
1267 grade = MAC_LOMAC_TYPE_LOW;
1268
1269 if (trusted_interfaces[0] == '\0' ||
1270 !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
1271 goto set;
1272
1273 bzero(tiflist, sizeof(tiflist));
1274 for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
1275 if(*p != ' ' && *p != '\t')
1276 *q = *p;
1277
1278 for (p = q = tiflist;; p++) {
1279 if (*p == ',' || *p == '\0') {
1280 len = p - q;
1281 if (len < IFNAMSIZ) {
1282 bzero(tifname, sizeof(tifname));
1283 bcopy(q, tifname, len);
1284 if (strcmp(tifname, ifnet->if_xname) == 0) {
1285 grade = MAC_LOMAC_TYPE_HIGH;
1286 break;
1287 }
1288 }
1289 else {
1290 *p = '\0';
1291 printf("MAC/LOMAC warning: interface name "
1292 "\"%s\" is too long (must be < %d)\n",
1293 q, IFNAMSIZ);
1294 }
1295 if (*p == '\0')
1296 break;
1297 q = p + 1;
1298 }
1299 }
1300set:
1301 mac_lomac_set_single(dest, grade, 0);
1302 mac_lomac_set_range(dest, grade, 0, grade, 0);
1303}
1304
1305static void
1306mac_lomac_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1307 struct ipq *ipq, struct label *ipqlabel)
1308{
1309 struct mac_lomac *source, *dest;
1310
1311 source = SLOT(fragmentlabel);
1312 dest = SLOT(ipqlabel);
1313
1314 mac_lomac_copy_single(source, dest);
1315}
1316
1317static void
1318mac_lomac_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1319 struct mbuf *datagram, struct label *datagramlabel)
1320{
1321 struct mac_lomac *source, *dest;
1322
1323 source = SLOT(ipqlabel);
1324 dest = SLOT(datagramlabel);
1325
1326 /* Just use the head, since we require them all to match. */
1327 mac_lomac_copy_single(source, dest);
1328}
1329
1330static void
1331mac_lomac_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1332 struct mbuf *fragment, struct label *fragmentlabel)
1333{
1334 struct mac_lomac *source, *dest;
1335
1336 source = SLOT(datagramlabel);
1337 dest = SLOT(fragmentlabel);
1338
1339 mac_lomac_copy_single(source, dest);
1340}
1341
1342static void
1343mac_lomac_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel,
1344 struct mbuf *m, struct label *mlabel)
1345{
1346 struct mac_lomac *source, *dest;
1347
1348 source = SLOT(inplabel);
1349 dest = SLOT(mlabel);
1350
1351 mac_lomac_copy_single(source, dest);
1352}
1353
1354static void
1355mac_lomac_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
1356 struct label *oldmbuflabel, struct mbuf *newmbuf,
1357 struct label *newmbuflabel)
1358{
1359 struct mac_lomac *source, *dest;
1360
1361 source = SLOT(oldmbuflabel);
1362 dest = SLOT(newmbuflabel);
1363
1364 /*
1365 * Because the source mbuf may not yet have been "created",
1366 * just initialized, we do a conditional copy. Since we don't
1367 * allow mbufs to have ranges, do a KASSERT to make sure that
1368 * doesn't happen.
1369 */
1370 KASSERT((source->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0,
1371 ("mac_lomac_create_mbuf_from_mbuf: source mbuf has range"));
1372 mac_lomac_copy(source, dest);
1373}
1374
1375static void
1376mac_lomac_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1377 struct mbuf *mbuf, struct label *mbuflabel)
1378{
1379 struct mac_lomac *dest;
1380
1381 dest = SLOT(mbuflabel);
1382
1383 mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1384}
1385
1386static void
1387mac_lomac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1388 struct mbuf *mbuf, struct label *mbuflabel)
1389{
1390 struct mac_lomac *source, *dest;
1391
1392 source = SLOT(bpflabel);
1393 dest = SLOT(mbuflabel);
1394
1395 mac_lomac_copy_single(source, dest);
1396}
1397
1398static void
1399mac_lomac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1400 struct mbuf *m, struct label *mbuflabel)
1401{
1402 struct mac_lomac *source, *dest;
1403
1404 source = SLOT(ifnetlabel);
1405 dest = SLOT(mbuflabel);
1406
1407 mac_lomac_copy_single(source, dest);
1408}
1409
1410static void
1411mac_lomac_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1412 struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1413 struct mbuf *newmbuf, struct label *newmbuflabel)
1414{
1415 struct mac_lomac *source, *dest;
1416
1417 source = SLOT(oldmbuflabel);
1418 dest = SLOT(newmbuflabel);
1419
1420 mac_lomac_copy_single(source, dest);
1421}
1422
1423static void
1424mac_lomac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1425 struct mbuf *newmbuf, struct label *newmbuflabel)
1426{
1427 struct mac_lomac *source, *dest;
1428
1429 source = SLOT(oldmbuflabel);
1430 dest = SLOT(newmbuflabel);
1431
1432 mac_lomac_copy_single(source, dest);
1433}
1434
1435static int
1436mac_lomac_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1437 struct ipq *ipq, struct label *ipqlabel)
1438{
1439 struct mac_lomac *a, *b;
1440
1441 a = SLOT(ipqlabel);
1442 b = SLOT(fragmentlabel);
1443
1444 return (mac_lomac_equal_single(a, b));
1445}
1446
1447static void
1448mac_lomac_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1449 struct label *ifnetlabel, struct label *newlabel)
1450{
1451 struct mac_lomac *source, *dest;
1452
1453 source = SLOT(newlabel);
1454 dest = SLOT(ifnetlabel);
1455
1456 try_relabel(source, dest);
1457}
1458
1459static void
1460mac_lomac_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1461 struct ipq *ipq, struct label *ipqlabel)
1462{
1463
1464 /* NOOP: we only accept matching labels, so no need to update */
1465}
1466
1467static void
1468mac_lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1469 struct inpcb *inp, struct label *inplabel)
1470{
1471 struct mac_lomac *source, *dest;
1472
1473 source = SLOT(solabel);
1474 dest = SLOT(inplabel);
1475
1476 mac_lomac_copy_single(source, dest);
1477}
1478
1479/*
1480 * Labeling event operations: processes.
1481 */
1482static void
1483mac_lomac_execve_transition(struct ucred *old, struct ucred *new,
1484 struct vnode *vp, struct label *vnodelabel,
1485 struct label *interpvnodelabel, struct image_params *imgp,
1486 struct label *execlabel)
1487{
1488 struct mac_lomac *source, *dest, *obj, *robj;
1489
1490 source = SLOT(old->cr_label);
1491 dest = SLOT(new->cr_label);
1492 obj = SLOT(vnodelabel);
1493 robj = interpvnodelabel != NULL ? SLOT(interpvnodelabel) : obj;
1494
1495 mac_lomac_copy(source, dest);
1496 /*
1497 * If there's an auxiliary label on the real object, respect it
1498 * and assume that this level should be assumed immediately if
1499 * a higher level is currently in place.
1500 */
1501 if (robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
1502 !mac_lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single)
1503 && mac_lomac_auxsingle_in_range(robj, dest))
1504 mac_lomac_set_single(dest, robj->ml_auxsingle.mle_type,
1505 robj->ml_auxsingle.mle_grade);
1506 /*
1507 * Restructuring to use the execve transitioning mechanism
1508 * instead of the normal demotion mechanism here would be
1509 * difficult, so just copy the label over and perform standard
1510 * demotion. This is also non-optimal because it will result
1511 * in the intermediate label "new" being created and immediately
1512 * recycled.
1513 */
1514 if (mac_lomac_enabled && revocation_enabled &&
1515 !mac_lomac_dominate_single(obj, source))
1516 (void)maybe_demote(source, obj, "executing", "file", vp);
1517}
1518
1519static int
1520mac_lomac_execve_will_transition(struct ucred *old, struct vnode *vp,
1521 struct label *vnodelabel, struct label *interpvnodelabel,
1522 struct image_params *imgp, struct label *execlabel)
1523{
1524 struct mac_lomac *subj, *obj, *robj;
1525
1526 if (!mac_lomac_enabled || !revocation_enabled)
1527 return (0);
1528
1529 subj = SLOT(old->cr_label);
1530 obj = SLOT(vnodelabel);
1531 robj = interpvnodelabel != NULL ? SLOT(interpvnodelabel) : obj;
1532
1533 return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
1534 !mac_lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single)
1535 && mac_lomac_auxsingle_in_range(robj, subj)) ||
1536 !mac_lomac_dominate_single(obj, subj));
1537}
1538
1539static void
1540mac_lomac_create_proc0(struct ucred *cred)
1541{
1542 struct mac_lomac *dest;
1543
1544 dest = SLOT(cred->cr_label);
1545
1546 mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1547 mac_lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH,
1548 0);
1549}
1550
1551static void
1552mac_lomac_create_proc1(struct ucred *cred)
1553{
1554 struct mac_lomac *dest;
1555
1556 dest = SLOT(cred->cr_label);
1557
1558 mac_lomac_set_single(dest, MAC_LOMAC_TYPE_HIGH, 0);
1559 mac_lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH,
1560 0);
1561}
1562
1563static void
1564mac_lomac_relabel_cred(struct ucred *cred, struct label *newlabel)
1565{
1566 struct mac_lomac *source, *dest;
1567
1568 source = SLOT(newlabel);
1569 dest = SLOT(cred->cr_label);
1570
1571 try_relabel(source, dest);
1572}
1573
1574/*
1575 * Access control checks.
1576 */
1577static int
1578mac_lomac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1579 struct ifnet *ifnet, struct label *ifnetlabel)
1580{
1581 struct mac_lomac *a, *b;
1582
1583 if (!mac_lomac_enabled)
1584 return (0);
1585
1586 a = SLOT(bpflabel);
1587 b = SLOT(ifnetlabel);
1588
1589 if (mac_lomac_equal_single(a, b))
1590 return (0);
1591 return (EACCES);
1592}
1593
1594static int
1595mac_lomac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1596{
1597 struct mac_lomac *subj, *new;
1598 int error;
1599
1600 subj = SLOT(cred->cr_label);
1601 new = SLOT(newlabel);
1602
1603 /*
1604 * If there is a LOMAC label update for the credential, it may
1605 * be an update of the single, range, or both.
1606 */
1607 error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1608 if (error)
1609 return (error);
1610
1611 /*
1612 * If the LOMAC label is to be changed, authorize as appropriate.
1613 */
1614 if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1615 /*
1616 * Fill in the missing parts from the previous label.
1617 */
1618 if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1619 mac_lomac_copy_single(subj, new);
1620 if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1621 mac_lomac_copy_range(subj, new);
1622
1623 /*
1624 * To change the LOMAC range on a credential, the new
1625 * range label must be in the current range.
1626 */
1627 if (!mac_lomac_range_in_range(new, subj))
1628 return (EPERM);
1629
1630 /*
1631 * To change the LOMAC single label on a credential, the
1632 * new single label must be in the new range. Implicitly
1633 * from the previous check, the new single is in the old
1634 * range.
1635 */
1636 if (!mac_lomac_single_in_range(new, new))
1637 return (EPERM);
1638
1639 /*
1640 * To have EQUAL in any component of the new credential
1641 * LOMAC label, the subject must already have EQUAL in
1642 * their label.
1643 */
1644 if (mac_lomac_contains_equal(new)) {
1645 error = mac_lomac_subject_privileged(subj);
1646 if (error)
1647 return (error);
1648 }
1649
1650 /*
1651 * XXXMAC: Additional consistency tests regarding the
1652 * single and range of the new label might be performed
1653 * here.
1654 */
1655 }
1656
1657 return (0);
1658}
1659
1660static int
1661mac_lomac_check_cred_visible(struct ucred *u1, struct ucred *u2)
1662{
1663 struct mac_lomac *subj, *obj;
1664
1665 if (!mac_lomac_enabled)
1666 return (0);
1667
1668 subj = SLOT(u1->cr_label);
1669 obj = SLOT(u2->cr_label);
1670
1671 /* XXX: range */
1672 if (!mac_lomac_dominate_single(obj, subj))
1673 return (ESRCH);
1674
1675 return (0);
1676}
1677
1678static int
1679mac_lomac_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1680 struct label *ifnetlabel, struct label *newlabel)
1681{
1682 struct mac_lomac *subj, *new;
1683 int error;
1684
1685 subj = SLOT(cred->cr_label);
1686 new = SLOT(newlabel);
1687
1688 /*
1689 * If there is a LOMAC label update for the interface, it may
1690 * be an update of the single, range, or both.
1691 */
1692 error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1693 if (error)
1694 return (error);
1695
1696 /*
1697 * Relabling network interfaces requires LOMAC privilege.
1698 */
1699 error = mac_lomac_subject_privileged(subj);
1700 if (error)
1701 return (error);
1702
1703 /*
1704 * If the LOMAC label is to be changed, authorize as appropriate.
1705 */
1706 if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1707 /*
1708 * Fill in the missing parts from the previous label.
1709 */
1710 if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1711 mac_lomac_copy_single(subj, new);
1712 if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1713 mac_lomac_copy_range(subj, new);
1714
1715 /*
1716 * Rely on the traditional superuser status for the LOMAC
1717 * interface relabel requirements. XXXMAC: This will go
1718 * away.
1719 */
1720 error = suser_cred(cred, 0);
1721 if (error)
1722 return (EPERM);
1723
1724 /*
1725 * XXXMAC: Additional consistency tests regarding the single
1726 * and the range of the new label might be performed here.
1727 */
1728 }
1729
1730 return (0);
1731}
1732
1733static int
1734mac_lomac_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1735 struct mbuf *m, struct label *mbuflabel)
1736{
1737 struct mac_lomac *p, *i;
1738
1739 if (!mac_lomac_enabled)
1740 return (0);
1741
1742 p = SLOT(mbuflabel);
1743 i = SLOT(ifnetlabel);
1744
1745 return (mac_lomac_single_in_range(p, i) ? 0 : EACCES);
1746}
1747
1748static int
1749mac_lomac_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel,
1750 struct mbuf *m, struct label *mlabel)
1751{
1752 struct mac_lomac *p, *i;
1753
1754 if (!mac_lomac_enabled)
1755 return (0);
1756
1757 p = SLOT(mlabel);
1758 i = SLOT(inplabel);
1759
1760 return (mac_lomac_equal_single(p, i) ? 0 : EACCES);
1761}
1762
1763static int
1764mac_lomac_check_kld_load(struct ucred *cred, struct vnode *vp,
1765 struct label *label)
1766{
1767 struct mac_lomac *subj, *obj;
1768
1769 if (!mac_lomac_enabled)
1770 return (0);
1771
1772 subj = SLOT(cred->cr_label);
1773 obj = SLOT(label);
1774
1775 if (mac_lomac_subject_privileged(subj))
1776 return (EPERM);
1777
1778 if (!mac_lomac_high_single(obj))
1779 return (EACCES);
1780
1781 return (0);
1782}
1783
1784static int
1785mac_lomac_check_kld_unload(struct ucred *cred)
1786{
1787 struct mac_lomac *subj;
1788
1789 if (!mac_lomac_enabled)
1790 return (0);
1791
1792 subj = SLOT(cred->cr_label);
1793
1794 if (mac_lomac_subject_privileged(subj))
1795 return (EPERM);
1796
1797 return (0);
1798}
1799
1800static int
1801mac_lomac_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
1802 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1803{
1804
1805 if(!mac_lomac_enabled)
1806 return (0);
1807
1808 /* XXX: This will be implemented soon... */
1809
1810 return (0);
1811}
1812
1813static int
1814mac_lomac_check_pipe_read(struct ucred *cred, struct pipepair *pp,
1815 struct label *pipelabel)
1816{
1817 struct mac_lomac *subj, *obj;
1818
1819 if (!mac_lomac_enabled)
1820 return (0);
1821
1822 subj = SLOT(cred->cr_label);
1823 obj = SLOT((pipelabel));
1824
1825 if (!mac_lomac_dominate_single(obj, subj))
1826 return (maybe_demote(subj, obj, "reading", "pipe", NULL));
1827
1828 return (0);
1829}
1830
1831static int
1832mac_lomac_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1833 struct label *pipelabel, struct label *newlabel)
1834{
1835 struct mac_lomac *subj, *obj, *new;
1836 int error;
1837
1838 new = SLOT(newlabel);
1839 subj = SLOT(cred->cr_label);
1840 obj = SLOT(pipelabel);
1841
1842 /*
1843 * If there is a LOMAC label update for a pipe, it must be a
1844 * single update.
1845 */
1846 error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1847 if (error)
1848 return (error);
1849
1850 /*
1851 * To perform a relabel of a pipe (LOMAC label or not), LOMAC must
1852 * authorize the relabel.
1853 */
1854 if (!mac_lomac_single_in_range(obj, subj))
1855 return (EPERM);
1856
1857 /*
1858 * If the LOMAC label is to be changed, authorize as appropriate.
1859 */
1860 if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1861 /*
1862 * To change the LOMAC label on a pipe, the new pipe label
1863 * must be in the subject range.
1864 */
1865 if (!mac_lomac_single_in_range(new, subj))
1866 return (EPERM);
1867
1868 /*
1869 * To change the LOMAC label on a pipe to be EQUAL, the
1870 * subject must have appropriate privilege.
1871 */
1872 if (mac_lomac_contains_equal(new)) {
1873 error = mac_lomac_subject_privileged(subj);
1874 if (error)
1875 return (error);
1876 }
1877 }
1878
1879 return (0);
1880}
1881
1882static int
1883mac_lomac_check_pipe_write(struct ucred *cred, struct pipepair *pp,
1884 struct label *pipelabel)
1885{
1886 struct mac_lomac *subj, *obj;
1887
1888 if (!mac_lomac_enabled)
1889 return (0);
1890
1891 subj = SLOT(cred->cr_label);
1892 obj = SLOT((pipelabel));
1893
1894 if (!mac_lomac_subject_dominate(subj, obj))
1895 return (EACCES);
1896
1897 return (0);
1898}
1899
1900static int
1901mac_lomac_check_proc_debug(struct ucred *cred, struct proc *proc)
1902{
1903 struct mac_lomac *subj, *obj;
1904
1905 if (!mac_lomac_enabled)
1906 return (0);
1907
1908 subj = SLOT(cred->cr_label);
1909 obj = SLOT(proc->p_ucred->cr_label);
1910
1911 /* XXX: range checks */
1912 if (!mac_lomac_dominate_single(obj, subj))
1913 return (ESRCH);
1914 if (!mac_lomac_subject_dominate(subj, obj))
1915 return (EACCES);
1916
1917 return (0);
1918}
1919
1920static int
1921mac_lomac_check_proc_sched(struct ucred *cred, struct proc *proc)
1922{
1923 struct mac_lomac *subj, *obj;
1924
1925 if (!mac_lomac_enabled)
1926 return (0);
1927
1928 subj = SLOT(cred->cr_label);
1929 obj = SLOT(proc->p_ucred->cr_label);
1930
1931 /* XXX: range checks */
1932 if (!mac_lomac_dominate_single(obj, subj))
1933 return (ESRCH);
1934 if (!mac_lomac_subject_dominate(subj, obj))
1935 return (EACCES);
1936
1937 return (0);
1938}
1939
1940static int
1941mac_lomac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1942{
1943 struct mac_lomac *subj, *obj;
1944
1945 if (!mac_lomac_enabled)
1946 return (0);
1947
1948 subj = SLOT(cred->cr_label);
1949 obj = SLOT(proc->p_ucred->cr_label);
1950
1951 /* XXX: range checks */
1952 if (!mac_lomac_dominate_single(obj, subj))
1953 return (ESRCH);
1954 if (!mac_lomac_subject_dominate(subj, obj))
1955 return (EACCES);
1956
1957 return (0);
1958}
1959
1960static int
1961mac_lomac_check_socket_deliver(struct socket *so, struct label *socketlabel,
1962 struct mbuf *m, struct label *mbuflabel)
1963{
1964 struct mac_lomac *p, *s;
1965
1966 if (!mac_lomac_enabled)
1967 return (0);
1968
1969 p = SLOT(mbuflabel);
1970 s = SLOT(socketlabel);
1971
1972 return (mac_lomac_equal_single(p, s) ? 0 : EACCES);
1973}
1974
1975static int
1976mac_lomac_check_socket_relabel(struct ucred *cred, struct socket *socket,
1977 struct label *socketlabel, struct label *newlabel)
1978{
1979 struct mac_lomac *subj, *obj, *new;
1980 int error;
1981
1982 new = SLOT(newlabel);
1983 subj = SLOT(cred->cr_label);
1984 obj = SLOT(socketlabel);
1985
1986 /*
1987 * If there is a LOMAC label update for the socket, it may be
1988 * an update of single.
1989 */
1990 error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1991 if (error)
1992 return (error);
1993
1994 /*
1995 * To relabel a socket, the old socket single must be in the subject
1996 * range.
1997 */
1998 if (!mac_lomac_single_in_range(obj, subj))
1999 return (EPERM);
2000
2001 /*
2002 * If the LOMAC label is to be changed, authorize as appropriate.
2003 */
2004 if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2005 /*
2006 * To relabel a socket, the new socket single must be in
2007 * the subject range.
2008 */
2009 if (!mac_lomac_single_in_range(new, subj))
2010 return (EPERM);
2011
2012 /*
2013 * To change the LOMAC label on the socket to contain EQUAL,
2014 * the subject must have appropriate privilege.
2015 */
2016 if (mac_lomac_contains_equal(new)) {
2017 error = mac_lomac_subject_privileged(subj);
2018 if (error)
2019 return (error);
2020 }
2021 }
2022
2023 return (0);
2024}
2025
2026static int
2027mac_lomac_check_socket_visible(struct ucred *cred, struct socket *socket,
2028 struct label *socketlabel)
2029{
2030 struct mac_lomac *subj, *obj;
2031
2032 if (!mac_lomac_enabled)
2033 return (0);
2034
2035 subj = SLOT(cred->cr_label);
2036 obj = SLOT(socketlabel);
2037
2038 if (!mac_lomac_dominate_single(obj, subj))
2039 return (ENOENT);
2040
2041 return (0);
2042}
2043
2044static int
2045mac_lomac_check_system_swapon(struct ucred *cred, struct vnode *vp,
2046 struct label *label)
2047{
2048 struct mac_lomac *subj, *obj;
2049
2050 if (!mac_lomac_enabled)
2051 return (0);
2052
2053 subj = SLOT(cred->cr_label);
2054 obj = SLOT(label);
2055
2056 if (mac_lomac_subject_privileged(subj))
2057 return (EPERM);
2058
2059 if (!mac_lomac_high_single(obj))
2060 return (EACCES);
2061
2062 return (0);
2063}
2064
2065static int
2066mac_lomac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2067 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2068{
2069 struct mac_lomac *subj;
2070
2071 if (!mac_lomac_enabled)
2072 return (0);
2073
2074 subj = SLOT(cred->cr_label);
2075
2076 /*
2077 * In general, treat sysctl variables as lomac/high, but also
2078 * require privilege to change them, since they are a
2079 * communications channel between grades. Exempt MIB
2080 * queries from this due to undocmented sysctl magic.
2081 * XXXMAC: This probably requires some more review.
2082 */
2083 if (new != NULL) {
2084 if (namelen > 0 && name[0] == 0)
2085 return (0);
2086
2087#ifdef notdef
2088 if (!mac_lomac_subject_dominate_high(subj))
2089 return (EACCES);
2090#endif
2091
2092 if (mac_lomac_subject_privileged(subj))
2093 return (EPERM);
2094 }
2095
2096 return (0);
2097}
2098
2099static int
2100mac_lomac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2101 struct label *dlabel, struct componentname *cnp, struct vattr *vap)
2102{
2103 struct mac_lomac *subj, *obj;
2104
2105 if (!mac_lomac_enabled)
2106 return (0);
2107
2108 subj = SLOT(cred->cr_label);
2109 obj = SLOT(dlabel);
2110
2111 if (!mac_lomac_subject_dominate(subj, obj))
2112 return (EACCES);
2113 if (obj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2114 !mac_lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle))
2115 return (EACCES);
2116
2117 return (0);
2118}
2119
2120static int
2121mac_lomac_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
2122 struct label *dlabel, struct vnode *vp, struct label *label,
2123 struct componentname *cnp)
2124{
2125 struct mac_lomac *subj, *obj;
2126
2127 if (!mac_lomac_enabled)
2128 return (0);
2129
2130 subj = SLOT(cred->cr_label);
2131 obj = SLOT(dlabel);
2132
2133 if (!mac_lomac_subject_dominate(subj, obj))
2134 return (EACCES);
2135
2136 obj = SLOT(label);
2137
2138 if (!mac_lomac_subject_dominate(subj, obj))
2139 return (EACCES);
2140
2141 return (0);
2142}
2143
2144static int
2145mac_lomac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2146 struct label *label, acl_type_t type)
2147{
2148 struct mac_lomac *subj, *obj;
2149
2150 if (!mac_lomac_enabled)
2151 return (0);
2152
2153 subj = SLOT(cred->cr_label);
2154 obj = SLOT(label);
2155
2156 if (!mac_lomac_subject_dominate(subj, obj))
2157 return (EACCES);
2158
2159 return (0);
2160}
2161
2162static int
2163mac_lomac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2164 struct label *dlabel, struct vnode *vp, struct label *label,
2165 struct componentname *cnp)
2166{
2167 struct mac_lomac *subj, *obj;
2168
2169 if (!mac_lomac_enabled)
2170 return (0);
2171
2172 subj = SLOT(cred->cr_label);
2173 obj = SLOT(dlabel);
2174
2175 if (!mac_lomac_subject_dominate(subj, obj))
2176 return (EACCES);
2177
2178 obj = SLOT(label);
2179
2180 if (!mac_lomac_subject_dominate(subj, obj))
2181 return (EACCES);
2182
2183 return (0);
2184}
2185
2186static int
2187mac_lomac_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2188 struct label *label, int prot)
2189{
2190 struct mac_lomac *subj, *obj;
2191
2192 /*
2193 * Rely on the use of open()-time protections to handle
2194 * non-revocation cases.
2195 */
2196 if (!mac_lomac_enabled)
2197 return (0);
2198
2199 subj = SLOT(cred->cr_label);
2200 obj = SLOT(label);
2201
2202 if (prot & VM_PROT_WRITE) {
2203 if (!mac_lomac_subject_dominate(subj, obj))
2204 return (EACCES);
2205 }
2206 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2207 if (!mac_lomac_dominate_single(obj, subj))
2208 return (maybe_demote(subj, obj, "mapping", "file", vp));
2209 }
2210
2211 return (0);
2212}
2213
2214static int
2215mac_lomac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp,
2216 struct label *label, int prot)
2217{
2218 struct mac_lomac *subj, *obj;
2219
2220 /*
2221 * Rely on the use of open()-time protections to handle
2222 * non-revocation cases.
2223 */
2224 if (!mac_lomac_enabled || !revocation_enabled)
2225 return (0);
2226
2227 subj = SLOT(cred->cr_label);
2228 obj = SLOT(label);
2229
2230 if (prot & VM_PROT_WRITE) {
2231 if (!mac_lomac_subject_dominate(subj, obj))
2232 return (EACCES);
2233 }
2234 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2235 if (!mac_lomac_dominate_single(obj, subj))
2236 return (EACCES);
2237 }
2238
2239 return (0);
2240}
2241
2242static void
2243mac_lomac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp,
2244 struct label *label, /* XXX vm_prot_t */ int *prot)
2245{
2246 struct mac_lomac *subj, *obj;
2247
2248 /*
2249 * Rely on the use of open()-time protections to handle
2250 * non-revocation cases.
2251 */
2252 if (!mac_lomac_enabled || !revocation_enabled)
2253 return;
2254
2255 subj = SLOT(cred->cr_label);
2256 obj = SLOT(label);
2257
2258 if (!mac_lomac_subject_dominate(subj, obj))
2259 *prot &= ~VM_PROT_WRITE;
2260}
2261
2262static int
2263mac_lomac_check_vnode_open(struct ucred *cred, struct vnode *vp,
2264 struct label *vnodelabel, int acc_mode)
2265{
2266 struct mac_lomac *subj, *obj;
2267
2268 if (!mac_lomac_enabled)
2269 return (0);
2270
2271 subj = SLOT(cred->cr_label);
2272 obj = SLOT(vnodelabel);
2273
2274 /* XXX privilege override for admin? */
2275 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2276 if (!mac_lomac_subject_dominate(subj, obj))
2277 return (EACCES);
2278 }
2279
2280 return (0);
2281}
2282
2283static int
2284mac_lomac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2285 struct vnode *vp, struct label *label)
2286{
2287 struct mac_lomac *subj, *obj;
2288
2289 if (!mac_lomac_enabled || !revocation_enabled)
2290 return (0);
2291
2292 subj = SLOT(active_cred->cr_label);
2293 obj = SLOT(label);
2294
2295 if (!mac_lomac_dominate_single(obj, subj))
2296 return (maybe_demote(subj, obj, "reading", "file", vp));
2297
2298 return (0);
2299}
2300
2301static int
2302mac_lomac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2303 struct label *vnodelabel, struct label *newlabel)
2304{
2305 struct mac_lomac *old, *new, *subj;
2306 int error;
2307
2308 old = SLOT(vnodelabel);
2309 new = SLOT(newlabel);
2310 subj = SLOT(cred->cr_label);
2311
2312 /*
2313 * If there is a LOMAC label update for the vnode, it must be a
2314 * single label, with an optional explicit auxiliary single.
2315 */
2316 error = lomac_atmostflags(new,
2317 MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX);
2318 if (error)
2319 return (error);
2320
2321 /*
2322 * To perform a relabel of the vnode (LOMAC label or not), LOMAC must
2323 * authorize the relabel.
2324 */
2325 if (!mac_lomac_single_in_range(old, subj))
2326 return (EPERM);
2327
2328 /*
2329 * If the LOMAC label is to be changed, authorize as appropriate.
2330 */
2331 if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2332 /*
2333 * To change the LOMAC label on a vnode, the new vnode label
2334 * must be in the subject range.
2335 */
2336 if (!mac_lomac_single_in_range(new, subj))
2337 return (EPERM);
2338
2339 /*
2340 * To change the LOMAC label on the vnode to be EQUAL,
2341 * the subject must have appropriate privilege.
2342 */
2343 if (mac_lomac_contains_equal(new)) {
2344 error = mac_lomac_subject_privileged(subj);
2345 if (error)
2346 return (error);
2347 }
2348 }
2349 if (new->ml_flags & MAC_LOMAC_FLAG_AUX) {
2350 /*
2351 * Fill in the missing parts from the previous label.
2352 */
2353 if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
2354 mac_lomac_copy_single(subj, new);
2355
2356 /*
2357 * To change the auxiliary LOMAC label on a vnode, the new
2358 * vnode label must be in the subject range.
2359 */
2360 if (!mac_lomac_auxsingle_in_range(new, subj))
2361 return (EPERM);
2362
2363 /*
2364 * To change the auxiliary LOMAC label on the vnode to be
2365 * EQUAL, the subject must have appropriate privilege.
2366 */
2367 if (mac_lomac_contains_equal(new)) {
2368 error = mac_lomac_subject_privileged(subj);
2369 if (error)
2370 return (error);
2371 }
2372 }
2373
2374 return (0);
2375}
2376
2377static int
2378mac_lomac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2379 struct label *dlabel, struct vnode *vp, struct label *label,
2380 struct componentname *cnp)
2381{
2382 struct mac_lomac *subj, *obj;
2383
2384 if (!mac_lomac_enabled)
2385 return (0);
2386
2387 subj = SLOT(cred->cr_label);
2388 obj = SLOT(dlabel);
2389
2390 if (!mac_lomac_subject_dominate(subj, obj))
2391 return (EACCES);
2392
2393 obj = SLOT(label);
2394
2395 if (!mac_lomac_subject_dominate(subj, obj))
2396 return (EACCES);
2397
2398 return (0);
2399}
2400
2401static int
2402mac_lomac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2403 struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2404 struct componentname *cnp)
2405{
2406 struct mac_lomac *subj, *obj;
2407
2408 if (!mac_lomac_enabled)
2409 return (0);
2410
2411 subj = SLOT(cred->cr_label);
2412 obj = SLOT(dlabel);
2413
2414 if (!mac_lomac_subject_dominate(subj, obj))
2415 return (EACCES);
2416
2417 if (vp != NULL) {
2418 obj = SLOT(label);
2419
2420 if (!mac_lomac_subject_dominate(subj, obj))
2421 return (EACCES);
2422 }
2423
2424 return (0);
2425}
2426
2427static int
2428mac_lomac_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2429 struct label *label)
2430{
2431 struct mac_lomac *subj, *obj;
2432
2433 if (!mac_lomac_enabled)
2434 return (0);
2435
2436 subj = SLOT(cred->cr_label);
2437 obj = SLOT(label);
2438
2439 if (!mac_lomac_subject_dominate(subj, obj))
2440 return (EACCES);
2441
2442 return (0);
2443}
2444
2445static int
2446mac_lomac_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2447 struct label *label, acl_type_t type, struct acl *acl)
2448{
2449 struct mac_lomac *subj, *obj;
2450
2451 if (!mac_lomac_enabled)
2452 return (0);
2453
2454 subj = SLOT(cred->cr_label);
2455 obj = SLOT(label);
2456
2457 if (!mac_lomac_subject_dominate(subj, obj))
2458 return (EACCES);
2459
2460 return (0);
2461}
2462
2463static int
2464mac_lomac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2465 struct label *vnodelabel, int attrnamespace, const char *name,
2466 struct uio *uio)
2467{
2468 struct mac_lomac *subj, *obj;
2469
2470 if (!mac_lomac_enabled)
2471 return (0);
2472
2473 subj = SLOT(cred->cr_label);
2474 obj = SLOT(vnodelabel);
2475
2476 if (!mac_lomac_subject_dominate(subj, obj))
2477 return (EACCES);
2478
2479 /* XXX: protect the MAC EA in a special way? */
2480
2481 return (0);
2482}
2483
2484static int
2485mac_lomac_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2486 struct label *vnodelabel, u_long flags)
2487{
2488 struct mac_lomac *subj, *obj;
2489
2490 if (!mac_lomac_enabled)
2491 return (0);
2492
2493 subj = SLOT(cred->cr_label);
2494 obj = SLOT(vnodelabel);
2495
2496 if (!mac_lomac_subject_dominate(subj, obj))
2497 return (EACCES);
2498
2499 return (0);
2500}
2501
2502static int
2503mac_lomac_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2504 struct label *vnodelabel, mode_t mode)
2505{
2506 struct mac_lomac *subj, *obj;
2507
2508 if (!mac_lomac_enabled)
2509 return (0);
2510
2511 subj = SLOT(cred->cr_label);
2512 obj = SLOT(vnodelabel);
2513
2514 if (!mac_lomac_subject_dominate(subj, obj))
2515 return (EACCES);
2516
2517 return (0);
2518}
2519
2520static int
2521mac_lomac_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2522 struct label *vnodelabel, uid_t uid, gid_t gid)
2523{
2524 struct mac_lomac *subj, *obj;
2525
2526 if (!mac_lomac_enabled)
2527 return (0);
2528
2529 subj = SLOT(cred->cr_label);
2530 obj = SLOT(vnodelabel);
2531
2532 if (!mac_lomac_subject_dominate(subj, obj))
2533 return (EACCES);
2534
2535 return (0);
2536}
2537
2538static int
2539mac_lomac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2540 struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2541{
2542 struct mac_lomac *subj, *obj;
2543
2544 if (!mac_lomac_enabled)
2545 return (0);
2546
2547 subj = SLOT(cred->cr_label);
2548 obj = SLOT(vnodelabel);
2549
2550 if (!mac_lomac_subject_dominate(subj, obj))
2551 return (EACCES);
2552
2553 return (0);
2554}
2555
2556static int
2557mac_lomac_check_vnode_write(struct ucred *active_cred,
2558 struct ucred *file_cred, struct vnode *vp, struct label *label)
2559{
2560 struct mac_lomac *subj, *obj;
2561
2562 if (!mac_lomac_enabled || !revocation_enabled)
2563 return (0);
2564
2565 subj = SLOT(active_cred->cr_label);
2566 obj = SLOT(label);
2567
2568 if (!mac_lomac_subject_dominate(subj, obj))
2569 return (EACCES);
2570
2571 return (0);
2572}
2573
2574static void
2575mac_lomac_thread_userret(struct thread *td)
2576{
2577 struct proc *p = td->td_proc;
2578 struct mac_lomac_proc *subj = PSLOT(p->p_label);
2579 struct ucred *newcred, *oldcred;
2580 int dodrop;
2581
2582 mtx_lock(&subj->mtx);
2583 if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
2584 dodrop = 0;
2585 mtx_unlock(&subj->mtx);
2586 newcred = crget();
2587 /*
2588 * Prevent a lock order reversal in
2589 * mac_cred_mmapped_drop_perms; ideally, the other
2590 * user of subj->mtx wouldn't be holding Giant.
2591 */
2592 mtx_lock(&Giant);
2593 PROC_LOCK(p);
2594 mtx_lock(&subj->mtx);
2595 /*
2596 * Check if we lost the race while allocating the cred.
2597 */
2598 if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) {
2599 crfree(newcred);
2600 goto out;
2601 }
2602 oldcred = p->p_ucred;
2603 crcopy(newcred, oldcred);
2604 crhold(newcred);
2605 mac_lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label));
2606 p->p_ucred = newcred;
2607 crfree(oldcred);
2608 dodrop = 1;
2609 out:
2610 mtx_unlock(&subj->mtx);
2611 PROC_UNLOCK(p);
2612 if (dodrop)
2613 mac_cred_mmapped_drop_perms(curthread, newcred);
2614 mtx_unlock(&Giant);
2615 } else {
2616 mtx_unlock(&subj->mtx);
2617 }
2618}
2619
2620static struct mac_policy_ops mac_lomac_ops =
2621{
2622 .mpo_init = mac_lomac_init,
2623 .mpo_init_bpfdesc_label = mac_lomac_init_label,
2624 .mpo_init_cred_label = mac_lomac_init_label,
2625 .mpo_init_devfsdirent_label = mac_lomac_init_label,
2626 .mpo_init_ifnet_label = mac_lomac_init_label,
2627 .mpo_init_inpcb_label = mac_lomac_init_label_waitcheck,
2628 .mpo_init_ipq_label = mac_lomac_init_label_waitcheck,
2629 .mpo_init_mbuf_label = mac_lomac_init_label_waitcheck,
2630 .mpo_init_mount_label = mac_lomac_init_label,
2631 .mpo_init_mount_fs_label = mac_lomac_init_label,
2632 .mpo_init_pipe_label = mac_lomac_init_label,
2633 .mpo_init_proc_label = mac_lomac_init_proc_label,
2634 .mpo_init_socket_label = mac_lomac_init_label_waitcheck,
2635 .mpo_init_socket_peer_label = mac_lomac_init_label_waitcheck,
2636 .mpo_init_vnode_label = mac_lomac_init_label,
2637 .mpo_destroy_bpfdesc_label = mac_lomac_destroy_label,
2638 .mpo_destroy_cred_label = mac_lomac_destroy_label,
2639 .mpo_destroy_devfsdirent_label = mac_lomac_destroy_label,
2640 .mpo_destroy_ifnet_label = mac_lomac_destroy_label,
2641 .mpo_destroy_inpcb_label = mac_lomac_destroy_label,
2642 .mpo_destroy_ipq_label = mac_lomac_destroy_label,
2643 .mpo_destroy_mbuf_label = mac_lomac_destroy_label,
2644 .mpo_destroy_mount_label = mac_lomac_destroy_label,
2645 .mpo_destroy_mount_fs_label = mac_lomac_destroy_label,
2646 .mpo_destroy_pipe_label = mac_lomac_destroy_label,
2647 .mpo_destroy_proc_label = mac_lomac_destroy_proc_label,
2648 .mpo_destroy_socket_label = mac_lomac_destroy_label,
2649 .mpo_destroy_socket_peer_label = mac_lomac_destroy_label,
2650 .mpo_destroy_vnode_label = mac_lomac_destroy_label,
2651 .mpo_copy_cred_label = mac_lomac_copy_label,
2652 .mpo_copy_mbuf_label = mac_lomac_copy_label,
2653 .mpo_copy_pipe_label = mac_lomac_copy_label,
2654 .mpo_copy_socket_label = mac_lomac_copy_label,
2655 .mpo_copy_vnode_label = mac_lomac_copy_label,
2656 .mpo_externalize_cred_label = mac_lomac_externalize_label,
2657 .mpo_externalize_ifnet_label = mac_lomac_externalize_label,
2658 .mpo_externalize_pipe_label = mac_lomac_externalize_label,
2659 .mpo_externalize_socket_label = mac_lomac_externalize_label,
2660 .mpo_externalize_socket_peer_label = mac_lomac_externalize_label,
2661 .mpo_externalize_vnode_label = mac_lomac_externalize_label,
2662 .mpo_internalize_cred_label = mac_lomac_internalize_label,
2663 .mpo_internalize_ifnet_label = mac_lomac_internalize_label,
2664 .mpo_internalize_pipe_label = mac_lomac_internalize_label,
2665 .mpo_internalize_socket_label = mac_lomac_internalize_label,
2666 .mpo_internalize_vnode_label = mac_lomac_internalize_label,
2667 .mpo_create_devfs_device = mac_lomac_create_devfs_device,
2668 .mpo_create_devfs_directory = mac_lomac_create_devfs_directory,
2669 .mpo_create_devfs_symlink = mac_lomac_create_devfs_symlink,
2670 .mpo_create_mount = mac_lomac_create_mount,
2671 .mpo_create_root_mount = mac_lomac_create_root_mount,
2672 .mpo_relabel_vnode = mac_lomac_relabel_vnode,
2673 .mpo_update_devfsdirent = mac_lomac_update_devfsdirent,
2674 .mpo_associate_vnode_devfs = mac_lomac_associate_vnode_devfs,
2675 .mpo_associate_vnode_extattr = mac_lomac_associate_vnode_extattr,
2676 .mpo_associate_vnode_singlelabel =
2677 mac_lomac_associate_vnode_singlelabel,
2678 .mpo_create_vnode_extattr = mac_lomac_create_vnode_extattr,
2679 .mpo_setlabel_vnode_extattr = mac_lomac_setlabel_vnode_extattr,
2680 .mpo_create_mbuf_from_socket = mac_lomac_create_mbuf_from_socket,
2681 .mpo_create_pipe = mac_lomac_create_pipe,
2682 .mpo_create_socket = mac_lomac_create_socket,
2683 .mpo_create_socket_from_socket = mac_lomac_create_socket_from_socket,
2684 .mpo_relabel_pipe = mac_lomac_relabel_pipe,
2685 .mpo_relabel_socket = mac_lomac_relabel_socket,
2686 .mpo_set_socket_peer_from_mbuf = mac_lomac_set_socket_peer_from_mbuf,
2687 .mpo_set_socket_peer_from_socket =
2688 mac_lomac_set_socket_peer_from_socket,
2689 .mpo_create_bpfdesc = mac_lomac_create_bpfdesc,
2690 .mpo_create_datagram_from_ipq = mac_lomac_create_datagram_from_ipq,
2691 .mpo_create_fragment = mac_lomac_create_fragment,
2692 .mpo_create_ifnet = mac_lomac_create_ifnet,
2693 .mpo_create_inpcb_from_socket = mac_lomac_create_inpcb_from_socket,
2694 .mpo_create_ipq = mac_lomac_create_ipq,
2695 .mpo_create_mbuf_from_inpcb = mac_lomac_create_mbuf_from_inpcb,
2696 .mpo_create_mbuf_from_mbuf = mac_lomac_create_mbuf_from_mbuf,
2697 .mpo_create_mbuf_linklayer = mac_lomac_create_mbuf_linklayer,
2698 .mpo_create_mbuf_from_bpfdesc = mac_lomac_create_mbuf_from_bpfdesc,
2699 .mpo_create_mbuf_from_ifnet = mac_lomac_create_mbuf_from_ifnet,
2700 .mpo_create_mbuf_multicast_encap =
2701 mac_lomac_create_mbuf_multicast_encap,
2702 .mpo_create_mbuf_netlayer = mac_lomac_create_mbuf_netlayer,
2703 .mpo_fragment_match = mac_lomac_fragment_match,
2704 .mpo_relabel_ifnet = mac_lomac_relabel_ifnet,
2705 .mpo_update_ipq = mac_lomac_update_ipq,
2706 .mpo_inpcb_sosetlabel = mac_lomac_inpcb_sosetlabel,
2707 .mpo_execve_transition = mac_lomac_execve_transition,
2708 .mpo_execve_will_transition = mac_lomac_execve_will_transition,
2709 .mpo_create_proc0 = mac_lomac_create_proc0,
2710 .mpo_create_proc1 = mac_lomac_create_proc1,
2711 .mpo_relabel_cred = mac_lomac_relabel_cred,
2712 .mpo_check_bpfdesc_receive = mac_lomac_check_bpfdesc_receive,
2713 .mpo_check_cred_relabel = mac_lomac_check_cred_relabel,
2714 .mpo_check_cred_visible = mac_lomac_check_cred_visible,
2715 .mpo_check_ifnet_relabel = mac_lomac_check_ifnet_relabel,
2716 .mpo_check_ifnet_transmit = mac_lomac_check_ifnet_transmit,
2717 .mpo_check_inpcb_deliver = mac_lomac_check_inpcb_deliver,
2718 .mpo_check_kld_load = mac_lomac_check_kld_load,
2719 .mpo_check_kld_unload = mac_lomac_check_kld_unload,
2720 .mpo_check_pipe_ioctl = mac_lomac_check_pipe_ioctl,
2721 .mpo_check_pipe_read = mac_lomac_check_pipe_read,
2722 .mpo_check_pipe_relabel = mac_lomac_check_pipe_relabel,
2723 .mpo_check_pipe_write = mac_lomac_check_pipe_write,
2724 .mpo_check_proc_debug = mac_lomac_check_proc_debug,
2725 .mpo_check_proc_sched = mac_lomac_check_proc_sched,
2726 .mpo_check_proc_signal = mac_lomac_check_proc_signal,
2727 .mpo_check_socket_deliver = mac_lomac_check_socket_deliver,
2728 .mpo_check_socket_relabel = mac_lomac_check_socket_relabel,
2729 .mpo_check_socket_visible = mac_lomac_check_socket_visible,
2730 .mpo_check_system_swapon = mac_lomac_check_system_swapon,
2731 .mpo_check_system_sysctl = mac_lomac_check_system_sysctl,
2732 .mpo_check_vnode_access = mac_lomac_check_vnode_open,
2733 .mpo_check_vnode_create = mac_lomac_check_vnode_create,
2734 .mpo_check_vnode_delete = mac_lomac_check_vnode_delete,
2735 .mpo_check_vnode_deleteacl = mac_lomac_check_vnode_deleteacl,
2736 .mpo_check_vnode_link = mac_lomac_check_vnode_link,
2737 .mpo_check_vnode_mmap = mac_lomac_check_vnode_mmap,
2738 .mpo_check_vnode_mmap_downgrade = mac_lomac_check_vnode_mmap_downgrade,
2739 .mpo_check_vnode_mprotect = mac_lomac_check_vnode_mprotect,
2740 .mpo_check_vnode_open = mac_lomac_check_vnode_open,
2741 .mpo_check_vnode_read = mac_lomac_check_vnode_read,
2742 .mpo_check_vnode_relabel = mac_lomac_check_vnode_relabel,
2743 .mpo_check_vnode_rename_from = mac_lomac_check_vnode_rename_from,
2744 .mpo_check_vnode_rename_to = mac_lomac_check_vnode_rename_to,
2745 .mpo_check_vnode_revoke = mac_lomac_check_vnode_revoke,
2746 .mpo_check_vnode_setacl = mac_lomac_check_vnode_setacl,
2747 .mpo_check_vnode_setextattr = mac_lomac_check_vnode_setextattr,
2748 .mpo_check_vnode_setflags = mac_lomac_check_vnode_setflags,
2749 .mpo_check_vnode_setmode = mac_lomac_check_vnode_setmode,
2750 .mpo_check_vnode_setowner = mac_lomac_check_vnode_setowner,
2751 .mpo_check_vnode_setutimes = mac_lomac_check_vnode_setutimes,
2752 .mpo_check_vnode_write = mac_lomac_check_vnode_write,
2753 .mpo_thread_userret = mac_lomac_thread_userret,
2754};
2755
2756MAC_POLICY_SET(&mac_lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC",
2757 MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS,
2758 &mac_lomac_slot);
2 * Copyright (c) 1999-2002 Robert N. M. Watson
3 * Copyright (c) 2001-2003 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 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * $FreeBSD: head/sys/security/mac_lomac/mac_lomac.c 126097 2004-02-22 00:33:12Z rwatson $
35 */
36
37/*
38 * Developed by the TrustedBSD Project.
39 * Low-watermark floating label mandatory integrity policy.
40 */
41
42#include <sys/types.h>
43#include <sys/param.h>
44#include <sys/acl.h>
45#include <sys/conf.h>
46#include <sys/extattr.h>
47#include <sys/kernel.h>
48#include <sys/mac.h>
49#include <sys/malloc.h>
50#include <sys/mount.h>
51#include <sys/proc.h>
52#include <sys/sbuf.h>
53#include <sys/systm.h>
54#include <sys/sysproto.h>
55#include <sys/sysent.h>
56#include <sys/systm.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#include <sys/syslog.h>
64
65#include <fs/devfs/devfs.h>
66
67#include <net/bpfdesc.h>
68#include <net/if.h>
69#include <net/if_types.h>
70#include <net/if_var.h>
71
72#include <netinet/in.h>
73#include <netinet/in_pcb.h>
74#include <netinet/ip_var.h>
75
76#include <vm/vm.h>
77
78#include <sys/mac_policy.h>
79
80#include <security/mac_lomac/mac_lomac.h>
81
82struct mac_lomac_proc {
83 struct mac_lomac mac_lomac;
84 struct mtx mtx;
85};
86
87SYSCTL_DECL(_security_mac);
88
89SYSCTL_NODE(_security_mac, OID_AUTO, lomac, CTLFLAG_RW, 0,
90 "TrustedBSD mac_lomac policy controls");
91
92static int mac_lomac_label_size = sizeof(struct mac_lomac);
93SYSCTL_INT(_security_mac_lomac, OID_AUTO, label_size, CTLFLAG_RD,
94 &mac_lomac_label_size, 0, "Size of struct mac_lomac");
95
96static int mac_lomac_enabled = 1;
97SYSCTL_INT(_security_mac_lomac, OID_AUTO, enabled, CTLFLAG_RW,
98 &mac_lomac_enabled, 0, "Enforce MAC/LOMAC policy");
99TUNABLE_INT("security.mac.lomac.enabled", &mac_lomac_enabled);
100
101static int destroyed_not_inited;
102SYSCTL_INT(_security_mac_lomac, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
103 &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
104
105static int trust_all_interfaces = 0;
106SYSCTL_INT(_security_mac_lomac, OID_AUTO, trust_all_interfaces, CTLFLAG_RD,
107 &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/LOMAC");
108TUNABLE_INT("security.mac.lomac.trust_all_interfaces", &trust_all_interfaces);
109
110static char trusted_interfaces[128];
111SYSCTL_STRING(_security_mac_lomac, OID_AUTO, trusted_interfaces, CTLFLAG_RD,
112 trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/LOMAC");
113TUNABLE_STR("security.mac.lomac.trusted_interfaces", trusted_interfaces,
114 sizeof(trusted_interfaces));
115
116static int ptys_equal = 0;
117SYSCTL_INT(_security_mac_lomac, OID_AUTO, ptys_equal, CTLFLAG_RW,
118 &ptys_equal, 0, "Label pty devices as lomac/equal on create");
119TUNABLE_INT("security.mac.lomac.ptys_equal", &ptys_equal);
120
121static int revocation_enabled = 1;
122SYSCTL_INT(_security_mac_lomac, OID_AUTO, revocation_enabled, CTLFLAG_RW,
123 &revocation_enabled, 0, "Revoke access to objects on relabel");
124TUNABLE_INT("security.mac.lomac.revocation_enabled", &revocation_enabled);
125
126static int mac_lomac_slot;
127#define SLOT(l) ((struct mac_lomac *)LABEL_TO_SLOT((l), mac_lomac_slot).l_ptr)
128#define PSLOT(l) ((struct mac_lomac_proc *) \
129 LABEL_TO_SLOT((l), mac_lomac_slot).l_ptr)
130
131MALLOC_DEFINE(M_MACLOMAC, "lomac label", "MAC/LOMAC labels");
132
133static struct mac_lomac *
134lomac_alloc(int flag)
135{
136 struct mac_lomac *mac_lomac;
137
138 mac_lomac = malloc(sizeof(struct mac_lomac), M_MACLOMAC, M_ZERO | flag);
139
140 return (mac_lomac);
141}
142
143static void
144lomac_free(struct mac_lomac *mac_lomac)
145{
146
147 if (mac_lomac != NULL)
148 free(mac_lomac, M_MACLOMAC);
149 else
150 atomic_add_int(&destroyed_not_inited, 1);
151}
152
153static int
154lomac_atmostflags(struct mac_lomac *mac_lomac, int flags)
155{
156
157 if ((mac_lomac->ml_flags & flags) != mac_lomac->ml_flags)
158 return (EINVAL);
159 return (0);
160}
161
162static int
163mac_lomac_dominate_element(struct mac_lomac_element *a,
164 struct mac_lomac_element *b)
165{
166
167 switch (a->mle_type) {
168 case MAC_LOMAC_TYPE_EQUAL:
169 case MAC_LOMAC_TYPE_HIGH:
170 return (1);
171
172 case MAC_LOMAC_TYPE_LOW:
173 switch (b->mle_type) {
174 case MAC_LOMAC_TYPE_GRADE:
175 case MAC_LOMAC_TYPE_HIGH:
176 return (0);
177
178 case MAC_LOMAC_TYPE_EQUAL:
179 case MAC_LOMAC_TYPE_LOW:
180 return (1);
181
182 default:
183 panic("mac_lomac_dominate_element: b->mle_type invalid");
184 }
185
186 case MAC_LOMAC_TYPE_GRADE:
187 switch (b->mle_type) {
188 case MAC_LOMAC_TYPE_EQUAL:
189 case MAC_LOMAC_TYPE_LOW:
190 return (1);
191
192 case MAC_LOMAC_TYPE_HIGH:
193 return (0);
194
195 case MAC_LOMAC_TYPE_GRADE:
196 return (a->mle_grade >= b->mle_grade);
197
198 default:
199 panic("mac_lomac_dominate_element: b->mle_type invalid");
200 }
201
202 default:
203 panic("mac_lomac_dominate_element: a->mle_type invalid");
204 }
205}
206
207static int
208mac_lomac_range_in_range(struct mac_lomac *rangea, struct mac_lomac *rangeb)
209{
210
211 return (mac_lomac_dominate_element(&rangeb->ml_rangehigh,
212 &rangea->ml_rangehigh) &&
213 mac_lomac_dominate_element(&rangea->ml_rangelow,
214 &rangeb->ml_rangelow));
215}
216
217static int
218mac_lomac_single_in_range(struct mac_lomac *single, struct mac_lomac *range)
219{
220
221 KASSERT((single->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
222 ("mac_lomac_single_in_range: a not single"));
223 KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
224 ("mac_lomac_single_in_range: b not range"));
225
226 return (mac_lomac_dominate_element(&range->ml_rangehigh,
227 &single->ml_single) &&
228 mac_lomac_dominate_element(&single->ml_single,
229 &range->ml_rangelow));
230}
231
232static int
233mac_lomac_auxsingle_in_range(struct mac_lomac *single, struct mac_lomac *range)
234{
235
236 KASSERT((single->ml_flags & MAC_LOMAC_FLAG_AUX) != 0,
237 ("mac_lomac_single_in_range: a not auxsingle"));
238 KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
239 ("mac_lomac_single_in_range: b not range"));
240
241 return (mac_lomac_dominate_element(&range->ml_rangehigh,
242 &single->ml_auxsingle) &&
243 mac_lomac_dominate_element(&single->ml_auxsingle,
244 &range->ml_rangelow));
245}
246
247static int
248mac_lomac_dominate_single(struct mac_lomac *a, struct mac_lomac *b)
249{
250 KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
251 ("mac_lomac_dominate_single: a not single"));
252 KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
253 ("mac_lomac_dominate_single: b not single"));
254
255 return (mac_lomac_dominate_element(&a->ml_single, &b->ml_single));
256}
257
258static int
259mac_lomac_subject_dominate(struct mac_lomac *a, struct mac_lomac *b)
260{
261 KASSERT((~a->ml_flags &
262 (MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_RANGE)) == 0,
263 ("mac_lomac_dominate_single: a not subject"));
264 KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
265 ("mac_lomac_dominate_single: b not single"));
266
267 return (mac_lomac_dominate_element(&a->ml_rangehigh,
268 &b->ml_single));
269}
270
271static int
272mac_lomac_equal_element(struct mac_lomac_element *a, struct mac_lomac_element *b)
273{
274
275 if (a->mle_type == MAC_LOMAC_TYPE_EQUAL ||
276 b->mle_type == MAC_LOMAC_TYPE_EQUAL)
277 return (1);
278
279 return (a->mle_type == b->mle_type && a->mle_grade == b->mle_grade);
280}
281
282static int
283mac_lomac_equal_single(struct mac_lomac *a, struct mac_lomac *b)
284{
285
286 KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
287 ("mac_lomac_equal_single: a not single"));
288 KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
289 ("mac_lomac_equal_single: b not single"));
290
291 return (mac_lomac_equal_element(&a->ml_single, &b->ml_single));
292}
293
294static int
295mac_lomac_contains_equal(struct mac_lomac *mac_lomac)
296{
297
298 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE)
299 if (mac_lomac->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL)
300 return (1);
301 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_AUX)
302 if (mac_lomac->ml_auxsingle.mle_type == MAC_LOMAC_TYPE_EQUAL)
303 return (1);
304
305 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_RANGE) {
306 if (mac_lomac->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL)
307 return (1);
308 if (mac_lomac->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL)
309 return (1);
310 }
311
312 return (0);
313}
314
315static int
316mac_lomac_subject_privileged(struct mac_lomac *mac_lomac)
317{
318
319 KASSERT((mac_lomac->ml_flags & MAC_LOMAC_FLAGS_BOTH) ==
320 MAC_LOMAC_FLAGS_BOTH,
321 ("mac_lomac_subject_privileged: subject doesn't have both labels"));
322
323 /* If the single is EQUAL, it's ok. */
324 if (mac_lomac->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL)
325 return (0);
326
327 /* If either range endpoint is EQUAL, it's ok. */
328 if (mac_lomac->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL ||
329 mac_lomac->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL)
330 return (0);
331
332 /* If the range is low-high, it's ok. */
333 if (mac_lomac->ml_rangelow.mle_type == MAC_LOMAC_TYPE_LOW &&
334 mac_lomac->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_HIGH)
335 return (0);
336
337 /* It's not ok. */
338 return (EPERM);
339}
340
341static int
342mac_lomac_high_single(struct mac_lomac *mac_lomac)
343{
344
345 KASSERT((mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
346 ("mac_lomac_high_single: mac_lomac not single"));
347
348 return (mac_lomac->ml_single.mle_type == MAC_LOMAC_TYPE_HIGH);
349}
350
351static int
352mac_lomac_valid(struct mac_lomac *mac_lomac)
353{
354
355 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
356 switch (mac_lomac->ml_single.mle_type) {
357 case MAC_LOMAC_TYPE_GRADE:
358 case MAC_LOMAC_TYPE_EQUAL:
359 case MAC_LOMAC_TYPE_HIGH:
360 case MAC_LOMAC_TYPE_LOW:
361 break;
362
363 default:
364 return (EINVAL);
365 }
366 } else {
367 if (mac_lomac->ml_single.mle_type != MAC_LOMAC_TYPE_UNDEF)
368 return (EINVAL);
369 }
370
371 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_AUX) {
372 switch (mac_lomac->ml_auxsingle.mle_type) {
373 case MAC_LOMAC_TYPE_GRADE:
374 case MAC_LOMAC_TYPE_EQUAL:
375 case MAC_LOMAC_TYPE_HIGH:
376 case MAC_LOMAC_TYPE_LOW:
377 break;
378
379 default:
380 return (EINVAL);
381 }
382 } else {
383 if (mac_lomac->ml_auxsingle.mle_type != MAC_LOMAC_TYPE_UNDEF)
384 return (EINVAL);
385 }
386
387 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_RANGE) {
388 switch (mac_lomac->ml_rangelow.mle_type) {
389 case MAC_LOMAC_TYPE_GRADE:
390 case MAC_LOMAC_TYPE_EQUAL:
391 case MAC_LOMAC_TYPE_HIGH:
392 case MAC_LOMAC_TYPE_LOW:
393 break;
394
395 default:
396 return (EINVAL);
397 }
398
399 switch (mac_lomac->ml_rangehigh.mle_type) {
400 case MAC_LOMAC_TYPE_GRADE:
401 case MAC_LOMAC_TYPE_EQUAL:
402 case MAC_LOMAC_TYPE_HIGH:
403 case MAC_LOMAC_TYPE_LOW:
404 break;
405
406 default:
407 return (EINVAL);
408 }
409 if (!mac_lomac_dominate_element(&mac_lomac->ml_rangehigh,
410 &mac_lomac->ml_rangelow))
411 return (EINVAL);
412 } else {
413 if (mac_lomac->ml_rangelow.mle_type != MAC_LOMAC_TYPE_UNDEF ||
414 mac_lomac->ml_rangehigh.mle_type != MAC_LOMAC_TYPE_UNDEF)
415 return (EINVAL);
416 }
417
418 return (0);
419}
420
421static void
422mac_lomac_set_range(struct mac_lomac *mac_lomac, u_short typelow,
423 u_short gradelow, u_short typehigh, u_short gradehigh)
424{
425
426 mac_lomac->ml_rangelow.mle_type = typelow;
427 mac_lomac->ml_rangelow.mle_grade = gradelow;
428 mac_lomac->ml_rangehigh.mle_type = typehigh;
429 mac_lomac->ml_rangehigh.mle_grade = gradehigh;
430 mac_lomac->ml_flags |= MAC_LOMAC_FLAG_RANGE;
431}
432
433static void
434mac_lomac_set_single(struct mac_lomac *mac_lomac, u_short type, u_short grade)
435{
436
437 mac_lomac->ml_single.mle_type = type;
438 mac_lomac->ml_single.mle_grade = grade;
439 mac_lomac->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
440}
441
442static void
443mac_lomac_copy_range(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
444{
445
446 KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
447 ("mac_lomac_copy_range: labelfrom not range"));
448
449 labelto->ml_rangelow = labelfrom->ml_rangelow;
450 labelto->ml_rangehigh = labelfrom->ml_rangehigh;
451 labelto->ml_flags |= MAC_LOMAC_FLAG_RANGE;
452}
453
454static void
455mac_lomac_copy_single(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
456{
457
458 KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
459 ("mac_lomac_copy_single: labelfrom not single"));
460
461 labelto->ml_single = labelfrom->ml_single;
462 labelto->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
463}
464
465static void
466mac_lomac_copy_auxsingle(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
467{
468
469 KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_AUX) != 0,
470 ("mac_lomac_copy_auxsingle: labelfrom not auxsingle"));
471
472 labelto->ml_auxsingle = labelfrom->ml_auxsingle;
473 labelto->ml_flags |= MAC_LOMAC_FLAG_AUX;
474}
475
476static void
477mac_lomac_copy(struct mac_lomac *source, struct mac_lomac *dest)
478{
479
480 if (source->ml_flags & MAC_LOMAC_FLAG_SINGLE)
481 mac_lomac_copy_single(source, dest);
482 if (source->ml_flags & MAC_LOMAC_FLAG_AUX)
483 mac_lomac_copy_auxsingle(source, dest);
484 if (source->ml_flags & MAC_LOMAC_FLAG_RANGE)
485 mac_lomac_copy_range(source, dest);
486}
487
488static int mac_lomac_to_string(struct sbuf *sb,
489 struct mac_lomac *mac_lomac);
490
491static int
492maybe_demote(struct mac_lomac *subjlabel, struct mac_lomac *objlabel,
493 const char *actionname, const char *objname, struct vnode *vpq)
494{
495 struct sbuf subjlabel_sb, subjtext_sb, objlabel_sb;
496 char *subjlabeltext, *objlabeltext, *subjtext;
497 struct mac_lomac cached_subjlabel;
498 struct mac_lomac_proc *subj;
499 struct vattr va;
500 struct proc *p;
501 pid_t pgid;
502
503 subj = PSLOT(curthread->td_proc->p_label);
504
505 p = curthread->td_proc;
506 mtx_lock(&subj->mtx);
507 if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
508 /*
509 * Check to see if the pending demotion would be more or
510 * less severe than this one, and keep the more severe.
511 * This can only happen for a multi-threaded application.
512 */
513 if (mac_lomac_dominate_single(objlabel, &subj->mac_lomac)) {
514 mtx_unlock(&subj->mtx);
515 return (0);
516 }
517 }
518 bzero(&subj->mac_lomac, sizeof(subj->mac_lomac));
519 /*
520 * Always demote the single label.
521 */
522 mac_lomac_copy_single(objlabel, &subj->mac_lomac);
523 /*
524 * Start with the original range, then minimize each side of
525 * the range to the point of not dominating the object. The
526 * high side will always be demoted, of course.
527 */
528 mac_lomac_copy_range(subjlabel, &subj->mac_lomac);
529 if (!mac_lomac_dominate_element(&objlabel->ml_single,
530 &subj->mac_lomac.ml_rangelow))
531 subj->mac_lomac.ml_rangelow = objlabel->ml_single;
532 subj->mac_lomac.ml_rangehigh = objlabel->ml_single;
533 subj->mac_lomac.ml_flags |= MAC_LOMAC_FLAG_UPDATE;
534 mtx_lock_spin(&sched_lock);
535 curthread->td_flags |= TDF_ASTPENDING;
536 curthread->td_proc->p_sflag |= PS_MACPEND;
537 mtx_unlock_spin(&sched_lock);
538
539 /*
540 * Avoid memory allocation while holding a mutex; cache the
541 * label.
542 */
543 mac_lomac_copy_single(&subj->mac_lomac, &cached_subjlabel);
544 mtx_unlock(&subj->mtx);
545
546 sbuf_new(&subjlabel_sb, NULL, 0, SBUF_AUTOEXTEND);
547 mac_lomac_to_string(&subjlabel_sb, subjlabel);
548 sbuf_finish(&subjlabel_sb);
549 subjlabeltext = sbuf_data(&subjlabel_sb);
550
551 sbuf_new(&subjtext_sb, NULL, 0, SBUF_AUTOEXTEND);
552 mac_lomac_to_string(&subjtext_sb, &subj->mac_lomac);
553 sbuf_finish(&subjtext_sb);
554 subjtext = sbuf_data(&subjtext_sb);
555
556 sbuf_new(&objlabel_sb, NULL, 0, SBUF_AUTOEXTEND);
557 mac_lomac_to_string(&objlabel_sb, objlabel);
558 sbuf_finish(&objlabel_sb);
559 objlabeltext = sbuf_data(&objlabel_sb);
560
561 pgid = p->p_pgrp->pg_id; /* XXX could be stale? */
562 if (vpq != NULL && VOP_GETATTR(vpq, &va, curthread->td_ucred,
563 curthread) == 0) {
564 log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to"
565 " level %s after %s a level-%s %s (inode=%ld, "
566 "mountpount=%s)\n",
567 subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid,
568 p->p_comm, subjtext, actionname, objlabeltext, objname,
569 va.va_fileid, vpq->v_mount->mnt_stat.f_mntonname);
570 } else {
571 log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to"
572 " level %s after %s a level-%s %s\n",
573 subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid,
574 p->p_comm, subjtext, actionname, objlabeltext, objname);
575 }
576
577 sbuf_delete(&subjlabel_sb);
578 sbuf_delete(&subjtext_sb);
579 sbuf_delete(&objlabel_sb);
580
581 return (0);
582}
583
584/*
585 * Relabel "to" to "from" only if "from" is a valid label (contains
586 * at least a single), as for a relabel operation which may or may
587 * not involve a relevant label.
588 */
589static void
590try_relabel(struct mac_lomac *from, struct mac_lomac *to)
591{
592
593 if (from->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
594 bzero(to, sizeof(*to));
595 mac_lomac_copy(from, to);
596 }
597}
598
599/*
600 * Policy module operations.
601 */
602static void
603mac_lomac_init(struct mac_policy_conf *conf)
604{
605
606}
607
608/*
609 * Label operations.
610 */
611static void
612mac_lomac_init_label(struct label *label)
613{
614
615 SLOT(label) = lomac_alloc(M_WAITOK);
616}
617
618static int
619mac_lomac_init_label_waitcheck(struct label *label, int flag)
620{
621
622 SLOT(label) = lomac_alloc(flag);
623 if (SLOT(label) == NULL)
624 return (ENOMEM);
625
626 return (0);
627}
628
629static void
630mac_lomac_init_proc_label(struct label *label)
631{
632
633 PSLOT(label) = malloc(sizeof(struct mac_lomac_proc), M_MACLOMAC,
634 M_ZERO | M_WAITOK);
635 mtx_init(&PSLOT(label)->mtx, "MAC/Lomac proc lock", NULL, MTX_DEF);
636}
637
638static void
639mac_lomac_destroy_label(struct label *label)
640{
641
642 lomac_free(SLOT(label));
643 SLOT(label) = NULL;
644}
645
646static void
647mac_lomac_destroy_proc_label(struct label *label)
648{
649
650 mtx_destroy(&PSLOT(label)->mtx);
651 FREE(PSLOT(label), M_MACLOMAC);
652 PSLOT(label) = NULL;
653}
654
655static int
656mac_lomac_element_to_string(struct sbuf *sb, struct mac_lomac_element *element)
657{
658
659 switch (element->mle_type) {
660 case MAC_LOMAC_TYPE_HIGH:
661 return (sbuf_printf(sb, "high"));
662
663 case MAC_LOMAC_TYPE_LOW:
664 return (sbuf_printf(sb, "low"));
665
666 case MAC_LOMAC_TYPE_EQUAL:
667 return (sbuf_printf(sb, "equal"));
668
669 case MAC_LOMAC_TYPE_GRADE:
670 return (sbuf_printf(sb, "%d", element->mle_grade));
671
672 default:
673 panic("mac_lomac_element_to_string: invalid type (%d)",
674 element->mle_type);
675 }
676}
677
678static int
679mac_lomac_to_string(struct sbuf *sb, struct mac_lomac *mac_lomac)
680{
681
682 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
683 if (mac_lomac_element_to_string(sb, &mac_lomac->ml_single)
684 == -1)
685 return (EINVAL);
686 }
687
688 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_AUX) {
689 if (sbuf_putc(sb, '[') == -1)
690 return (EINVAL);
691
692 if (mac_lomac_element_to_string(sb, &mac_lomac->ml_auxsingle)
693 == -1)
694 return (EINVAL);
695
696 if (sbuf_putc(sb, ']') == -1)
697 return (EINVAL);
698 }
699
700 if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_RANGE) {
701 if (sbuf_putc(sb, '(') == -1)
702 return (EINVAL);
703
704 if (mac_lomac_element_to_string(sb, &mac_lomac->ml_rangelow)
705 == -1)
706 return (EINVAL);
707
708 if (sbuf_putc(sb, '-') == -1)
709 return (EINVAL);
710
711 if (mac_lomac_element_to_string(sb, &mac_lomac->ml_rangehigh)
712 == -1)
713 return (EINVAL);
714
715 if (sbuf_putc(sb, ')') == -1)
716 return (EINVAL);
717 }
718
719 return (0);
720}
721
722static int
723mac_lomac_externalize_label(struct label *label, char *element_name,
724 struct sbuf *sb, int *claimed)
725{
726 struct mac_lomac *mac_lomac;
727
728 if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0)
729 return (0);
730
731 (*claimed)++;
732
733 mac_lomac = SLOT(label);
734
735 return (mac_lomac_to_string(sb, mac_lomac));
736}
737
738static int
739mac_lomac_parse_element(struct mac_lomac_element *element, char *string)
740{
741
742 if (strcmp(string, "high") == 0 ||
743 strcmp(string, "hi") == 0) {
744 element->mle_type = MAC_LOMAC_TYPE_HIGH;
745 element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
746 } else if (strcmp(string, "low") == 0 ||
747 strcmp(string, "lo") == 0) {
748 element->mle_type = MAC_LOMAC_TYPE_LOW;
749 element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
750 } else if (strcmp(string, "equal") == 0 ||
751 strcmp(string, "eq") == 0) {
752 element->mle_type = MAC_LOMAC_TYPE_EQUAL;
753 element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
754 } else {
755 char *p0, *p1;
756 int d;
757
758 p0 = string;
759 d = strtol(p0, &p1, 10);
760
761 if (d < 0 || d > 65535)
762 return (EINVAL);
763 element->mle_type = MAC_LOMAC_TYPE_GRADE;
764 element->mle_grade = d;
765
766 if (p1 == p0 || *p1 != '\0')
767 return (EINVAL);
768 }
769
770 return (0);
771}
772
773/*
774 * Note: destructively consumes the string, make a local copy before
775 * calling if that's a problem.
776 */
777static int
778mac_lomac_parse(struct mac_lomac *mac_lomac, char *string)
779{
780 char *range, *rangeend, *rangehigh, *rangelow, *single, *auxsingle,
781 *auxsingleend;
782 int error;
783
784 /* Do we have a range? */
785 single = string;
786 range = index(string, '(');
787 if (range == single)
788 single = NULL;
789 auxsingle = index(string, '[');
790 if (auxsingle == single)
791 single = NULL;
792 if (range != NULL && auxsingle != NULL)
793 return (EINVAL);
794 rangelow = rangehigh = NULL;
795 if (range != NULL) {
796 /* Nul terminate the end of the single string. */
797 *range = '\0';
798 range++;
799 rangelow = range;
800 rangehigh = index(rangelow, '-');
801 if (rangehigh == NULL)
802 return (EINVAL);
803 rangehigh++;
804 if (*rangelow == '\0' || *rangehigh == '\0')
805 return (EINVAL);
806 rangeend = index(rangehigh, ')');
807 if (rangeend == NULL)
808 return (EINVAL);
809 if (*(rangeend + 1) != '\0')
810 return (EINVAL);
811 /* Nul terminate the ends of the ranges. */
812 *(rangehigh - 1) = '\0';
813 *rangeend = '\0';
814 }
815 KASSERT((rangelow != NULL && rangehigh != NULL) ||
816 (rangelow == NULL && rangehigh == NULL),
817 ("mac_lomac_internalize_label: range mismatch"));
818 if (auxsingle != NULL) {
819 /* Nul terminate the end of the single string. */
820 *auxsingle = '\0';
821 auxsingle++;
822 auxsingleend = index(auxsingle, ']');
823 if (auxsingleend == NULL)
824 return (EINVAL);
825 if (*(auxsingleend + 1) != '\0')
826 return (EINVAL);
827 /* Nul terminate the end of the auxsingle. */
828 *auxsingleend = '\0';
829 }
830
831 bzero(mac_lomac, sizeof(*mac_lomac));
832 if (single != NULL) {
833 error = mac_lomac_parse_element(&mac_lomac->ml_single, single);
834 if (error)
835 return (error);
836 mac_lomac->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
837 }
838
839 if (auxsingle != NULL) {
840 error = mac_lomac_parse_element(&mac_lomac->ml_auxsingle,
841 auxsingle);
842 if (error)
843 return (error);
844 mac_lomac->ml_flags |= MAC_LOMAC_FLAG_AUX;
845 }
846
847 if (rangelow != NULL) {
848 error = mac_lomac_parse_element(&mac_lomac->ml_rangelow,
849 rangelow);
850 if (error)
851 return (error);
852 error = mac_lomac_parse_element(&mac_lomac->ml_rangehigh,
853 rangehigh);
854 if (error)
855 return (error);
856 mac_lomac->ml_flags |= MAC_LOMAC_FLAG_RANGE;
857 }
858
859 error = mac_lomac_valid(mac_lomac);
860 if (error)
861 return (error);
862
863 return (0);
864}
865
866static int
867mac_lomac_internalize_label(struct label *label, char *element_name,
868 char *element_data, int *claimed)
869{
870 struct mac_lomac *mac_lomac, mac_lomac_temp;
871 int error;
872
873 if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0)
874 return (0);
875
876 (*claimed)++;
877
878 error = mac_lomac_parse(&mac_lomac_temp, element_data);
879 if (error)
880 return (error);
881
882 mac_lomac = SLOT(label);
883 *mac_lomac = mac_lomac_temp;
884
885 return (0);
886}
887
888static void
889mac_lomac_copy_label(struct label *src, struct label *dest)
890{
891
892 *SLOT(dest) = *SLOT(src);
893}
894
895/*
896 * Labeling event operations: file system objects, and things that look
897 * a lot like file system objects.
898 */
899static void
900mac_lomac_create_devfs_device(struct mount *mp, dev_t dev,
901 struct devfs_dirent *devfs_dirent, struct label *label)
902{
903 struct mac_lomac *mac_lomac;
904 int lomac_type;
905
906 mac_lomac = SLOT(label);
907 if (strcmp(dev->si_name, "null") == 0 ||
908 strcmp(dev->si_name, "zero") == 0 ||
909 strcmp(dev->si_name, "random") == 0 ||
910 strncmp(dev->si_name, "fd/", strlen("fd/")) == 0 ||
911 strncmp(dev->si_name, "ttyv", strlen("ttyv")) == 0)
912 lomac_type = MAC_LOMAC_TYPE_EQUAL;
913 else if (ptys_equal &&
914 (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
915 strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
916 lomac_type = MAC_LOMAC_TYPE_EQUAL;
917 else
918 lomac_type = MAC_LOMAC_TYPE_HIGH;
919 mac_lomac_set_single(mac_lomac, lomac_type, 0);
920}
921
922static void
923mac_lomac_create_devfs_directory(struct mount *mp, char *dirname,
924 int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label)
925{
926 struct mac_lomac *mac_lomac;
927
928 mac_lomac = SLOT(label);
929 mac_lomac_set_single(mac_lomac, MAC_LOMAC_TYPE_HIGH, 0);
930}
931
932static void
933mac_lomac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
934 struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
935 struct label *delabel)
936{
937 struct mac_lomac *source, *dest;
938
939 source = SLOT(cred->cr_label);
940 dest = SLOT(delabel);
941
942 mac_lomac_copy_single(source, dest);
943}
944
945static void
946mac_lomac_create_mount(struct ucred *cred, struct mount *mp,
947 struct label *mntlabel, struct label *fslabel)
948{
949 struct mac_lomac *source, *dest;
950
951 source = SLOT(cred->cr_label);
952 dest = SLOT(mntlabel);
953 mac_lomac_copy_single(source, dest);
954 dest = SLOT(fslabel);
955 mac_lomac_copy_single(source, dest);
956}
957
958static void
959mac_lomac_create_root_mount(struct ucred *cred, struct mount *mp,
960 struct label *mntlabel, struct label *fslabel)
961{
962 struct mac_lomac *mac_lomac;
963
964 /* Always mount root as high integrity. */
965 mac_lomac = SLOT(fslabel);
966 mac_lomac_set_single(mac_lomac, MAC_LOMAC_TYPE_HIGH, 0);
967 mac_lomac = SLOT(mntlabel);
968 mac_lomac_set_single(mac_lomac, MAC_LOMAC_TYPE_HIGH, 0);
969}
970
971static void
972mac_lomac_relabel_vnode(struct ucred *cred, struct vnode *vp,
973 struct label *vnodelabel, struct label *label)
974{
975 struct mac_lomac *source, *dest;
976
977 source = SLOT(label);
978 dest = SLOT(vnodelabel);
979
980 try_relabel(source, dest);
981}
982
983static void
984mac_lomac_update_devfsdirent(struct mount *mp,
985 struct devfs_dirent *devfs_dirent, struct label *direntlabel,
986 struct vnode *vp, struct label *vnodelabel)
987{
988 struct mac_lomac *source, *dest;
989
990 source = SLOT(vnodelabel);
991 dest = SLOT(direntlabel);
992
993 mac_lomac_copy(source, dest);
994}
995
996static void
997mac_lomac_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
998 struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
999 struct label *vlabel)
1000{
1001 struct mac_lomac *source, *dest;
1002
1003 source = SLOT(delabel);
1004 dest = SLOT(vlabel);
1005
1006 mac_lomac_copy_single(source, dest);
1007}
1008
1009static int
1010mac_lomac_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
1011 struct vnode *vp, struct label *vlabel)
1012{
1013 struct mac_lomac temp, *source, *dest;
1014 int buflen, error;
1015
1016 source = SLOT(fslabel);
1017 dest = SLOT(vlabel);
1018
1019 buflen = sizeof(temp);
1020 bzero(&temp, buflen);
1021
1022 error = vn_extattr_get(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
1023 MAC_LOMAC_EXTATTR_NAME, &buflen, (char *)&temp, curthread);
1024 if (error == ENOATTR || error == EOPNOTSUPP) {
1025 /* Fall back to the fslabel. */
1026 mac_lomac_copy_single(source, dest);
1027 return (0);
1028 } else if (error)
1029 return (error);
1030
1031 if (buflen != sizeof(temp)) {
1032 if (buflen != sizeof(temp) - sizeof(temp.ml_auxsingle)) {
1033 printf("mac_lomac_associate_vnode_extattr: bad size %d\n",
1034 buflen);
1035 return (EPERM);
1036 }
1037 bzero(&temp.ml_auxsingle, sizeof(temp.ml_auxsingle));
1038 buflen = sizeof(temp);
1039 (void)vn_extattr_set(vp, IO_NODELOCKED,
1040 MAC_LOMAC_EXTATTR_NAMESPACE, MAC_LOMAC_EXTATTR_NAME,
1041 buflen, (char *)&temp, curthread);
1042 }
1043 if (mac_lomac_valid(&temp) != 0) {
1044 printf("mac_lomac_associate_vnode_extattr: invalid\n");
1045 return (EPERM);
1046 }
1047 if ((temp.ml_flags & MAC_LOMAC_FLAGS_BOTH) != MAC_LOMAC_FLAG_SINGLE) {
1048 printf("mac_lomac_associate_vnode_extattr: not single\n");
1049 return (EPERM);
1050 }
1051
1052 mac_lomac_copy_single(&temp, dest);
1053 return (0);
1054}
1055
1056static void
1057mac_lomac_associate_vnode_singlelabel(struct mount *mp,
1058 struct label *fslabel, struct vnode *vp, struct label *vlabel)
1059{
1060 struct mac_lomac *source, *dest;
1061
1062 source = SLOT(fslabel);
1063 dest = SLOT(vlabel);
1064
1065 mac_lomac_copy_single(source, dest);
1066}
1067
1068static int
1069mac_lomac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1070 struct label *fslabel, struct vnode *dvp, struct label *dlabel,
1071 struct vnode *vp, struct label *vlabel, struct componentname *cnp)
1072{
1073 struct mac_lomac *source, *dest, *dir, temp;
1074 size_t buflen;
1075 int error;
1076
1077 buflen = sizeof(temp);
1078 bzero(&temp, buflen);
1079
1080 source = SLOT(cred->cr_label);
1081 dest = SLOT(vlabel);
1082 dir = SLOT(dlabel);
1083 if (dir->ml_flags & MAC_LOMAC_FLAG_AUX) {
1084 mac_lomac_copy_auxsingle(dir, &temp);
1085 mac_lomac_set_single(&temp, dir->ml_auxsingle.mle_type,
1086 dir->ml_auxsingle.mle_grade);
1087 } else {
1088 mac_lomac_copy_single(source, &temp);
1089 }
1090
1091 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
1092 MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
1093 if (error == 0)
1094 mac_lomac_copy(&temp, dest);
1095 return (error);
1096}
1097
1098static int
1099mac_lomac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1100 struct label *vlabel, struct label *intlabel)
1101{
1102 struct mac_lomac *source, temp;
1103 size_t buflen;
1104 int error;
1105
1106 buflen = sizeof(temp);
1107 bzero(&temp, buflen);
1108
1109 source = SLOT(intlabel);
1110 if ((source->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1111 return (0);
1112
1113 mac_lomac_copy_single(source, &temp);
1114 error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
1115 MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
1116 return (error);
1117}
1118
1119/*
1120 * Labeling event operations: IPC object.
1121 */
1122static void
1123mac_lomac_create_inpcb_from_socket(struct socket *so, struct label *solabel,
1124 struct inpcb *inp, struct label *inplabel)
1125{
1126 struct mac_lomac *source, *dest;
1127
1128 source = SLOT(solabel);
1129 dest = SLOT(inplabel);
1130
1131 mac_lomac_copy_single(source, dest);
1132}
1133
1134static void
1135mac_lomac_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
1136 struct mbuf *m, struct label *mbuflabel)
1137{
1138 struct mac_lomac *source, *dest;
1139
1140 source = SLOT(socketlabel);
1141 dest = SLOT(mbuflabel);
1142
1143 mac_lomac_copy_single(source, dest);
1144}
1145
1146static void
1147mac_lomac_create_socket(struct ucred *cred, struct socket *socket,
1148 struct label *socketlabel)
1149{
1150 struct mac_lomac *source, *dest;
1151
1152 source = SLOT(cred->cr_label);
1153 dest = SLOT(socketlabel);
1154
1155 mac_lomac_copy_single(source, dest);
1156}
1157
1158static void
1159mac_lomac_create_pipe(struct ucred *cred, struct pipepair *pp,
1160 struct label *pipelabel)
1161{
1162 struct mac_lomac *source, *dest;
1163
1164 source = SLOT(cred->cr_label);
1165 dest = SLOT(pipelabel);
1166
1167 mac_lomac_copy_single(source, dest);
1168}
1169
1170static void
1171mac_lomac_create_socket_from_socket(struct socket *oldsocket,
1172 struct label *oldsocketlabel, struct socket *newsocket,
1173 struct label *newsocketlabel)
1174{
1175 struct mac_lomac *source, *dest;
1176
1177 source = SLOT(oldsocketlabel);
1178 dest = SLOT(newsocketlabel);
1179
1180 mac_lomac_copy_single(source, dest);
1181}
1182
1183static void
1184mac_lomac_relabel_socket(struct ucred *cred, struct socket *socket,
1185 struct label *socketlabel, struct label *newlabel)
1186{
1187 struct mac_lomac *source, *dest;
1188
1189 source = SLOT(newlabel);
1190 dest = SLOT(socketlabel);
1191
1192 try_relabel(source, dest);
1193}
1194
1195static void
1196mac_lomac_relabel_pipe(struct ucred *cred, struct pipepair *pp,
1197 struct label *pipelabel, struct label *newlabel)
1198{
1199 struct mac_lomac *source, *dest;
1200
1201 source = SLOT(newlabel);
1202 dest = SLOT(pipelabel);
1203
1204 try_relabel(source, dest);
1205}
1206
1207static void
1208mac_lomac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
1209 struct socket *socket, struct label *socketpeerlabel)
1210{
1211 struct mac_lomac *source, *dest;
1212
1213 source = SLOT(mbuflabel);
1214 dest = SLOT(socketpeerlabel);
1215
1216 mac_lomac_copy_single(source, dest);
1217}
1218
1219/*
1220 * Labeling event operations: network objects.
1221 */
1222static void
1223mac_lomac_set_socket_peer_from_socket(struct socket *oldsocket,
1224 struct label *oldsocketlabel, struct socket *newsocket,
1225 struct label *newsocketpeerlabel)
1226{
1227 struct mac_lomac *source, *dest;
1228
1229 source = SLOT(oldsocketlabel);
1230 dest = SLOT(newsocketpeerlabel);
1231
1232 mac_lomac_copy_single(source, dest);
1233}
1234
1235static void
1236mac_lomac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
1237 struct label *bpflabel)
1238{
1239 struct mac_lomac *source, *dest;
1240
1241 source = SLOT(cred->cr_label);
1242 dest = SLOT(bpflabel);
1243
1244 mac_lomac_copy_single(source, dest);
1245}
1246
1247static void
1248mac_lomac_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
1249{
1250 char tifname[IFNAMSIZ], *p, *q;
1251 char tiflist[sizeof(trusted_interfaces)];
1252 struct mac_lomac *dest;
1253 int len, grade;
1254
1255 dest = SLOT(ifnetlabel);
1256
1257 if (ifnet->if_type == IFT_LOOP) {
1258 grade = MAC_LOMAC_TYPE_EQUAL;
1259 goto set;
1260 }
1261
1262 if (trust_all_interfaces) {
1263 grade = MAC_LOMAC_TYPE_HIGH;
1264 goto set;
1265 }
1266
1267 grade = MAC_LOMAC_TYPE_LOW;
1268
1269 if (trusted_interfaces[0] == '\0' ||
1270 !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
1271 goto set;
1272
1273 bzero(tiflist, sizeof(tiflist));
1274 for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
1275 if(*p != ' ' && *p != '\t')
1276 *q = *p;
1277
1278 for (p = q = tiflist;; p++) {
1279 if (*p == ',' || *p == '\0') {
1280 len = p - q;
1281 if (len < IFNAMSIZ) {
1282 bzero(tifname, sizeof(tifname));
1283 bcopy(q, tifname, len);
1284 if (strcmp(tifname, ifnet->if_xname) == 0) {
1285 grade = MAC_LOMAC_TYPE_HIGH;
1286 break;
1287 }
1288 }
1289 else {
1290 *p = '\0';
1291 printf("MAC/LOMAC warning: interface name "
1292 "\"%s\" is too long (must be < %d)\n",
1293 q, IFNAMSIZ);
1294 }
1295 if (*p == '\0')
1296 break;
1297 q = p + 1;
1298 }
1299 }
1300set:
1301 mac_lomac_set_single(dest, grade, 0);
1302 mac_lomac_set_range(dest, grade, 0, grade, 0);
1303}
1304
1305static void
1306mac_lomac_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1307 struct ipq *ipq, struct label *ipqlabel)
1308{
1309 struct mac_lomac *source, *dest;
1310
1311 source = SLOT(fragmentlabel);
1312 dest = SLOT(ipqlabel);
1313
1314 mac_lomac_copy_single(source, dest);
1315}
1316
1317static void
1318mac_lomac_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1319 struct mbuf *datagram, struct label *datagramlabel)
1320{
1321 struct mac_lomac *source, *dest;
1322
1323 source = SLOT(ipqlabel);
1324 dest = SLOT(datagramlabel);
1325
1326 /* Just use the head, since we require them all to match. */
1327 mac_lomac_copy_single(source, dest);
1328}
1329
1330static void
1331mac_lomac_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1332 struct mbuf *fragment, struct label *fragmentlabel)
1333{
1334 struct mac_lomac *source, *dest;
1335
1336 source = SLOT(datagramlabel);
1337 dest = SLOT(fragmentlabel);
1338
1339 mac_lomac_copy_single(source, dest);
1340}
1341
1342static void
1343mac_lomac_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel,
1344 struct mbuf *m, struct label *mlabel)
1345{
1346 struct mac_lomac *source, *dest;
1347
1348 source = SLOT(inplabel);
1349 dest = SLOT(mlabel);
1350
1351 mac_lomac_copy_single(source, dest);
1352}
1353
1354static void
1355mac_lomac_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
1356 struct label *oldmbuflabel, struct mbuf *newmbuf,
1357 struct label *newmbuflabel)
1358{
1359 struct mac_lomac *source, *dest;
1360
1361 source = SLOT(oldmbuflabel);
1362 dest = SLOT(newmbuflabel);
1363
1364 /*
1365 * Because the source mbuf may not yet have been "created",
1366 * just initialized, we do a conditional copy. Since we don't
1367 * allow mbufs to have ranges, do a KASSERT to make sure that
1368 * doesn't happen.
1369 */
1370 KASSERT((source->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0,
1371 ("mac_lomac_create_mbuf_from_mbuf: source mbuf has range"));
1372 mac_lomac_copy(source, dest);
1373}
1374
1375static void
1376mac_lomac_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1377 struct mbuf *mbuf, struct label *mbuflabel)
1378{
1379 struct mac_lomac *dest;
1380
1381 dest = SLOT(mbuflabel);
1382
1383 mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1384}
1385
1386static void
1387mac_lomac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1388 struct mbuf *mbuf, struct label *mbuflabel)
1389{
1390 struct mac_lomac *source, *dest;
1391
1392 source = SLOT(bpflabel);
1393 dest = SLOT(mbuflabel);
1394
1395 mac_lomac_copy_single(source, dest);
1396}
1397
1398static void
1399mac_lomac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1400 struct mbuf *m, struct label *mbuflabel)
1401{
1402 struct mac_lomac *source, *dest;
1403
1404 source = SLOT(ifnetlabel);
1405 dest = SLOT(mbuflabel);
1406
1407 mac_lomac_copy_single(source, dest);
1408}
1409
1410static void
1411mac_lomac_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1412 struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1413 struct mbuf *newmbuf, struct label *newmbuflabel)
1414{
1415 struct mac_lomac *source, *dest;
1416
1417 source = SLOT(oldmbuflabel);
1418 dest = SLOT(newmbuflabel);
1419
1420 mac_lomac_copy_single(source, dest);
1421}
1422
1423static void
1424mac_lomac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1425 struct mbuf *newmbuf, struct label *newmbuflabel)
1426{
1427 struct mac_lomac *source, *dest;
1428
1429 source = SLOT(oldmbuflabel);
1430 dest = SLOT(newmbuflabel);
1431
1432 mac_lomac_copy_single(source, dest);
1433}
1434
1435static int
1436mac_lomac_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1437 struct ipq *ipq, struct label *ipqlabel)
1438{
1439 struct mac_lomac *a, *b;
1440
1441 a = SLOT(ipqlabel);
1442 b = SLOT(fragmentlabel);
1443
1444 return (mac_lomac_equal_single(a, b));
1445}
1446
1447static void
1448mac_lomac_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1449 struct label *ifnetlabel, struct label *newlabel)
1450{
1451 struct mac_lomac *source, *dest;
1452
1453 source = SLOT(newlabel);
1454 dest = SLOT(ifnetlabel);
1455
1456 try_relabel(source, dest);
1457}
1458
1459static void
1460mac_lomac_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1461 struct ipq *ipq, struct label *ipqlabel)
1462{
1463
1464 /* NOOP: we only accept matching labels, so no need to update */
1465}
1466
1467static void
1468mac_lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1469 struct inpcb *inp, struct label *inplabel)
1470{
1471 struct mac_lomac *source, *dest;
1472
1473 source = SLOT(solabel);
1474 dest = SLOT(inplabel);
1475
1476 mac_lomac_copy_single(source, dest);
1477}
1478
1479/*
1480 * Labeling event operations: processes.
1481 */
1482static void
1483mac_lomac_execve_transition(struct ucred *old, struct ucred *new,
1484 struct vnode *vp, struct label *vnodelabel,
1485 struct label *interpvnodelabel, struct image_params *imgp,
1486 struct label *execlabel)
1487{
1488 struct mac_lomac *source, *dest, *obj, *robj;
1489
1490 source = SLOT(old->cr_label);
1491 dest = SLOT(new->cr_label);
1492 obj = SLOT(vnodelabel);
1493 robj = interpvnodelabel != NULL ? SLOT(interpvnodelabel) : obj;
1494
1495 mac_lomac_copy(source, dest);
1496 /*
1497 * If there's an auxiliary label on the real object, respect it
1498 * and assume that this level should be assumed immediately if
1499 * a higher level is currently in place.
1500 */
1501 if (robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
1502 !mac_lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single)
1503 && mac_lomac_auxsingle_in_range(robj, dest))
1504 mac_lomac_set_single(dest, robj->ml_auxsingle.mle_type,
1505 robj->ml_auxsingle.mle_grade);
1506 /*
1507 * Restructuring to use the execve transitioning mechanism
1508 * instead of the normal demotion mechanism here would be
1509 * difficult, so just copy the label over and perform standard
1510 * demotion. This is also non-optimal because it will result
1511 * in the intermediate label "new" being created and immediately
1512 * recycled.
1513 */
1514 if (mac_lomac_enabled && revocation_enabled &&
1515 !mac_lomac_dominate_single(obj, source))
1516 (void)maybe_demote(source, obj, "executing", "file", vp);
1517}
1518
1519static int
1520mac_lomac_execve_will_transition(struct ucred *old, struct vnode *vp,
1521 struct label *vnodelabel, struct label *interpvnodelabel,
1522 struct image_params *imgp, struct label *execlabel)
1523{
1524 struct mac_lomac *subj, *obj, *robj;
1525
1526 if (!mac_lomac_enabled || !revocation_enabled)
1527 return (0);
1528
1529 subj = SLOT(old->cr_label);
1530 obj = SLOT(vnodelabel);
1531 robj = interpvnodelabel != NULL ? SLOT(interpvnodelabel) : obj;
1532
1533 return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
1534 !mac_lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single)
1535 && mac_lomac_auxsingle_in_range(robj, subj)) ||
1536 !mac_lomac_dominate_single(obj, subj));
1537}
1538
1539static void
1540mac_lomac_create_proc0(struct ucred *cred)
1541{
1542 struct mac_lomac *dest;
1543
1544 dest = SLOT(cred->cr_label);
1545
1546 mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1547 mac_lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH,
1548 0);
1549}
1550
1551static void
1552mac_lomac_create_proc1(struct ucred *cred)
1553{
1554 struct mac_lomac *dest;
1555
1556 dest = SLOT(cred->cr_label);
1557
1558 mac_lomac_set_single(dest, MAC_LOMAC_TYPE_HIGH, 0);
1559 mac_lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH,
1560 0);
1561}
1562
1563static void
1564mac_lomac_relabel_cred(struct ucred *cred, struct label *newlabel)
1565{
1566 struct mac_lomac *source, *dest;
1567
1568 source = SLOT(newlabel);
1569 dest = SLOT(cred->cr_label);
1570
1571 try_relabel(source, dest);
1572}
1573
1574/*
1575 * Access control checks.
1576 */
1577static int
1578mac_lomac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1579 struct ifnet *ifnet, struct label *ifnetlabel)
1580{
1581 struct mac_lomac *a, *b;
1582
1583 if (!mac_lomac_enabled)
1584 return (0);
1585
1586 a = SLOT(bpflabel);
1587 b = SLOT(ifnetlabel);
1588
1589 if (mac_lomac_equal_single(a, b))
1590 return (0);
1591 return (EACCES);
1592}
1593
1594static int
1595mac_lomac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1596{
1597 struct mac_lomac *subj, *new;
1598 int error;
1599
1600 subj = SLOT(cred->cr_label);
1601 new = SLOT(newlabel);
1602
1603 /*
1604 * If there is a LOMAC label update for the credential, it may
1605 * be an update of the single, range, or both.
1606 */
1607 error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1608 if (error)
1609 return (error);
1610
1611 /*
1612 * If the LOMAC label is to be changed, authorize as appropriate.
1613 */
1614 if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1615 /*
1616 * Fill in the missing parts from the previous label.
1617 */
1618 if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1619 mac_lomac_copy_single(subj, new);
1620 if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1621 mac_lomac_copy_range(subj, new);
1622
1623 /*
1624 * To change the LOMAC range on a credential, the new
1625 * range label must be in the current range.
1626 */
1627 if (!mac_lomac_range_in_range(new, subj))
1628 return (EPERM);
1629
1630 /*
1631 * To change the LOMAC single label on a credential, the
1632 * new single label must be in the new range. Implicitly
1633 * from the previous check, the new single is in the old
1634 * range.
1635 */
1636 if (!mac_lomac_single_in_range(new, new))
1637 return (EPERM);
1638
1639 /*
1640 * To have EQUAL in any component of the new credential
1641 * LOMAC label, the subject must already have EQUAL in
1642 * their label.
1643 */
1644 if (mac_lomac_contains_equal(new)) {
1645 error = mac_lomac_subject_privileged(subj);
1646 if (error)
1647 return (error);
1648 }
1649
1650 /*
1651 * XXXMAC: Additional consistency tests regarding the
1652 * single and range of the new label might be performed
1653 * here.
1654 */
1655 }
1656
1657 return (0);
1658}
1659
1660static int
1661mac_lomac_check_cred_visible(struct ucred *u1, struct ucred *u2)
1662{
1663 struct mac_lomac *subj, *obj;
1664
1665 if (!mac_lomac_enabled)
1666 return (0);
1667
1668 subj = SLOT(u1->cr_label);
1669 obj = SLOT(u2->cr_label);
1670
1671 /* XXX: range */
1672 if (!mac_lomac_dominate_single(obj, subj))
1673 return (ESRCH);
1674
1675 return (0);
1676}
1677
1678static int
1679mac_lomac_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1680 struct label *ifnetlabel, struct label *newlabel)
1681{
1682 struct mac_lomac *subj, *new;
1683 int error;
1684
1685 subj = SLOT(cred->cr_label);
1686 new = SLOT(newlabel);
1687
1688 /*
1689 * If there is a LOMAC label update for the interface, it may
1690 * be an update of the single, range, or both.
1691 */
1692 error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1693 if (error)
1694 return (error);
1695
1696 /*
1697 * Relabling network interfaces requires LOMAC privilege.
1698 */
1699 error = mac_lomac_subject_privileged(subj);
1700 if (error)
1701 return (error);
1702
1703 /*
1704 * If the LOMAC label is to be changed, authorize as appropriate.
1705 */
1706 if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1707 /*
1708 * Fill in the missing parts from the previous label.
1709 */
1710 if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1711 mac_lomac_copy_single(subj, new);
1712 if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1713 mac_lomac_copy_range(subj, new);
1714
1715 /*
1716 * Rely on the traditional superuser status for the LOMAC
1717 * interface relabel requirements. XXXMAC: This will go
1718 * away.
1719 */
1720 error = suser_cred(cred, 0);
1721 if (error)
1722 return (EPERM);
1723
1724 /*
1725 * XXXMAC: Additional consistency tests regarding the single
1726 * and the range of the new label might be performed here.
1727 */
1728 }
1729
1730 return (0);
1731}
1732
1733static int
1734mac_lomac_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1735 struct mbuf *m, struct label *mbuflabel)
1736{
1737 struct mac_lomac *p, *i;
1738
1739 if (!mac_lomac_enabled)
1740 return (0);
1741
1742 p = SLOT(mbuflabel);
1743 i = SLOT(ifnetlabel);
1744
1745 return (mac_lomac_single_in_range(p, i) ? 0 : EACCES);
1746}
1747
1748static int
1749mac_lomac_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel,
1750 struct mbuf *m, struct label *mlabel)
1751{
1752 struct mac_lomac *p, *i;
1753
1754 if (!mac_lomac_enabled)
1755 return (0);
1756
1757 p = SLOT(mlabel);
1758 i = SLOT(inplabel);
1759
1760 return (mac_lomac_equal_single(p, i) ? 0 : EACCES);
1761}
1762
1763static int
1764mac_lomac_check_kld_load(struct ucred *cred, struct vnode *vp,
1765 struct label *label)
1766{
1767 struct mac_lomac *subj, *obj;
1768
1769 if (!mac_lomac_enabled)
1770 return (0);
1771
1772 subj = SLOT(cred->cr_label);
1773 obj = SLOT(label);
1774
1775 if (mac_lomac_subject_privileged(subj))
1776 return (EPERM);
1777
1778 if (!mac_lomac_high_single(obj))
1779 return (EACCES);
1780
1781 return (0);
1782}
1783
1784static int
1785mac_lomac_check_kld_unload(struct ucred *cred)
1786{
1787 struct mac_lomac *subj;
1788
1789 if (!mac_lomac_enabled)
1790 return (0);
1791
1792 subj = SLOT(cred->cr_label);
1793
1794 if (mac_lomac_subject_privileged(subj))
1795 return (EPERM);
1796
1797 return (0);
1798}
1799
1800static int
1801mac_lomac_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
1802 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1803{
1804
1805 if(!mac_lomac_enabled)
1806 return (0);
1807
1808 /* XXX: This will be implemented soon... */
1809
1810 return (0);
1811}
1812
1813static int
1814mac_lomac_check_pipe_read(struct ucred *cred, struct pipepair *pp,
1815 struct label *pipelabel)
1816{
1817 struct mac_lomac *subj, *obj;
1818
1819 if (!mac_lomac_enabled)
1820 return (0);
1821
1822 subj = SLOT(cred->cr_label);
1823 obj = SLOT((pipelabel));
1824
1825 if (!mac_lomac_dominate_single(obj, subj))
1826 return (maybe_demote(subj, obj, "reading", "pipe", NULL));
1827
1828 return (0);
1829}
1830
1831static int
1832mac_lomac_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1833 struct label *pipelabel, struct label *newlabel)
1834{
1835 struct mac_lomac *subj, *obj, *new;
1836 int error;
1837
1838 new = SLOT(newlabel);
1839 subj = SLOT(cred->cr_label);
1840 obj = SLOT(pipelabel);
1841
1842 /*
1843 * If there is a LOMAC label update for a pipe, it must be a
1844 * single update.
1845 */
1846 error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1847 if (error)
1848 return (error);
1849
1850 /*
1851 * To perform a relabel of a pipe (LOMAC label or not), LOMAC must
1852 * authorize the relabel.
1853 */
1854 if (!mac_lomac_single_in_range(obj, subj))
1855 return (EPERM);
1856
1857 /*
1858 * If the LOMAC label is to be changed, authorize as appropriate.
1859 */
1860 if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1861 /*
1862 * To change the LOMAC label on a pipe, the new pipe label
1863 * must be in the subject range.
1864 */
1865 if (!mac_lomac_single_in_range(new, subj))
1866 return (EPERM);
1867
1868 /*
1869 * To change the LOMAC label on a pipe to be EQUAL, the
1870 * subject must have appropriate privilege.
1871 */
1872 if (mac_lomac_contains_equal(new)) {
1873 error = mac_lomac_subject_privileged(subj);
1874 if (error)
1875 return (error);
1876 }
1877 }
1878
1879 return (0);
1880}
1881
1882static int
1883mac_lomac_check_pipe_write(struct ucred *cred, struct pipepair *pp,
1884 struct label *pipelabel)
1885{
1886 struct mac_lomac *subj, *obj;
1887
1888 if (!mac_lomac_enabled)
1889 return (0);
1890
1891 subj = SLOT(cred->cr_label);
1892 obj = SLOT((pipelabel));
1893
1894 if (!mac_lomac_subject_dominate(subj, obj))
1895 return (EACCES);
1896
1897 return (0);
1898}
1899
1900static int
1901mac_lomac_check_proc_debug(struct ucred *cred, struct proc *proc)
1902{
1903 struct mac_lomac *subj, *obj;
1904
1905 if (!mac_lomac_enabled)
1906 return (0);
1907
1908 subj = SLOT(cred->cr_label);
1909 obj = SLOT(proc->p_ucred->cr_label);
1910
1911 /* XXX: range checks */
1912 if (!mac_lomac_dominate_single(obj, subj))
1913 return (ESRCH);
1914 if (!mac_lomac_subject_dominate(subj, obj))
1915 return (EACCES);
1916
1917 return (0);
1918}
1919
1920static int
1921mac_lomac_check_proc_sched(struct ucred *cred, struct proc *proc)
1922{
1923 struct mac_lomac *subj, *obj;
1924
1925 if (!mac_lomac_enabled)
1926 return (0);
1927
1928 subj = SLOT(cred->cr_label);
1929 obj = SLOT(proc->p_ucred->cr_label);
1930
1931 /* XXX: range checks */
1932 if (!mac_lomac_dominate_single(obj, subj))
1933 return (ESRCH);
1934 if (!mac_lomac_subject_dominate(subj, obj))
1935 return (EACCES);
1936
1937 return (0);
1938}
1939
1940static int
1941mac_lomac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1942{
1943 struct mac_lomac *subj, *obj;
1944
1945 if (!mac_lomac_enabled)
1946 return (0);
1947
1948 subj = SLOT(cred->cr_label);
1949 obj = SLOT(proc->p_ucred->cr_label);
1950
1951 /* XXX: range checks */
1952 if (!mac_lomac_dominate_single(obj, subj))
1953 return (ESRCH);
1954 if (!mac_lomac_subject_dominate(subj, obj))
1955 return (EACCES);
1956
1957 return (0);
1958}
1959
1960static int
1961mac_lomac_check_socket_deliver(struct socket *so, struct label *socketlabel,
1962 struct mbuf *m, struct label *mbuflabel)
1963{
1964 struct mac_lomac *p, *s;
1965
1966 if (!mac_lomac_enabled)
1967 return (0);
1968
1969 p = SLOT(mbuflabel);
1970 s = SLOT(socketlabel);
1971
1972 return (mac_lomac_equal_single(p, s) ? 0 : EACCES);
1973}
1974
1975static int
1976mac_lomac_check_socket_relabel(struct ucred *cred, struct socket *socket,
1977 struct label *socketlabel, struct label *newlabel)
1978{
1979 struct mac_lomac *subj, *obj, *new;
1980 int error;
1981
1982 new = SLOT(newlabel);
1983 subj = SLOT(cred->cr_label);
1984 obj = SLOT(socketlabel);
1985
1986 /*
1987 * If there is a LOMAC label update for the socket, it may be
1988 * an update of single.
1989 */
1990 error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1991 if (error)
1992 return (error);
1993
1994 /*
1995 * To relabel a socket, the old socket single must be in the subject
1996 * range.
1997 */
1998 if (!mac_lomac_single_in_range(obj, subj))
1999 return (EPERM);
2000
2001 /*
2002 * If the LOMAC label is to be changed, authorize as appropriate.
2003 */
2004 if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2005 /*
2006 * To relabel a socket, the new socket single must be in
2007 * the subject range.
2008 */
2009 if (!mac_lomac_single_in_range(new, subj))
2010 return (EPERM);
2011
2012 /*
2013 * To change the LOMAC label on the socket to contain EQUAL,
2014 * the subject must have appropriate privilege.
2015 */
2016 if (mac_lomac_contains_equal(new)) {
2017 error = mac_lomac_subject_privileged(subj);
2018 if (error)
2019 return (error);
2020 }
2021 }
2022
2023 return (0);
2024}
2025
2026static int
2027mac_lomac_check_socket_visible(struct ucred *cred, struct socket *socket,
2028 struct label *socketlabel)
2029{
2030 struct mac_lomac *subj, *obj;
2031
2032 if (!mac_lomac_enabled)
2033 return (0);
2034
2035 subj = SLOT(cred->cr_label);
2036 obj = SLOT(socketlabel);
2037
2038 if (!mac_lomac_dominate_single(obj, subj))
2039 return (ENOENT);
2040
2041 return (0);
2042}
2043
2044static int
2045mac_lomac_check_system_swapon(struct ucred *cred, struct vnode *vp,
2046 struct label *label)
2047{
2048 struct mac_lomac *subj, *obj;
2049
2050 if (!mac_lomac_enabled)
2051 return (0);
2052
2053 subj = SLOT(cred->cr_label);
2054 obj = SLOT(label);
2055
2056 if (mac_lomac_subject_privileged(subj))
2057 return (EPERM);
2058
2059 if (!mac_lomac_high_single(obj))
2060 return (EACCES);
2061
2062 return (0);
2063}
2064
2065static int
2066mac_lomac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2067 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2068{
2069 struct mac_lomac *subj;
2070
2071 if (!mac_lomac_enabled)
2072 return (0);
2073
2074 subj = SLOT(cred->cr_label);
2075
2076 /*
2077 * In general, treat sysctl variables as lomac/high, but also
2078 * require privilege to change them, since they are a
2079 * communications channel between grades. Exempt MIB
2080 * queries from this due to undocmented sysctl magic.
2081 * XXXMAC: This probably requires some more review.
2082 */
2083 if (new != NULL) {
2084 if (namelen > 0 && name[0] == 0)
2085 return (0);
2086
2087#ifdef notdef
2088 if (!mac_lomac_subject_dominate_high(subj))
2089 return (EACCES);
2090#endif
2091
2092 if (mac_lomac_subject_privileged(subj))
2093 return (EPERM);
2094 }
2095
2096 return (0);
2097}
2098
2099static int
2100mac_lomac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2101 struct label *dlabel, struct componentname *cnp, struct vattr *vap)
2102{
2103 struct mac_lomac *subj, *obj;
2104
2105 if (!mac_lomac_enabled)
2106 return (0);
2107
2108 subj = SLOT(cred->cr_label);
2109 obj = SLOT(dlabel);
2110
2111 if (!mac_lomac_subject_dominate(subj, obj))
2112 return (EACCES);
2113 if (obj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2114 !mac_lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle))
2115 return (EACCES);
2116
2117 return (0);
2118}
2119
2120static int
2121mac_lomac_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
2122 struct label *dlabel, struct vnode *vp, struct label *label,
2123 struct componentname *cnp)
2124{
2125 struct mac_lomac *subj, *obj;
2126
2127 if (!mac_lomac_enabled)
2128 return (0);
2129
2130 subj = SLOT(cred->cr_label);
2131 obj = SLOT(dlabel);
2132
2133 if (!mac_lomac_subject_dominate(subj, obj))
2134 return (EACCES);
2135
2136 obj = SLOT(label);
2137
2138 if (!mac_lomac_subject_dominate(subj, obj))
2139 return (EACCES);
2140
2141 return (0);
2142}
2143
2144static int
2145mac_lomac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2146 struct label *label, acl_type_t type)
2147{
2148 struct mac_lomac *subj, *obj;
2149
2150 if (!mac_lomac_enabled)
2151 return (0);
2152
2153 subj = SLOT(cred->cr_label);
2154 obj = SLOT(label);
2155
2156 if (!mac_lomac_subject_dominate(subj, obj))
2157 return (EACCES);
2158
2159 return (0);
2160}
2161
2162static int
2163mac_lomac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2164 struct label *dlabel, struct vnode *vp, struct label *label,
2165 struct componentname *cnp)
2166{
2167 struct mac_lomac *subj, *obj;
2168
2169 if (!mac_lomac_enabled)
2170 return (0);
2171
2172 subj = SLOT(cred->cr_label);
2173 obj = SLOT(dlabel);
2174
2175 if (!mac_lomac_subject_dominate(subj, obj))
2176 return (EACCES);
2177
2178 obj = SLOT(label);
2179
2180 if (!mac_lomac_subject_dominate(subj, obj))
2181 return (EACCES);
2182
2183 return (0);
2184}
2185
2186static int
2187mac_lomac_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2188 struct label *label, int prot)
2189{
2190 struct mac_lomac *subj, *obj;
2191
2192 /*
2193 * Rely on the use of open()-time protections to handle
2194 * non-revocation cases.
2195 */
2196 if (!mac_lomac_enabled)
2197 return (0);
2198
2199 subj = SLOT(cred->cr_label);
2200 obj = SLOT(label);
2201
2202 if (prot & VM_PROT_WRITE) {
2203 if (!mac_lomac_subject_dominate(subj, obj))
2204 return (EACCES);
2205 }
2206 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2207 if (!mac_lomac_dominate_single(obj, subj))
2208 return (maybe_demote(subj, obj, "mapping", "file", vp));
2209 }
2210
2211 return (0);
2212}
2213
2214static int
2215mac_lomac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp,
2216 struct label *label, int prot)
2217{
2218 struct mac_lomac *subj, *obj;
2219
2220 /*
2221 * Rely on the use of open()-time protections to handle
2222 * non-revocation cases.
2223 */
2224 if (!mac_lomac_enabled || !revocation_enabled)
2225 return (0);
2226
2227 subj = SLOT(cred->cr_label);
2228 obj = SLOT(label);
2229
2230 if (prot & VM_PROT_WRITE) {
2231 if (!mac_lomac_subject_dominate(subj, obj))
2232 return (EACCES);
2233 }
2234 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2235 if (!mac_lomac_dominate_single(obj, subj))
2236 return (EACCES);
2237 }
2238
2239 return (0);
2240}
2241
2242static void
2243mac_lomac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp,
2244 struct label *label, /* XXX vm_prot_t */ int *prot)
2245{
2246 struct mac_lomac *subj, *obj;
2247
2248 /*
2249 * Rely on the use of open()-time protections to handle
2250 * non-revocation cases.
2251 */
2252 if (!mac_lomac_enabled || !revocation_enabled)
2253 return;
2254
2255 subj = SLOT(cred->cr_label);
2256 obj = SLOT(label);
2257
2258 if (!mac_lomac_subject_dominate(subj, obj))
2259 *prot &= ~VM_PROT_WRITE;
2260}
2261
2262static int
2263mac_lomac_check_vnode_open(struct ucred *cred, struct vnode *vp,
2264 struct label *vnodelabel, int acc_mode)
2265{
2266 struct mac_lomac *subj, *obj;
2267
2268 if (!mac_lomac_enabled)
2269 return (0);
2270
2271 subj = SLOT(cred->cr_label);
2272 obj = SLOT(vnodelabel);
2273
2274 /* XXX privilege override for admin? */
2275 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2276 if (!mac_lomac_subject_dominate(subj, obj))
2277 return (EACCES);
2278 }
2279
2280 return (0);
2281}
2282
2283static int
2284mac_lomac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2285 struct vnode *vp, struct label *label)
2286{
2287 struct mac_lomac *subj, *obj;
2288
2289 if (!mac_lomac_enabled || !revocation_enabled)
2290 return (0);
2291
2292 subj = SLOT(active_cred->cr_label);
2293 obj = SLOT(label);
2294
2295 if (!mac_lomac_dominate_single(obj, subj))
2296 return (maybe_demote(subj, obj, "reading", "file", vp));
2297
2298 return (0);
2299}
2300
2301static int
2302mac_lomac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2303 struct label *vnodelabel, struct label *newlabel)
2304{
2305 struct mac_lomac *old, *new, *subj;
2306 int error;
2307
2308 old = SLOT(vnodelabel);
2309 new = SLOT(newlabel);
2310 subj = SLOT(cred->cr_label);
2311
2312 /*
2313 * If there is a LOMAC label update for the vnode, it must be a
2314 * single label, with an optional explicit auxiliary single.
2315 */
2316 error = lomac_atmostflags(new,
2317 MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX);
2318 if (error)
2319 return (error);
2320
2321 /*
2322 * To perform a relabel of the vnode (LOMAC label or not), LOMAC must
2323 * authorize the relabel.
2324 */
2325 if (!mac_lomac_single_in_range(old, subj))
2326 return (EPERM);
2327
2328 /*
2329 * If the LOMAC label is to be changed, authorize as appropriate.
2330 */
2331 if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2332 /*
2333 * To change the LOMAC label on a vnode, the new vnode label
2334 * must be in the subject range.
2335 */
2336 if (!mac_lomac_single_in_range(new, subj))
2337 return (EPERM);
2338
2339 /*
2340 * To change the LOMAC label on the vnode to be EQUAL,
2341 * the subject must have appropriate privilege.
2342 */
2343 if (mac_lomac_contains_equal(new)) {
2344 error = mac_lomac_subject_privileged(subj);
2345 if (error)
2346 return (error);
2347 }
2348 }
2349 if (new->ml_flags & MAC_LOMAC_FLAG_AUX) {
2350 /*
2351 * Fill in the missing parts from the previous label.
2352 */
2353 if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
2354 mac_lomac_copy_single(subj, new);
2355
2356 /*
2357 * To change the auxiliary LOMAC label on a vnode, the new
2358 * vnode label must be in the subject range.
2359 */
2360 if (!mac_lomac_auxsingle_in_range(new, subj))
2361 return (EPERM);
2362
2363 /*
2364 * To change the auxiliary LOMAC label on the vnode to be
2365 * EQUAL, the subject must have appropriate privilege.
2366 */
2367 if (mac_lomac_contains_equal(new)) {
2368 error = mac_lomac_subject_privileged(subj);
2369 if (error)
2370 return (error);
2371 }
2372 }
2373
2374 return (0);
2375}
2376
2377static int
2378mac_lomac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2379 struct label *dlabel, struct vnode *vp, struct label *label,
2380 struct componentname *cnp)
2381{
2382 struct mac_lomac *subj, *obj;
2383
2384 if (!mac_lomac_enabled)
2385 return (0);
2386
2387 subj = SLOT(cred->cr_label);
2388 obj = SLOT(dlabel);
2389
2390 if (!mac_lomac_subject_dominate(subj, obj))
2391 return (EACCES);
2392
2393 obj = SLOT(label);
2394
2395 if (!mac_lomac_subject_dominate(subj, obj))
2396 return (EACCES);
2397
2398 return (0);
2399}
2400
2401static int
2402mac_lomac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2403 struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2404 struct componentname *cnp)
2405{
2406 struct mac_lomac *subj, *obj;
2407
2408 if (!mac_lomac_enabled)
2409 return (0);
2410
2411 subj = SLOT(cred->cr_label);
2412 obj = SLOT(dlabel);
2413
2414 if (!mac_lomac_subject_dominate(subj, obj))
2415 return (EACCES);
2416
2417 if (vp != NULL) {
2418 obj = SLOT(label);
2419
2420 if (!mac_lomac_subject_dominate(subj, obj))
2421 return (EACCES);
2422 }
2423
2424 return (0);
2425}
2426
2427static int
2428mac_lomac_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2429 struct label *label)
2430{
2431 struct mac_lomac *subj, *obj;
2432
2433 if (!mac_lomac_enabled)
2434 return (0);
2435
2436 subj = SLOT(cred->cr_label);
2437 obj = SLOT(label);
2438
2439 if (!mac_lomac_subject_dominate(subj, obj))
2440 return (EACCES);
2441
2442 return (0);
2443}
2444
2445static int
2446mac_lomac_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2447 struct label *label, acl_type_t type, struct acl *acl)
2448{
2449 struct mac_lomac *subj, *obj;
2450
2451 if (!mac_lomac_enabled)
2452 return (0);
2453
2454 subj = SLOT(cred->cr_label);
2455 obj = SLOT(label);
2456
2457 if (!mac_lomac_subject_dominate(subj, obj))
2458 return (EACCES);
2459
2460 return (0);
2461}
2462
2463static int
2464mac_lomac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2465 struct label *vnodelabel, int attrnamespace, const char *name,
2466 struct uio *uio)
2467{
2468 struct mac_lomac *subj, *obj;
2469
2470 if (!mac_lomac_enabled)
2471 return (0);
2472
2473 subj = SLOT(cred->cr_label);
2474 obj = SLOT(vnodelabel);
2475
2476 if (!mac_lomac_subject_dominate(subj, obj))
2477 return (EACCES);
2478
2479 /* XXX: protect the MAC EA in a special way? */
2480
2481 return (0);
2482}
2483
2484static int
2485mac_lomac_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2486 struct label *vnodelabel, u_long flags)
2487{
2488 struct mac_lomac *subj, *obj;
2489
2490 if (!mac_lomac_enabled)
2491 return (0);
2492
2493 subj = SLOT(cred->cr_label);
2494 obj = SLOT(vnodelabel);
2495
2496 if (!mac_lomac_subject_dominate(subj, obj))
2497 return (EACCES);
2498
2499 return (0);
2500}
2501
2502static int
2503mac_lomac_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2504 struct label *vnodelabel, mode_t mode)
2505{
2506 struct mac_lomac *subj, *obj;
2507
2508 if (!mac_lomac_enabled)
2509 return (0);
2510
2511 subj = SLOT(cred->cr_label);
2512 obj = SLOT(vnodelabel);
2513
2514 if (!mac_lomac_subject_dominate(subj, obj))
2515 return (EACCES);
2516
2517 return (0);
2518}
2519
2520static int
2521mac_lomac_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2522 struct label *vnodelabel, uid_t uid, gid_t gid)
2523{
2524 struct mac_lomac *subj, *obj;
2525
2526 if (!mac_lomac_enabled)
2527 return (0);
2528
2529 subj = SLOT(cred->cr_label);
2530 obj = SLOT(vnodelabel);
2531
2532 if (!mac_lomac_subject_dominate(subj, obj))
2533 return (EACCES);
2534
2535 return (0);
2536}
2537
2538static int
2539mac_lomac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2540 struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2541{
2542 struct mac_lomac *subj, *obj;
2543
2544 if (!mac_lomac_enabled)
2545 return (0);
2546
2547 subj = SLOT(cred->cr_label);
2548 obj = SLOT(vnodelabel);
2549
2550 if (!mac_lomac_subject_dominate(subj, obj))
2551 return (EACCES);
2552
2553 return (0);
2554}
2555
2556static int
2557mac_lomac_check_vnode_write(struct ucred *active_cred,
2558 struct ucred *file_cred, struct vnode *vp, struct label *label)
2559{
2560 struct mac_lomac *subj, *obj;
2561
2562 if (!mac_lomac_enabled || !revocation_enabled)
2563 return (0);
2564
2565 subj = SLOT(active_cred->cr_label);
2566 obj = SLOT(label);
2567
2568 if (!mac_lomac_subject_dominate(subj, obj))
2569 return (EACCES);
2570
2571 return (0);
2572}
2573
2574static void
2575mac_lomac_thread_userret(struct thread *td)
2576{
2577 struct proc *p = td->td_proc;
2578 struct mac_lomac_proc *subj = PSLOT(p->p_label);
2579 struct ucred *newcred, *oldcred;
2580 int dodrop;
2581
2582 mtx_lock(&subj->mtx);
2583 if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
2584 dodrop = 0;
2585 mtx_unlock(&subj->mtx);
2586 newcred = crget();
2587 /*
2588 * Prevent a lock order reversal in
2589 * mac_cred_mmapped_drop_perms; ideally, the other
2590 * user of subj->mtx wouldn't be holding Giant.
2591 */
2592 mtx_lock(&Giant);
2593 PROC_LOCK(p);
2594 mtx_lock(&subj->mtx);
2595 /*
2596 * Check if we lost the race while allocating the cred.
2597 */
2598 if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) {
2599 crfree(newcred);
2600 goto out;
2601 }
2602 oldcred = p->p_ucred;
2603 crcopy(newcred, oldcred);
2604 crhold(newcred);
2605 mac_lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label));
2606 p->p_ucred = newcred;
2607 crfree(oldcred);
2608 dodrop = 1;
2609 out:
2610 mtx_unlock(&subj->mtx);
2611 PROC_UNLOCK(p);
2612 if (dodrop)
2613 mac_cred_mmapped_drop_perms(curthread, newcred);
2614 mtx_unlock(&Giant);
2615 } else {
2616 mtx_unlock(&subj->mtx);
2617 }
2618}
2619
2620static struct mac_policy_ops mac_lomac_ops =
2621{
2622 .mpo_init = mac_lomac_init,
2623 .mpo_init_bpfdesc_label = mac_lomac_init_label,
2624 .mpo_init_cred_label = mac_lomac_init_label,
2625 .mpo_init_devfsdirent_label = mac_lomac_init_label,
2626 .mpo_init_ifnet_label = mac_lomac_init_label,
2627 .mpo_init_inpcb_label = mac_lomac_init_label_waitcheck,
2628 .mpo_init_ipq_label = mac_lomac_init_label_waitcheck,
2629 .mpo_init_mbuf_label = mac_lomac_init_label_waitcheck,
2630 .mpo_init_mount_label = mac_lomac_init_label,
2631 .mpo_init_mount_fs_label = mac_lomac_init_label,
2632 .mpo_init_pipe_label = mac_lomac_init_label,
2633 .mpo_init_proc_label = mac_lomac_init_proc_label,
2634 .mpo_init_socket_label = mac_lomac_init_label_waitcheck,
2635 .mpo_init_socket_peer_label = mac_lomac_init_label_waitcheck,
2636 .mpo_init_vnode_label = mac_lomac_init_label,
2637 .mpo_destroy_bpfdesc_label = mac_lomac_destroy_label,
2638 .mpo_destroy_cred_label = mac_lomac_destroy_label,
2639 .mpo_destroy_devfsdirent_label = mac_lomac_destroy_label,
2640 .mpo_destroy_ifnet_label = mac_lomac_destroy_label,
2641 .mpo_destroy_inpcb_label = mac_lomac_destroy_label,
2642 .mpo_destroy_ipq_label = mac_lomac_destroy_label,
2643 .mpo_destroy_mbuf_label = mac_lomac_destroy_label,
2644 .mpo_destroy_mount_label = mac_lomac_destroy_label,
2645 .mpo_destroy_mount_fs_label = mac_lomac_destroy_label,
2646 .mpo_destroy_pipe_label = mac_lomac_destroy_label,
2647 .mpo_destroy_proc_label = mac_lomac_destroy_proc_label,
2648 .mpo_destroy_socket_label = mac_lomac_destroy_label,
2649 .mpo_destroy_socket_peer_label = mac_lomac_destroy_label,
2650 .mpo_destroy_vnode_label = mac_lomac_destroy_label,
2651 .mpo_copy_cred_label = mac_lomac_copy_label,
2652 .mpo_copy_mbuf_label = mac_lomac_copy_label,
2653 .mpo_copy_pipe_label = mac_lomac_copy_label,
2654 .mpo_copy_socket_label = mac_lomac_copy_label,
2655 .mpo_copy_vnode_label = mac_lomac_copy_label,
2656 .mpo_externalize_cred_label = mac_lomac_externalize_label,
2657 .mpo_externalize_ifnet_label = mac_lomac_externalize_label,
2658 .mpo_externalize_pipe_label = mac_lomac_externalize_label,
2659 .mpo_externalize_socket_label = mac_lomac_externalize_label,
2660 .mpo_externalize_socket_peer_label = mac_lomac_externalize_label,
2661 .mpo_externalize_vnode_label = mac_lomac_externalize_label,
2662 .mpo_internalize_cred_label = mac_lomac_internalize_label,
2663 .mpo_internalize_ifnet_label = mac_lomac_internalize_label,
2664 .mpo_internalize_pipe_label = mac_lomac_internalize_label,
2665 .mpo_internalize_socket_label = mac_lomac_internalize_label,
2666 .mpo_internalize_vnode_label = mac_lomac_internalize_label,
2667 .mpo_create_devfs_device = mac_lomac_create_devfs_device,
2668 .mpo_create_devfs_directory = mac_lomac_create_devfs_directory,
2669 .mpo_create_devfs_symlink = mac_lomac_create_devfs_symlink,
2670 .mpo_create_mount = mac_lomac_create_mount,
2671 .mpo_create_root_mount = mac_lomac_create_root_mount,
2672 .mpo_relabel_vnode = mac_lomac_relabel_vnode,
2673 .mpo_update_devfsdirent = mac_lomac_update_devfsdirent,
2674 .mpo_associate_vnode_devfs = mac_lomac_associate_vnode_devfs,
2675 .mpo_associate_vnode_extattr = mac_lomac_associate_vnode_extattr,
2676 .mpo_associate_vnode_singlelabel =
2677 mac_lomac_associate_vnode_singlelabel,
2678 .mpo_create_vnode_extattr = mac_lomac_create_vnode_extattr,
2679 .mpo_setlabel_vnode_extattr = mac_lomac_setlabel_vnode_extattr,
2680 .mpo_create_mbuf_from_socket = mac_lomac_create_mbuf_from_socket,
2681 .mpo_create_pipe = mac_lomac_create_pipe,
2682 .mpo_create_socket = mac_lomac_create_socket,
2683 .mpo_create_socket_from_socket = mac_lomac_create_socket_from_socket,
2684 .mpo_relabel_pipe = mac_lomac_relabel_pipe,
2685 .mpo_relabel_socket = mac_lomac_relabel_socket,
2686 .mpo_set_socket_peer_from_mbuf = mac_lomac_set_socket_peer_from_mbuf,
2687 .mpo_set_socket_peer_from_socket =
2688 mac_lomac_set_socket_peer_from_socket,
2689 .mpo_create_bpfdesc = mac_lomac_create_bpfdesc,
2690 .mpo_create_datagram_from_ipq = mac_lomac_create_datagram_from_ipq,
2691 .mpo_create_fragment = mac_lomac_create_fragment,
2692 .mpo_create_ifnet = mac_lomac_create_ifnet,
2693 .mpo_create_inpcb_from_socket = mac_lomac_create_inpcb_from_socket,
2694 .mpo_create_ipq = mac_lomac_create_ipq,
2695 .mpo_create_mbuf_from_inpcb = mac_lomac_create_mbuf_from_inpcb,
2696 .mpo_create_mbuf_from_mbuf = mac_lomac_create_mbuf_from_mbuf,
2697 .mpo_create_mbuf_linklayer = mac_lomac_create_mbuf_linklayer,
2698 .mpo_create_mbuf_from_bpfdesc = mac_lomac_create_mbuf_from_bpfdesc,
2699 .mpo_create_mbuf_from_ifnet = mac_lomac_create_mbuf_from_ifnet,
2700 .mpo_create_mbuf_multicast_encap =
2701 mac_lomac_create_mbuf_multicast_encap,
2702 .mpo_create_mbuf_netlayer = mac_lomac_create_mbuf_netlayer,
2703 .mpo_fragment_match = mac_lomac_fragment_match,
2704 .mpo_relabel_ifnet = mac_lomac_relabel_ifnet,
2705 .mpo_update_ipq = mac_lomac_update_ipq,
2706 .mpo_inpcb_sosetlabel = mac_lomac_inpcb_sosetlabel,
2707 .mpo_execve_transition = mac_lomac_execve_transition,
2708 .mpo_execve_will_transition = mac_lomac_execve_will_transition,
2709 .mpo_create_proc0 = mac_lomac_create_proc0,
2710 .mpo_create_proc1 = mac_lomac_create_proc1,
2711 .mpo_relabel_cred = mac_lomac_relabel_cred,
2712 .mpo_check_bpfdesc_receive = mac_lomac_check_bpfdesc_receive,
2713 .mpo_check_cred_relabel = mac_lomac_check_cred_relabel,
2714 .mpo_check_cred_visible = mac_lomac_check_cred_visible,
2715 .mpo_check_ifnet_relabel = mac_lomac_check_ifnet_relabel,
2716 .mpo_check_ifnet_transmit = mac_lomac_check_ifnet_transmit,
2717 .mpo_check_inpcb_deliver = mac_lomac_check_inpcb_deliver,
2718 .mpo_check_kld_load = mac_lomac_check_kld_load,
2719 .mpo_check_kld_unload = mac_lomac_check_kld_unload,
2720 .mpo_check_pipe_ioctl = mac_lomac_check_pipe_ioctl,
2721 .mpo_check_pipe_read = mac_lomac_check_pipe_read,
2722 .mpo_check_pipe_relabel = mac_lomac_check_pipe_relabel,
2723 .mpo_check_pipe_write = mac_lomac_check_pipe_write,
2724 .mpo_check_proc_debug = mac_lomac_check_proc_debug,
2725 .mpo_check_proc_sched = mac_lomac_check_proc_sched,
2726 .mpo_check_proc_signal = mac_lomac_check_proc_signal,
2727 .mpo_check_socket_deliver = mac_lomac_check_socket_deliver,
2728 .mpo_check_socket_relabel = mac_lomac_check_socket_relabel,
2729 .mpo_check_socket_visible = mac_lomac_check_socket_visible,
2730 .mpo_check_system_swapon = mac_lomac_check_system_swapon,
2731 .mpo_check_system_sysctl = mac_lomac_check_system_sysctl,
2732 .mpo_check_vnode_access = mac_lomac_check_vnode_open,
2733 .mpo_check_vnode_create = mac_lomac_check_vnode_create,
2734 .mpo_check_vnode_delete = mac_lomac_check_vnode_delete,
2735 .mpo_check_vnode_deleteacl = mac_lomac_check_vnode_deleteacl,
2736 .mpo_check_vnode_link = mac_lomac_check_vnode_link,
2737 .mpo_check_vnode_mmap = mac_lomac_check_vnode_mmap,
2738 .mpo_check_vnode_mmap_downgrade = mac_lomac_check_vnode_mmap_downgrade,
2739 .mpo_check_vnode_mprotect = mac_lomac_check_vnode_mprotect,
2740 .mpo_check_vnode_open = mac_lomac_check_vnode_open,
2741 .mpo_check_vnode_read = mac_lomac_check_vnode_read,
2742 .mpo_check_vnode_relabel = mac_lomac_check_vnode_relabel,
2743 .mpo_check_vnode_rename_from = mac_lomac_check_vnode_rename_from,
2744 .mpo_check_vnode_rename_to = mac_lomac_check_vnode_rename_to,
2745 .mpo_check_vnode_revoke = mac_lomac_check_vnode_revoke,
2746 .mpo_check_vnode_setacl = mac_lomac_check_vnode_setacl,
2747 .mpo_check_vnode_setextattr = mac_lomac_check_vnode_setextattr,
2748 .mpo_check_vnode_setflags = mac_lomac_check_vnode_setflags,
2749 .mpo_check_vnode_setmode = mac_lomac_check_vnode_setmode,
2750 .mpo_check_vnode_setowner = mac_lomac_check_vnode_setowner,
2751 .mpo_check_vnode_setutimes = mac_lomac_check_vnode_setutimes,
2752 .mpo_check_vnode_write = mac_lomac_check_vnode_write,
2753 .mpo_thread_userret = mac_lomac_thread_userret,
2754};
2755
2756MAC_POLICY_SET(&mac_lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC",
2757 MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS,
2758 &mac_lomac_slot);