1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001, 2002, 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 123173 2003-12-06 21:48:03Z 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 pipe *pipe,
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 pipe *pipe,
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_mbuf(struct mbuf *oldmbuf,
1344 struct label *oldmbuflabel, struct mbuf *newmbuf,
1345 struct label *newmbuflabel)
1346{
1347 struct mac_lomac *source, *dest;
1348
1349 source = SLOT(oldmbuflabel);
1350 dest = SLOT(newmbuflabel);
1351
1352 /*
1353 * Because the source mbuf may not yet have been "created",
1354 * just initialized, we do a conditional copy. Since we don't
1355 * allow mbufs to have ranges, do a KASSERT to make sure that
1356 * doesn't happen.
1357 */
1358 KASSERT((source->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0,
1359 ("mac_lomac_create_mbuf_from_mbuf: source mbuf has range"));
1360 mac_lomac_copy(source, dest);
1361}
1362
1363static void
1364mac_lomac_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1365 struct mbuf *mbuf, struct label *mbuflabel)
1366{
1367 struct mac_lomac *dest;
1368
1369 dest = SLOT(mbuflabel);
1370
1371 mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1372}
1373
1374static void
1375mac_lomac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1376 struct mbuf *mbuf, struct label *mbuflabel)
1377{
1378 struct mac_lomac *source, *dest;
1379
1380 source = SLOT(bpflabel);
1381 dest = SLOT(mbuflabel);
1382
1383 mac_lomac_copy_single(source, dest);
1384}
1385
1386static void
1387mac_lomac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1388 struct mbuf *m, struct label *mbuflabel)
1389{
1390 struct mac_lomac *source, *dest;
1391
1392 source = SLOT(ifnetlabel);
1393 dest = SLOT(mbuflabel);
1394
1395 mac_lomac_copy_single(source, dest);
1396}
1397
1398static void
1399mac_lomac_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1400 struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1401 struct mbuf *newmbuf, struct label *newmbuflabel)
1402{
1403 struct mac_lomac *source, *dest;
1404
1405 source = SLOT(oldmbuflabel);
1406 dest = SLOT(newmbuflabel);
1407
1408 mac_lomac_copy_single(source, dest);
1409}
1410
1411static void
1412mac_lomac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
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 int
1424mac_lomac_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1425 struct ipq *ipq, struct label *ipqlabel)
1426{
1427 struct mac_lomac *a, *b;
1428
1429 a = SLOT(ipqlabel);
1430 b = SLOT(fragmentlabel);
1431
1432 return (mac_lomac_equal_single(a, b));
1433}
1434
1435static void
1436mac_lomac_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1437 struct label *ifnetlabel, struct label *newlabel)
1438{
1439 struct mac_lomac *source, *dest;
1440
1441 source = SLOT(newlabel);
1442 dest = SLOT(ifnetlabel);
1443
1444 try_relabel(source, dest);
1445}
1446
1447static void
1448mac_lomac_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1449 struct ipq *ipq, struct label *ipqlabel)
1450{
1451
1452 /* NOOP: we only accept matching labels, so no need to update */
1453}
1454
1455static void
1456mac_lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1457 struct inpcb *inp, struct label *inplabel)
1458{
1459 struct mac_lomac *source, *dest;
1460
1461 source = SLOT(solabel);
1462 dest = SLOT(inplabel);
1463
1464 mac_lomac_copy_single(source, dest);
1465}
1466
1467/*
1468 * Labeling event operations: processes.
1469 */
1470static void
1471mac_lomac_execve_transition(struct ucred *old, struct ucred *new,
1472 struct vnode *vp, struct label *vnodelabel,
1473 struct label *interpvnodelabel, struct image_params *imgp,
1474 struct label *execlabel)
1475{
1476 struct mac_lomac *source, *dest, *obj, *robj;
1477
1478 source = SLOT(old->cr_label);
1479 dest = SLOT(new->cr_label);
1480 obj = SLOT(vnodelabel);
1481 robj = interpvnodelabel != NULL ? SLOT(interpvnodelabel) : obj;
1482
1483 mac_lomac_copy(source, dest);
1484 /*
1485 * If there's an auxiliary label on the real object, respect it
1486 * and assume that this level should be assumed immediately if
1487 * a higher level is currently in place.
1488 */
1489 if (robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
1490 !mac_lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single)
1491 && mac_lomac_auxsingle_in_range(robj, dest))
1492 mac_lomac_set_single(dest, robj->ml_auxsingle.mle_type,
1493 robj->ml_auxsingle.mle_grade);
1494 /*
1495 * Restructuring to use the execve transitioning mechanism
1496 * instead of the normal demotion mechanism here would be
1497 * difficult, so just copy the label over and perform standard
1498 * demotion. This is also non-optimal because it will result
1499 * in the intermediate label "new" being created and immediately
1500 * recycled.
1501 */
1502 if (mac_lomac_enabled && revocation_enabled &&
1503 !mac_lomac_dominate_single(obj, source))
1504 (void)maybe_demote(source, obj, "executing", "file", vp);
1505}
1506
1507static int
1508mac_lomac_execve_will_transition(struct ucred *old, struct vnode *vp,
1509 struct label *vnodelabel, struct label *interpvnodelabel,
1510 struct image_params *imgp, struct label *execlabel)
1511{
1512 struct mac_lomac *subj, *obj, *robj;
1513
1514 if (!mac_lomac_enabled || !revocation_enabled)
1515 return (0);
1516
1517 subj = SLOT(old->cr_label);
1518 obj = SLOT(vnodelabel);
1519 robj = interpvnodelabel != NULL ? SLOT(interpvnodelabel) : obj;
1520
1521 return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
1522 !mac_lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single)
1523 && mac_lomac_auxsingle_in_range(robj, subj)) ||
1524 !mac_lomac_dominate_single(obj, subj));
1525}
1526
1527static void
1528mac_lomac_create_proc0(struct ucred *cred)
1529{
1530 struct mac_lomac *dest;
1531
1532 dest = SLOT(cred->cr_label);
1533
1534 mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1535 mac_lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH,
1536 0);
1537}
1538
1539static void
1540mac_lomac_create_proc1(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_HIGH, 0);
1547 mac_lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH,
1548 0);
1549}
1550
1551static void
1552mac_lomac_relabel_cred(struct ucred *cred, struct label *newlabel)
1553{
1554 struct mac_lomac *source, *dest;
1555
1556 source = SLOT(newlabel);
1557 dest = SLOT(cred->cr_label);
1558
1559 try_relabel(source, dest);
1560}
1561
1562/*
1563 * Access control checks.
1564 */
1565static int
1566mac_lomac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1567 struct ifnet *ifnet, struct label *ifnetlabel)
1568{
1569 struct mac_lomac *a, *b;
1570
1571 if (!mac_lomac_enabled)
1572 return (0);
1573
1574 a = SLOT(bpflabel);
1575 b = SLOT(ifnetlabel);
1576
1577 if (mac_lomac_equal_single(a, b))
1578 return (0);
1579 return (EACCES);
1580}
1581
1582static int
1583mac_lomac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1584{
1585 struct mac_lomac *subj, *new;
1586 int error;
1587
1588 subj = SLOT(cred->cr_label);
1589 new = SLOT(newlabel);
1590
1591 /*
1592 * If there is a LOMAC label update for the credential, it may
1593 * be an update of the single, range, or both.
1594 */
1595 error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1596 if (error)
1597 return (error);
1598
1599 /*
1600 * If the LOMAC label is to be changed, authorize as appropriate.
1601 */
1602 if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1603 /*
1604 * Fill in the missing parts from the previous label.
1605 */
1606 if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1607 mac_lomac_copy_single(subj, new);
1608 if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1609 mac_lomac_copy_range(subj, new);
1610
1611 /*
1612 * To change the LOMAC range on a credential, the new
1613 * range label must be in the current range.
1614 */
1615 if (!mac_lomac_range_in_range(new, subj))
1616 return (EPERM);
1617
1618 /*
1619 * To change the LOMAC single label on a credential, the
1620 * new single label must be in the new range. Implicitly
1621 * from the previous check, the new single is in the old
1622 * range.
1623 */
1624 if (!mac_lomac_single_in_range(new, new))
1625 return (EPERM);
1626
1627 /*
1628 * To have EQUAL in any component of the new credential
1629 * LOMAC label, the subject must already have EQUAL in
1630 * their label.
1631 */
1632 if (mac_lomac_contains_equal(new)) {
1633 error = mac_lomac_subject_privileged(subj);
1634 if (error)
1635 return (error);
1636 }
1637
1638 /*
1639 * XXXMAC: Additional consistency tests regarding the
1640 * single and range of the new label might be performed
1641 * here.
1642 */
1643 }
1644
1645 return (0);
1646}
1647
1648static int
1649mac_lomac_check_cred_visible(struct ucred *u1, struct ucred *u2)
1650{
1651 struct mac_lomac *subj, *obj;
1652
1653 if (!mac_lomac_enabled)
1654 return (0);
1655
1656 subj = SLOT(u1->cr_label);
1657 obj = SLOT(u2->cr_label);
1658
1659 /* XXX: range */
1660 if (!mac_lomac_dominate_single(obj, subj))
1661 return (ESRCH);
1662
1663 return (0);
1664}
1665
1666static int
1667mac_lomac_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1668 struct label *ifnetlabel, struct label *newlabel)
1669{
1670 struct mac_lomac *subj, *new;
1671 int error;
1672
1673 subj = SLOT(cred->cr_label);
1674 new = SLOT(newlabel);
1675
1676 /*
1677 * If there is a LOMAC label update for the interface, it may
1678 * be an update of the single, range, or both.
1679 */
1680 error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1681 if (error)
1682 return (error);
1683
1684 /*
1685 * Relabling network interfaces requires LOMAC privilege.
1686 */
1687 error = mac_lomac_subject_privileged(subj);
1688 if (error)
1689 return (error);
1690
1691 /*
1692 * If the LOMAC label is to be changed, authorize as appropriate.
1693 */
1694 if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1695 /*
1696 * Fill in the missing parts from the previous label.
1697 */
1698 if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1699 mac_lomac_copy_single(subj, new);
1700 if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1701 mac_lomac_copy_range(subj, new);
1702
1703 /*
1704 * Rely on the traditional superuser status for the LOMAC
1705 * interface relabel requirements. XXXMAC: This will go
1706 * away.
1707 */
1708 error = suser_cred(cred, 0);
1709 if (error)
1710 return (EPERM);
1711
1712 /*
1713 * XXXMAC: Additional consistency tests regarding the single
1714 * and the range of the new label might be performed here.
1715 */
1716 }
1717
1718 return (0);
1719}
1720
1721static int
1722mac_lomac_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1723 struct mbuf *m, struct label *mbuflabel)
1724{
1725 struct mac_lomac *p, *i;
1726
1727 if (!mac_lomac_enabled)
1728 return (0);
1729
1730 p = SLOT(mbuflabel);
1731 i = SLOT(ifnetlabel);
1732
1733 return (mac_lomac_single_in_range(p, i) ? 0 : EACCES);
1734}
1735
1736static int
1737mac_lomac_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel,
1738 struct mbuf *m, struct label *mlabel)
1739{
1740 struct mac_lomac *p, *i;
1741
1742 if (!mac_lomac_enabled)
1743 return (0);
1744
1745 p = SLOT(mlabel);
1746 i = SLOT(inplabel);
1747
1748 return (mac_lomac_equal_single(p, i) ? 0 : EACCES);
1749}
1750
1751static int
1752mac_lomac_check_kld_load(struct ucred *cred, struct vnode *vp,
1753 struct label *label)
1754{
1755 struct mac_lomac *subj, *obj;
1756
1757 if (!mac_lomac_enabled)
1758 return (0);
1759
1760 subj = SLOT(cred->cr_label);
1761 obj = SLOT(label);
1762
1763 if (mac_lomac_subject_privileged(subj))
1764 return (EPERM);
1765
1766 if (!mac_lomac_high_single(obj))
1767 return (EACCES);
1768
1769 return (0);
1770}
1771
1772static int
1773mac_lomac_check_kld_unload(struct ucred *cred)
1774{
1775 struct mac_lomac *subj;
1776
1777 if (!mac_lomac_enabled)
1778 return (0);
1779
1780 subj = SLOT(cred->cr_label);
1781
1782 if (mac_lomac_subject_privileged(subj))
1783 return (EPERM);
1784
1785 return (0);
1786}
1787
1788static int
1789mac_lomac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
1790 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1791{
1792
1793 if(!mac_lomac_enabled)
1794 return (0);
1795
1796 /* XXX: This will be implemented soon... */
1797
1798 return (0);
1799}
1800
1801static int
1802mac_lomac_check_pipe_read(struct ucred *cred, struct pipe *pipe,
1803 struct label *pipelabel)
1804{
1805 struct mac_lomac *subj, *obj;
1806
1807 if (!mac_lomac_enabled)
1808 return (0);
1809
1810 subj = SLOT(cred->cr_label);
1811 obj = SLOT((pipelabel));
1812
1813 if (!mac_lomac_dominate_single(obj, subj))
1814 return (maybe_demote(subj, obj, "reading", "pipe", NULL));
1815
1816 return (0);
1817}
1818
1819static int
1820mac_lomac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
1821 struct label *pipelabel, struct label *newlabel)
1822{
1823 struct mac_lomac *subj, *obj, *new;
1824 int error;
1825
1826 new = SLOT(newlabel);
1827 subj = SLOT(cred->cr_label);
1828 obj = SLOT(pipelabel);
1829
1830 /*
1831 * If there is a LOMAC label update for a pipe, it must be a
1832 * single update.
1833 */
1834 error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1835 if (error)
1836 return (error);
1837
1838 /*
1839 * To perform a relabel of a pipe (LOMAC label or not), LOMAC must
1840 * authorize the relabel.
1841 */
1842 if (!mac_lomac_single_in_range(obj, subj))
1843 return (EPERM);
1844
1845 /*
1846 * If the LOMAC label is to be changed, authorize as appropriate.
1847 */
1848 if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1849 /*
1850 * To change the LOMAC label on a pipe, the new pipe label
1851 * must be in the subject range.
1852 */
1853 if (!mac_lomac_single_in_range(new, subj))
1854 return (EPERM);
1855
1856 /*
1857 * To change the LOMAC label on a pipe to be EQUAL, the
1858 * subject must have appropriate privilege.
1859 */
1860 if (mac_lomac_contains_equal(new)) {
1861 error = mac_lomac_subject_privileged(subj);
1862 if (error)
1863 return (error);
1864 }
1865 }
1866
1867 return (0);
1868}
1869
1870static int
1871mac_lomac_check_pipe_write(struct ucred *cred, struct pipe *pipe,
1872 struct label *pipelabel)
1873{
1874 struct mac_lomac *subj, *obj;
1875
1876 if (!mac_lomac_enabled)
1877 return (0);
1878
1879 subj = SLOT(cred->cr_label);
1880 obj = SLOT((pipelabel));
1881
1882 if (!mac_lomac_subject_dominate(subj, obj))
1883 return (EACCES);
1884
1885 return (0);
1886}
1887
1888static int
1889mac_lomac_check_proc_debug(struct ucred *cred, struct proc *proc)
1890{
1891 struct mac_lomac *subj, *obj;
1892
1893 if (!mac_lomac_enabled)
1894 return (0);
1895
1896 subj = SLOT(cred->cr_label);
1897 obj = SLOT(proc->p_ucred->cr_label);
1898
1899 /* XXX: range checks */
1900 if (!mac_lomac_dominate_single(obj, subj))
1901 return (ESRCH);
1902 if (!mac_lomac_subject_dominate(subj, obj))
1903 return (EACCES);
1904
1905 return (0);
1906}
1907
1908static int
1909mac_lomac_check_proc_sched(struct ucred *cred, struct proc *proc)
1910{
1911 struct mac_lomac *subj, *obj;
1912
1913 if (!mac_lomac_enabled)
1914 return (0);
1915
1916 subj = SLOT(cred->cr_label);
1917 obj = SLOT(proc->p_ucred->cr_label);
1918
1919 /* XXX: range checks */
1920 if (!mac_lomac_dominate_single(obj, subj))
1921 return (ESRCH);
1922 if (!mac_lomac_subject_dominate(subj, obj))
1923 return (EACCES);
1924
1925 return (0);
1926}
1927
1928static int
1929mac_lomac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1930{
1931 struct mac_lomac *subj, *obj;
1932
1933 if (!mac_lomac_enabled)
1934 return (0);
1935
1936 subj = SLOT(cred->cr_label);
1937 obj = SLOT(proc->p_ucred->cr_label);
1938
1939 /* XXX: range checks */
1940 if (!mac_lomac_dominate_single(obj, subj))
1941 return (ESRCH);
1942 if (!mac_lomac_subject_dominate(subj, obj))
1943 return (EACCES);
1944
1945 return (0);
1946}
1947
1948static int
1949mac_lomac_check_socket_deliver(struct socket *so, struct label *socketlabel,
1950 struct mbuf *m, struct label *mbuflabel)
1951{
1952 struct mac_lomac *p, *s;
1953
1954 if (!mac_lomac_enabled)
1955 return (0);
1956
1957 p = SLOT(mbuflabel);
1958 s = SLOT(socketlabel);
1959
1960 return (mac_lomac_equal_single(p, s) ? 0 : EACCES);
1961}
1962
1963static int
1964mac_lomac_check_socket_relabel(struct ucred *cred, struct socket *socket,
1965 struct label *socketlabel, struct label *newlabel)
1966{
1967 struct mac_lomac *subj, *obj, *new;
1968 int error;
1969
1970 new = SLOT(newlabel);
1971 subj = SLOT(cred->cr_label);
1972 obj = SLOT(socketlabel);
1973
1974 /*
1975 * If there is a LOMAC label update for the socket, it may be
1976 * an update of single.
1977 */
1978 error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1979 if (error)
1980 return (error);
1981
1982 /*
1983 * To relabel a socket, the old socket single must be in the subject
1984 * range.
1985 */
1986 if (!mac_lomac_single_in_range(obj, subj))
1987 return (EPERM);
1988
1989 /*
1990 * If the LOMAC label is to be changed, authorize as appropriate.
1991 */
1992 if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1993 /*
1994 * To relabel a socket, the new socket single must be in
1995 * the subject range.
1996 */
1997 if (!mac_lomac_single_in_range(new, subj))
1998 return (EPERM);
1999
2000 /*
2001 * To change the LOMAC label on the socket to contain EQUAL,
2002 * the subject must have appropriate privilege.
2003 */
2004 if (mac_lomac_contains_equal(new)) {
2005 error = mac_lomac_subject_privileged(subj);
2006 if (error)
2007 return (error);
2008 }
2009 }
2010
2011 return (0);
2012}
2013
2014static int
2015mac_lomac_check_socket_visible(struct ucred *cred, struct socket *socket,
2016 struct label *socketlabel)
2017{
2018 struct mac_lomac *subj, *obj;
2019
2020 if (!mac_lomac_enabled)
2021 return (0);
2022
2023 subj = SLOT(cred->cr_label);
2024 obj = SLOT(socketlabel);
2025
2026 if (!mac_lomac_dominate_single(obj, subj))
2027 return (ENOENT);
2028
2029 return (0);
2030}
2031
2032static int
2033mac_lomac_check_system_swapon(struct ucred *cred, struct vnode *vp,
2034 struct label *label)
2035{
2036 struct mac_lomac *subj, *obj;
2037
2038 if (!mac_lomac_enabled)
2039 return (0);
2040
2041 subj = SLOT(cred->cr_label);
2042 obj = SLOT(label);
2043
2044 if (mac_lomac_subject_privileged(subj))
2045 return (EPERM);
2046
2047 if (!mac_lomac_high_single(obj))
2048 return (EACCES);
2049
2050 return (0);
2051}
2052
2053static int
2054mac_lomac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2055 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2056{
2057 struct mac_lomac *subj;
2058
2059 if (!mac_lomac_enabled)
2060 return (0);
2061
2062 subj = SLOT(cred->cr_label);
2063
2064 /*
2065 * In general, treat sysctl variables as lomac/high, but also
2066 * require privilege to change them, since they are a
2067 * communications channel between grades. Exempt MIB
2068 * queries from this due to undocmented sysctl magic.
2069 * XXXMAC: This probably requires some more review.
2070 */
2071 if (new != NULL) {
2072 if (namelen > 0 && name[0] == 0)
2073 return (0);
2074
2075#ifdef notdef
2076 if (!mac_lomac_subject_dominate_high(subj))
2077 return (EACCES);
2078#endif
2079
2080 if (mac_lomac_subject_privileged(subj))
2081 return (EPERM);
2082 }
2083
2084 return (0);
2085}
2086
2087static int
2088mac_lomac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2089 struct label *dlabel, struct componentname *cnp, struct vattr *vap)
2090{
2091 struct mac_lomac *subj, *obj;
2092
2093 if (!mac_lomac_enabled)
2094 return (0);
2095
2096 subj = SLOT(cred->cr_label);
2097 obj = SLOT(dlabel);
2098
2099 if (!mac_lomac_subject_dominate(subj, obj))
2100 return (EACCES);
2101 if (obj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2102 !mac_lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle))
2103 return (EACCES);
2104
2105 return (0);
2106}
2107
2108static int
2109mac_lomac_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
2110 struct label *dlabel, struct vnode *vp, struct label *label,
2111 struct componentname *cnp)
2112{
2113 struct mac_lomac *subj, *obj;
2114
2115 if (!mac_lomac_enabled)
2116 return (0);
2117
2118 subj = SLOT(cred->cr_label);
2119 obj = SLOT(dlabel);
2120
2121 if (!mac_lomac_subject_dominate(subj, obj))
2122 return (EACCES);
2123
2124 obj = SLOT(label);
2125
2126 if (!mac_lomac_subject_dominate(subj, obj))
2127 return (EACCES);
2128
2129 return (0);
2130}
2131
2132static int
2133mac_lomac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2134 struct label *label, acl_type_t type)
2135{
2136 struct mac_lomac *subj, *obj;
2137
2138 if (!mac_lomac_enabled)
2139 return (0);
2140
2141 subj = SLOT(cred->cr_label);
2142 obj = SLOT(label);
2143
2144 if (!mac_lomac_subject_dominate(subj, obj))
2145 return (EACCES);
2146
2147 return (0);
2148}
2149
2150static int
2151mac_lomac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2152 struct label *dlabel, struct vnode *vp, struct label *label,
2153 struct componentname *cnp)
2154{
2155 struct mac_lomac *subj, *obj;
2156
2157 if (!mac_lomac_enabled)
2158 return (0);
2159
2160 subj = SLOT(cred->cr_label);
2161 obj = SLOT(dlabel);
2162
2163 if (!mac_lomac_subject_dominate(subj, obj))
2164 return (EACCES);
2165
2166 obj = SLOT(label);
2167
2168 if (!mac_lomac_subject_dominate(subj, obj))
2169 return (EACCES);
2170
2171 return (0);
2172}
2173
2174static int
2175mac_lomac_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2176 struct label *label, int prot)
2177{
2178 struct mac_lomac *subj, *obj;
2179
2180 /*
2181 * Rely on the use of open()-time protections to handle
2182 * non-revocation cases.
2183 */
2184 if (!mac_lomac_enabled)
2185 return (0);
2186
2187 subj = SLOT(cred->cr_label);
2188 obj = SLOT(label);
2189
2190 if (prot & VM_PROT_WRITE) {
2191 if (!mac_lomac_subject_dominate(subj, obj))
2192 return (EACCES);
2193 }
2194 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2195 if (!mac_lomac_dominate_single(obj, subj))
2196 return (maybe_demote(subj, obj, "mapping", "file", vp));
2197 }
2198
2199 return (0);
2200}
2201
2202static int
2203mac_lomac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp,
2204 struct label *label, int prot)
2205{
2206 struct mac_lomac *subj, *obj;
2207
2208 /*
2209 * Rely on the use of open()-time protections to handle
2210 * non-revocation cases.
2211 */
2212 if (!mac_lomac_enabled || !revocation_enabled)
2213 return (0);
2214
2215 subj = SLOT(cred->cr_label);
2216 obj = SLOT(label);
2217
2218 if (prot & VM_PROT_WRITE) {
2219 if (!mac_lomac_subject_dominate(subj, obj))
2220 return (EACCES);
2221 }
2222 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2223 if (!mac_lomac_dominate_single(obj, subj))
2224 return (EACCES);
2225 }
2226
2227 return (0);
2228}
2229
2230static void
2231mac_lomac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp,
2232 struct label *label, /* XXX vm_prot_t */ int *prot)
2233{
2234 struct mac_lomac *subj, *obj;
2235
2236 /*
2237 * Rely on the use of open()-time protections to handle
2238 * non-revocation cases.
2239 */
2240 if (!mac_lomac_enabled || !revocation_enabled)
2241 return;
2242
2243 subj = SLOT(cred->cr_label);
2244 obj = SLOT(label);
2245
2246 if (!mac_lomac_subject_dominate(subj, obj))
2247 *prot &= ~VM_PROT_WRITE;
2248}
2249
2250static int
2251mac_lomac_check_vnode_open(struct ucred *cred, struct vnode *vp,
2252 struct label *vnodelabel, int acc_mode)
2253{
2254 struct mac_lomac *subj, *obj;
2255
2256 if (!mac_lomac_enabled)
2257 return (0);
2258
2259 subj = SLOT(cred->cr_label);
2260 obj = SLOT(vnodelabel);
2261
2262 /* XXX privilege override for admin? */
2263 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2264 if (!mac_lomac_subject_dominate(subj, obj))
2265 return (EACCES);
2266 }
2267
2268 return (0);
2269}
2270
2271static int
2272mac_lomac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2273 struct vnode *vp, struct label *label)
2274{
2275 struct mac_lomac *subj, *obj;
2276
2277 if (!mac_lomac_enabled || !revocation_enabled)
2278 return (0);
2279
2280 subj = SLOT(active_cred->cr_label);
2281 obj = SLOT(label);
2282
2283 if (!mac_lomac_dominate_single(obj, subj))
2284 return (maybe_demote(subj, obj, "reading", "file", vp));
2285
2286 return (0);
2287}
2288
2289static int
2290mac_lomac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2291 struct label *vnodelabel, struct label *newlabel)
2292{
2293 struct mac_lomac *old, *new, *subj;
2294 int error;
2295
2296 old = SLOT(vnodelabel);
2297 new = SLOT(newlabel);
2298 subj = SLOT(cred->cr_label);
2299
2300 /*
2301 * If there is a LOMAC label update for the vnode, it must be a
2302 * single label, with an optional explicit auxiliary single.
2303 */
2304 error = lomac_atmostflags(new,
2305 MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX);
2306 if (error)
2307 return (error);
2308
2309 /*
2310 * To perform a relabel of the vnode (LOMAC label or not), LOMAC must
2311 * authorize the relabel.
2312 */
2313 if (!mac_lomac_single_in_range(old, subj))
2314 return (EPERM);
2315
2316 /*
2317 * If the LOMAC label is to be changed, authorize as appropriate.
2318 */
2319 if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2320 /*
2321 * To change the LOMAC label on a vnode, the new vnode label
2322 * must be in the subject range.
2323 */
2324 if (!mac_lomac_single_in_range(new, subj))
2325 return (EPERM);
2326
2327 /*
2328 * To change the LOMAC label on the vnode to be EQUAL,
2329 * the subject must have appropriate privilege.
2330 */
2331 if (mac_lomac_contains_equal(new)) {
2332 error = mac_lomac_subject_privileged(subj);
2333 if (error)
2334 return (error);
2335 }
2336 }
2337 if (new->ml_flags & MAC_LOMAC_FLAG_AUX) {
2338 /*
2339 * Fill in the missing parts from the previous label.
2340 */
2341 if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
2342 mac_lomac_copy_single(subj, new);
2343
2344 /*
2345 * To change the auxiliary LOMAC label on a vnode, the new
2346 * vnode label must be in the subject range.
2347 */
2348 if (!mac_lomac_auxsingle_in_range(new, subj))
2349 return (EPERM);
2350
2351 /*
2352 * To change the auxiliary LOMAC label on the vnode to be
2353 * EQUAL, the subject must have appropriate privilege.
2354 */
2355 if (mac_lomac_contains_equal(new)) {
2356 error = mac_lomac_subject_privileged(subj);
2357 if (error)
2358 return (error);
2359 }
2360 }
2361
2362 return (0);
2363}
2364
2365static int
2366mac_lomac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2367 struct label *dlabel, struct vnode *vp, struct label *label,
2368 struct componentname *cnp)
2369{
2370 struct mac_lomac *subj, *obj;
2371
2372 if (!mac_lomac_enabled)
2373 return (0);
2374
2375 subj = SLOT(cred->cr_label);
2376 obj = SLOT(dlabel);
2377
2378 if (!mac_lomac_subject_dominate(subj, obj))
2379 return (EACCES);
2380
2381 obj = SLOT(label);
2382
2383 if (!mac_lomac_subject_dominate(subj, obj))
2384 return (EACCES);
2385
2386 return (0);
2387}
2388
2389static int
2390mac_lomac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2391 struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2392 struct componentname *cnp)
2393{
2394 struct mac_lomac *subj, *obj;
2395
2396 if (!mac_lomac_enabled)
2397 return (0);
2398
2399 subj = SLOT(cred->cr_label);
2400 obj = SLOT(dlabel);
2401
2402 if (!mac_lomac_subject_dominate(subj, obj))
2403 return (EACCES);
2404
2405 if (vp != NULL) {
2406 obj = SLOT(label);
2407
2408 if (!mac_lomac_subject_dominate(subj, obj))
2409 return (EACCES);
2410 }
2411
2412 return (0);
2413}
2414
2415static int
2416mac_lomac_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2417 struct label *label)
2418{
2419 struct mac_lomac *subj, *obj;
2420
2421 if (!mac_lomac_enabled)
2422 return (0);
2423
2424 subj = SLOT(cred->cr_label);
2425 obj = SLOT(label);
2426
2427 if (!mac_lomac_subject_dominate(subj, obj))
2428 return (EACCES);
2429
2430 return (0);
2431}
2432
2433static int
2434mac_lomac_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2435 struct label *label, acl_type_t type, struct acl *acl)
2436{
2437 struct mac_lomac *subj, *obj;
2438
2439 if (!mac_lomac_enabled)
2440 return (0);
2441
2442 subj = SLOT(cred->cr_label);
2443 obj = SLOT(label);
2444
2445 if (!mac_lomac_subject_dominate(subj, obj))
2446 return (EACCES);
2447
2448 return (0);
2449}
2450
2451static int
2452mac_lomac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2453 struct label *vnodelabel, int attrnamespace, const char *name,
2454 struct uio *uio)
2455{
2456 struct mac_lomac *subj, *obj;
2457
2458 if (!mac_lomac_enabled)
2459 return (0);
2460
2461 subj = SLOT(cred->cr_label);
2462 obj = SLOT(vnodelabel);
2463
2464 if (!mac_lomac_subject_dominate(subj, obj))
2465 return (EACCES);
2466
2467 /* XXX: protect the MAC EA in a special way? */
2468
2469 return (0);
2470}
2471
2472static int
2473mac_lomac_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2474 struct label *vnodelabel, u_long flags)
2475{
2476 struct mac_lomac *subj, *obj;
2477
2478 if (!mac_lomac_enabled)
2479 return (0);
2480
2481 subj = SLOT(cred->cr_label);
2482 obj = SLOT(vnodelabel);
2483
2484 if (!mac_lomac_subject_dominate(subj, obj))
2485 return (EACCES);
2486
2487 return (0);
2488}
2489
2490static int
2491mac_lomac_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2492 struct label *vnodelabel, mode_t mode)
2493{
2494 struct mac_lomac *subj, *obj;
2495
2496 if (!mac_lomac_enabled)
2497 return (0);
2498
2499 subj = SLOT(cred->cr_label);
2500 obj = SLOT(vnodelabel);
2501
2502 if (!mac_lomac_subject_dominate(subj, obj))
2503 return (EACCES);
2504
2505 return (0);
2506}
2507
2508static int
2509mac_lomac_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2510 struct label *vnodelabel, uid_t uid, gid_t gid)
2511{
2512 struct mac_lomac *subj, *obj;
2513
2514 if (!mac_lomac_enabled)
2515 return (0);
2516
2517 subj = SLOT(cred->cr_label);
2518 obj = SLOT(vnodelabel);
2519
2520 if (!mac_lomac_subject_dominate(subj, obj))
2521 return (EACCES);
2522
2523 return (0);
2524}
2525
2526static int
2527mac_lomac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2528 struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2529{
2530 struct mac_lomac *subj, *obj;
2531
2532 if (!mac_lomac_enabled)
2533 return (0);
2534
2535 subj = SLOT(cred->cr_label);
2536 obj = SLOT(vnodelabel);
2537
2538 if (!mac_lomac_subject_dominate(subj, obj))
2539 return (EACCES);
2540
2541 return (0);
2542}
2543
2544static int
2545mac_lomac_check_vnode_write(struct ucred *active_cred,
2546 struct ucred *file_cred, struct vnode *vp, struct label *label)
2547{
2548 struct mac_lomac *subj, *obj;
2549
2550 if (!mac_lomac_enabled || !revocation_enabled)
2551 return (0);
2552
2553 subj = SLOT(active_cred->cr_label);
2554 obj = SLOT(label);
2555
2556 if (!mac_lomac_subject_dominate(subj, obj))
2557 return (EACCES);
2558
2559 return (0);
2560}
2561
2562static void
2563mac_lomac_thread_userret(struct thread *td)
2564{
2565 struct proc *p = td->td_proc;
2566 struct mac_lomac_proc *subj = PSLOT(p->p_label);
2567 struct ucred *newcred, *oldcred;
2568 int dodrop;
2569
2570 mtx_lock(&subj->mtx);
2571 if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
2572 dodrop = 0;
2573 mtx_unlock(&subj->mtx);
2574 newcred = crget();
2575 /*
2576 * Prevent a lock order reversal in
2577 * mac_cred_mmapped_drop_perms; ideally, the other
2578 * user of subj->mtx wouldn't be holding Giant.
2579 */
2580 mtx_lock(&Giant);
2581 PROC_LOCK(p);
2582 mtx_lock(&subj->mtx);
2583 /*
2584 * Check if we lost the race while allocating the cred.
2585 */
2586 if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) {
2587 crfree(newcred);
2588 goto out;
2589 }
2590 oldcred = p->p_ucred;
2591 crcopy(newcred, oldcred);
2592 crhold(newcred);
2593 mac_lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label));
2594 p->p_ucred = newcred;
2595 crfree(oldcred);
2596 dodrop = 1;
2597 out:
2598 mtx_unlock(&subj->mtx);
2599 PROC_UNLOCK(p);
2600 if (dodrop)
2601 mac_cred_mmapped_drop_perms(curthread, newcred);
2602 mtx_unlock(&Giant);
2603 } else {
2604 mtx_unlock(&subj->mtx);
2605 }
2606}
2607
2608static struct mac_policy_ops mac_lomac_ops =
2609{
2610 .mpo_init = mac_lomac_init,
2611 .mpo_init_bpfdesc_label = mac_lomac_init_label,
2612 .mpo_init_cred_label = mac_lomac_init_label,
2613 .mpo_init_devfsdirent_label = mac_lomac_init_label,
2614 .mpo_init_ifnet_label = mac_lomac_init_label,
2615 .mpo_init_inpcb_label = mac_lomac_init_label_waitcheck,
2616 .mpo_init_ipq_label = mac_lomac_init_label_waitcheck,
2617 .mpo_init_mbuf_label = mac_lomac_init_label_waitcheck,
2618 .mpo_init_mount_label = mac_lomac_init_label,
2619 .mpo_init_mount_fs_label = mac_lomac_init_label,
2620 .mpo_init_pipe_label = mac_lomac_init_label,
2621 .mpo_init_proc_label = mac_lomac_init_proc_label,
2622 .mpo_init_socket_label = mac_lomac_init_label_waitcheck,
2623 .mpo_init_socket_peer_label = mac_lomac_init_label_waitcheck,
2624 .mpo_init_vnode_label = mac_lomac_init_label,
2625 .mpo_destroy_bpfdesc_label = mac_lomac_destroy_label,
2626 .mpo_destroy_cred_label = mac_lomac_destroy_label,
2627 .mpo_destroy_devfsdirent_label = mac_lomac_destroy_label,
2628 .mpo_destroy_ifnet_label = mac_lomac_destroy_label,
2629 .mpo_destroy_inpcb_label = mac_lomac_destroy_label,
2630 .mpo_destroy_ipq_label = mac_lomac_destroy_label,
2631 .mpo_destroy_mbuf_label = mac_lomac_destroy_label,
2632 .mpo_destroy_mount_label = mac_lomac_destroy_label,
2633 .mpo_destroy_mount_fs_label = mac_lomac_destroy_label,
2634 .mpo_destroy_pipe_label = mac_lomac_destroy_label,
2635 .mpo_destroy_proc_label = mac_lomac_destroy_proc_label,
2636 .mpo_destroy_socket_label = mac_lomac_destroy_label,
2637 .mpo_destroy_socket_peer_label = mac_lomac_destroy_label,
2638 .mpo_destroy_vnode_label = mac_lomac_destroy_label,
2639 .mpo_copy_cred_label = mac_lomac_copy_label,
2640 .mpo_copy_mbuf_label = mac_lomac_copy_label,
2641 .mpo_copy_pipe_label = mac_lomac_copy_label,
2642 .mpo_copy_socket_label = mac_lomac_copy_label,
2643 .mpo_copy_vnode_label = mac_lomac_copy_label,
2644 .mpo_externalize_cred_label = mac_lomac_externalize_label,
2645 .mpo_externalize_ifnet_label = mac_lomac_externalize_label,
2646 .mpo_externalize_pipe_label = mac_lomac_externalize_label,
2647 .mpo_externalize_socket_label = mac_lomac_externalize_label,
2648 .mpo_externalize_socket_peer_label = mac_lomac_externalize_label,
2649 .mpo_externalize_vnode_label = mac_lomac_externalize_label,
2650 .mpo_internalize_cred_label = mac_lomac_internalize_label,
2651 .mpo_internalize_ifnet_label = mac_lomac_internalize_label,
2652 .mpo_internalize_pipe_label = mac_lomac_internalize_label,
2653 .mpo_internalize_socket_label = mac_lomac_internalize_label,
2654 .mpo_internalize_vnode_label = mac_lomac_internalize_label,
2655 .mpo_create_devfs_device = mac_lomac_create_devfs_device,
2656 .mpo_create_devfs_directory = mac_lomac_create_devfs_directory,
2657 .mpo_create_devfs_symlink = mac_lomac_create_devfs_symlink,
2658 .mpo_create_mount = mac_lomac_create_mount,
2659 .mpo_create_root_mount = mac_lomac_create_root_mount,
2660 .mpo_relabel_vnode = mac_lomac_relabel_vnode,
2661 .mpo_update_devfsdirent = mac_lomac_update_devfsdirent,
2662 .mpo_associate_vnode_devfs = mac_lomac_associate_vnode_devfs,
2663 .mpo_associate_vnode_extattr = mac_lomac_associate_vnode_extattr,
2664 .mpo_associate_vnode_singlelabel =
2665 mac_lomac_associate_vnode_singlelabel,
2666 .mpo_create_vnode_extattr = mac_lomac_create_vnode_extattr,
2667 .mpo_setlabel_vnode_extattr = mac_lomac_setlabel_vnode_extattr,
2668 .mpo_create_mbuf_from_socket = mac_lomac_create_mbuf_from_socket,
2669 .mpo_create_pipe = mac_lomac_create_pipe,
2670 .mpo_create_socket = mac_lomac_create_socket,
2671 .mpo_create_socket_from_socket = mac_lomac_create_socket_from_socket,
2672 .mpo_relabel_pipe = mac_lomac_relabel_pipe,
2673 .mpo_relabel_socket = mac_lomac_relabel_socket,
2674 .mpo_set_socket_peer_from_mbuf = mac_lomac_set_socket_peer_from_mbuf,
2675 .mpo_set_socket_peer_from_socket =
2676 mac_lomac_set_socket_peer_from_socket,
2677 .mpo_create_bpfdesc = mac_lomac_create_bpfdesc,
2678 .mpo_create_datagram_from_ipq = mac_lomac_create_datagram_from_ipq,
2679 .mpo_create_fragment = mac_lomac_create_fragment,
2680 .mpo_create_ifnet = mac_lomac_create_ifnet,
2681 .mpo_create_inpcb_from_socket = mac_lomac_create_inpcb_from_socket,
2682 .mpo_create_ipq = mac_lomac_create_ipq,
2683 .mpo_create_mbuf_from_mbuf = mac_lomac_create_mbuf_from_mbuf,
2684 .mpo_create_mbuf_linklayer = mac_lomac_create_mbuf_linklayer,
2685 .mpo_create_mbuf_from_bpfdesc = mac_lomac_create_mbuf_from_bpfdesc,
2686 .mpo_create_mbuf_from_ifnet = mac_lomac_create_mbuf_from_ifnet,
2687 .mpo_create_mbuf_multicast_encap =
2688 mac_lomac_create_mbuf_multicast_encap,
2689 .mpo_create_mbuf_netlayer = mac_lomac_create_mbuf_netlayer,
2690 .mpo_fragment_match = mac_lomac_fragment_match,
2691 .mpo_relabel_ifnet = mac_lomac_relabel_ifnet,
2692 .mpo_update_ipq = mac_lomac_update_ipq,
2693 .mpo_inpcb_sosetlabel = mac_lomac_inpcb_sosetlabel,
2694 .mpo_execve_transition = mac_lomac_execve_transition,
2695 .mpo_execve_will_transition = mac_lomac_execve_will_transition,
2696 .mpo_create_proc0 = mac_lomac_create_proc0,
2697 .mpo_create_proc1 = mac_lomac_create_proc1,
2698 .mpo_relabel_cred = mac_lomac_relabel_cred,
2699 .mpo_check_bpfdesc_receive = mac_lomac_check_bpfdesc_receive,
2700 .mpo_check_cred_relabel = mac_lomac_check_cred_relabel,
2701 .mpo_check_cred_visible = mac_lomac_check_cred_visible,
2702 .mpo_check_ifnet_relabel = mac_lomac_check_ifnet_relabel,
2703 .mpo_check_ifnet_transmit = mac_lomac_check_ifnet_transmit,
2704 .mpo_check_inpcb_deliver = mac_lomac_check_inpcb_deliver,
2705 .mpo_check_kld_load = mac_lomac_check_kld_load,
2706 .mpo_check_kld_unload = mac_lomac_check_kld_unload,
2707 .mpo_check_pipe_ioctl = mac_lomac_check_pipe_ioctl,
2708 .mpo_check_pipe_read = mac_lomac_check_pipe_read,
2709 .mpo_check_pipe_relabel = mac_lomac_check_pipe_relabel,
2710 .mpo_check_pipe_write = mac_lomac_check_pipe_write,
2711 .mpo_check_proc_debug = mac_lomac_check_proc_debug,
2712 .mpo_check_proc_sched = mac_lomac_check_proc_sched,
2713 .mpo_check_proc_signal = mac_lomac_check_proc_signal,
2714 .mpo_check_socket_deliver = mac_lomac_check_socket_deliver,
2715 .mpo_check_socket_relabel = mac_lomac_check_socket_relabel,
2716 .mpo_check_socket_visible = mac_lomac_check_socket_visible,
2717 .mpo_check_system_swapon = mac_lomac_check_system_swapon,
2718 .mpo_check_system_sysctl = mac_lomac_check_system_sysctl,
2719 .mpo_check_vnode_access = mac_lomac_check_vnode_open,
2720 .mpo_check_vnode_create = mac_lomac_check_vnode_create,
2721 .mpo_check_vnode_delete = mac_lomac_check_vnode_delete,
2722 .mpo_check_vnode_deleteacl = mac_lomac_check_vnode_deleteacl,
2723 .mpo_check_vnode_link = mac_lomac_check_vnode_link,
2724 .mpo_check_vnode_mmap = mac_lomac_check_vnode_mmap,
2725 .mpo_check_vnode_mmap_downgrade = mac_lomac_check_vnode_mmap_downgrade,
2726 .mpo_check_vnode_mprotect = mac_lomac_check_vnode_mprotect,
2727 .mpo_check_vnode_open = mac_lomac_check_vnode_open,
2728 .mpo_check_vnode_read = mac_lomac_check_vnode_read,
2729 .mpo_check_vnode_relabel = mac_lomac_check_vnode_relabel,
2730 .mpo_check_vnode_rename_from = mac_lomac_check_vnode_rename_from,
2731 .mpo_check_vnode_rename_to = mac_lomac_check_vnode_rename_to,
2732 .mpo_check_vnode_revoke = mac_lomac_check_vnode_revoke,
2733 .mpo_check_vnode_setacl = mac_lomac_check_vnode_setacl,
2734 .mpo_check_vnode_setextattr = mac_lomac_check_vnode_setextattr,
2735 .mpo_check_vnode_setflags = mac_lomac_check_vnode_setflags,
2736 .mpo_check_vnode_setmode = mac_lomac_check_vnode_setmode,
2737 .mpo_check_vnode_setowner = mac_lomac_check_vnode_setowner,
2738 .mpo_check_vnode_setutimes = mac_lomac_check_vnode_setutimes,
2739 .mpo_check_vnode_write = mac_lomac_check_vnode_write,
2740 .mpo_thread_userret = mac_lomac_thread_userret,
2741};
2742
2743MAC_POLICY_SET(&mac_lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC",
2744 MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS,
2745 &mac_lomac_slot);
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001, 2002, 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 123173 2003-12-06 21:48:03Z 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 pipe *pipe,
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 pipe *pipe,
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_mbuf(struct mbuf *oldmbuf,
1344 struct label *oldmbuflabel, struct mbuf *newmbuf,
1345 struct label *newmbuflabel)
1346{
1347 struct mac_lomac *source, *dest;
1348
1349 source = SLOT(oldmbuflabel);
1350 dest = SLOT(newmbuflabel);
1351
1352 /*
1353 * Because the source mbuf may not yet have been "created",
1354 * just initialized, we do a conditional copy. Since we don't
1355 * allow mbufs to have ranges, do a KASSERT to make sure that
1356 * doesn't happen.
1357 */
1358 KASSERT((source->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0,
1359 ("mac_lomac_create_mbuf_from_mbuf: source mbuf has range"));
1360 mac_lomac_copy(source, dest);
1361}
1362
1363static void
1364mac_lomac_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1365 struct mbuf *mbuf, struct label *mbuflabel)
1366{
1367 struct mac_lomac *dest;
1368
1369 dest = SLOT(mbuflabel);
1370
1371 mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1372}
1373
1374static void
1375mac_lomac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1376 struct mbuf *mbuf, struct label *mbuflabel)
1377{
1378 struct mac_lomac *source, *dest;
1379
1380 source = SLOT(bpflabel);
1381 dest = SLOT(mbuflabel);
1382
1383 mac_lomac_copy_single(source, dest);
1384}
1385
1386static void
1387mac_lomac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1388 struct mbuf *m, struct label *mbuflabel)
1389{
1390 struct mac_lomac *source, *dest;
1391
1392 source = SLOT(ifnetlabel);
1393 dest = SLOT(mbuflabel);
1394
1395 mac_lomac_copy_single(source, dest);
1396}
1397
1398static void
1399mac_lomac_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1400 struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1401 struct mbuf *newmbuf, struct label *newmbuflabel)
1402{
1403 struct mac_lomac *source, *dest;
1404
1405 source = SLOT(oldmbuflabel);
1406 dest = SLOT(newmbuflabel);
1407
1408 mac_lomac_copy_single(source, dest);
1409}
1410
1411static void
1412mac_lomac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
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 int
1424mac_lomac_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1425 struct ipq *ipq, struct label *ipqlabel)
1426{
1427 struct mac_lomac *a, *b;
1428
1429 a = SLOT(ipqlabel);
1430 b = SLOT(fragmentlabel);
1431
1432 return (mac_lomac_equal_single(a, b));
1433}
1434
1435static void
1436mac_lomac_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1437 struct label *ifnetlabel, struct label *newlabel)
1438{
1439 struct mac_lomac *source, *dest;
1440
1441 source = SLOT(newlabel);
1442 dest = SLOT(ifnetlabel);
1443
1444 try_relabel(source, dest);
1445}
1446
1447static void
1448mac_lomac_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1449 struct ipq *ipq, struct label *ipqlabel)
1450{
1451
1452 /* NOOP: we only accept matching labels, so no need to update */
1453}
1454
1455static void
1456mac_lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1457 struct inpcb *inp, struct label *inplabel)
1458{
1459 struct mac_lomac *source, *dest;
1460
1461 source = SLOT(solabel);
1462 dest = SLOT(inplabel);
1463
1464 mac_lomac_copy_single(source, dest);
1465}
1466
1467/*
1468 * Labeling event operations: processes.
1469 */
1470static void
1471mac_lomac_execve_transition(struct ucred *old, struct ucred *new,
1472 struct vnode *vp, struct label *vnodelabel,
1473 struct label *interpvnodelabel, struct image_params *imgp,
1474 struct label *execlabel)
1475{
1476 struct mac_lomac *source, *dest, *obj, *robj;
1477
1478 source = SLOT(old->cr_label);
1479 dest = SLOT(new->cr_label);
1480 obj = SLOT(vnodelabel);
1481 robj = interpvnodelabel != NULL ? SLOT(interpvnodelabel) : obj;
1482
1483 mac_lomac_copy(source, dest);
1484 /*
1485 * If there's an auxiliary label on the real object, respect it
1486 * and assume that this level should be assumed immediately if
1487 * a higher level is currently in place.
1488 */
1489 if (robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
1490 !mac_lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single)
1491 && mac_lomac_auxsingle_in_range(robj, dest))
1492 mac_lomac_set_single(dest, robj->ml_auxsingle.mle_type,
1493 robj->ml_auxsingle.mle_grade);
1494 /*
1495 * Restructuring to use the execve transitioning mechanism
1496 * instead of the normal demotion mechanism here would be
1497 * difficult, so just copy the label over and perform standard
1498 * demotion. This is also non-optimal because it will result
1499 * in the intermediate label "new" being created and immediately
1500 * recycled.
1501 */
1502 if (mac_lomac_enabled && revocation_enabled &&
1503 !mac_lomac_dominate_single(obj, source))
1504 (void)maybe_demote(source, obj, "executing", "file", vp);
1505}
1506
1507static int
1508mac_lomac_execve_will_transition(struct ucred *old, struct vnode *vp,
1509 struct label *vnodelabel, struct label *interpvnodelabel,
1510 struct image_params *imgp, struct label *execlabel)
1511{
1512 struct mac_lomac *subj, *obj, *robj;
1513
1514 if (!mac_lomac_enabled || !revocation_enabled)
1515 return (0);
1516
1517 subj = SLOT(old->cr_label);
1518 obj = SLOT(vnodelabel);
1519 robj = interpvnodelabel != NULL ? SLOT(interpvnodelabel) : obj;
1520
1521 return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
1522 !mac_lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single)
1523 && mac_lomac_auxsingle_in_range(robj, subj)) ||
1524 !mac_lomac_dominate_single(obj, subj));
1525}
1526
1527static void
1528mac_lomac_create_proc0(struct ucred *cred)
1529{
1530 struct mac_lomac *dest;
1531
1532 dest = SLOT(cred->cr_label);
1533
1534 mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1535 mac_lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH,
1536 0);
1537}
1538
1539static void
1540mac_lomac_create_proc1(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_HIGH, 0);
1547 mac_lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH,
1548 0);
1549}
1550
1551static void
1552mac_lomac_relabel_cred(struct ucred *cred, struct label *newlabel)
1553{
1554 struct mac_lomac *source, *dest;
1555
1556 source = SLOT(newlabel);
1557 dest = SLOT(cred->cr_label);
1558
1559 try_relabel(source, dest);
1560}
1561
1562/*
1563 * Access control checks.
1564 */
1565static int
1566mac_lomac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1567 struct ifnet *ifnet, struct label *ifnetlabel)
1568{
1569 struct mac_lomac *a, *b;
1570
1571 if (!mac_lomac_enabled)
1572 return (0);
1573
1574 a = SLOT(bpflabel);
1575 b = SLOT(ifnetlabel);
1576
1577 if (mac_lomac_equal_single(a, b))
1578 return (0);
1579 return (EACCES);
1580}
1581
1582static int
1583mac_lomac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1584{
1585 struct mac_lomac *subj, *new;
1586 int error;
1587
1588 subj = SLOT(cred->cr_label);
1589 new = SLOT(newlabel);
1590
1591 /*
1592 * If there is a LOMAC label update for the credential, it may
1593 * be an update of the single, range, or both.
1594 */
1595 error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1596 if (error)
1597 return (error);
1598
1599 /*
1600 * If the LOMAC label is to be changed, authorize as appropriate.
1601 */
1602 if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1603 /*
1604 * Fill in the missing parts from the previous label.
1605 */
1606 if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1607 mac_lomac_copy_single(subj, new);
1608 if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1609 mac_lomac_copy_range(subj, new);
1610
1611 /*
1612 * To change the LOMAC range on a credential, the new
1613 * range label must be in the current range.
1614 */
1615 if (!mac_lomac_range_in_range(new, subj))
1616 return (EPERM);
1617
1618 /*
1619 * To change the LOMAC single label on a credential, the
1620 * new single label must be in the new range. Implicitly
1621 * from the previous check, the new single is in the old
1622 * range.
1623 */
1624 if (!mac_lomac_single_in_range(new, new))
1625 return (EPERM);
1626
1627 /*
1628 * To have EQUAL in any component of the new credential
1629 * LOMAC label, the subject must already have EQUAL in
1630 * their label.
1631 */
1632 if (mac_lomac_contains_equal(new)) {
1633 error = mac_lomac_subject_privileged(subj);
1634 if (error)
1635 return (error);
1636 }
1637
1638 /*
1639 * XXXMAC: Additional consistency tests regarding the
1640 * single and range of the new label might be performed
1641 * here.
1642 */
1643 }
1644
1645 return (0);
1646}
1647
1648static int
1649mac_lomac_check_cred_visible(struct ucred *u1, struct ucred *u2)
1650{
1651 struct mac_lomac *subj, *obj;
1652
1653 if (!mac_lomac_enabled)
1654 return (0);
1655
1656 subj = SLOT(u1->cr_label);
1657 obj = SLOT(u2->cr_label);
1658
1659 /* XXX: range */
1660 if (!mac_lomac_dominate_single(obj, subj))
1661 return (ESRCH);
1662
1663 return (0);
1664}
1665
1666static int
1667mac_lomac_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1668 struct label *ifnetlabel, struct label *newlabel)
1669{
1670 struct mac_lomac *subj, *new;
1671 int error;
1672
1673 subj = SLOT(cred->cr_label);
1674 new = SLOT(newlabel);
1675
1676 /*
1677 * If there is a LOMAC label update for the interface, it may
1678 * be an update of the single, range, or both.
1679 */
1680 error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1681 if (error)
1682 return (error);
1683
1684 /*
1685 * Relabling network interfaces requires LOMAC privilege.
1686 */
1687 error = mac_lomac_subject_privileged(subj);
1688 if (error)
1689 return (error);
1690
1691 /*
1692 * If the LOMAC label is to be changed, authorize as appropriate.
1693 */
1694 if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1695 /*
1696 * Fill in the missing parts from the previous label.
1697 */
1698 if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1699 mac_lomac_copy_single(subj, new);
1700 if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1701 mac_lomac_copy_range(subj, new);
1702
1703 /*
1704 * Rely on the traditional superuser status for the LOMAC
1705 * interface relabel requirements. XXXMAC: This will go
1706 * away.
1707 */
1708 error = suser_cred(cred, 0);
1709 if (error)
1710 return (EPERM);
1711
1712 /*
1713 * XXXMAC: Additional consistency tests regarding the single
1714 * and the range of the new label might be performed here.
1715 */
1716 }
1717
1718 return (0);
1719}
1720
1721static int
1722mac_lomac_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1723 struct mbuf *m, struct label *mbuflabel)
1724{
1725 struct mac_lomac *p, *i;
1726
1727 if (!mac_lomac_enabled)
1728 return (0);
1729
1730 p = SLOT(mbuflabel);
1731 i = SLOT(ifnetlabel);
1732
1733 return (mac_lomac_single_in_range(p, i) ? 0 : EACCES);
1734}
1735
1736static int
1737mac_lomac_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel,
1738 struct mbuf *m, struct label *mlabel)
1739{
1740 struct mac_lomac *p, *i;
1741
1742 if (!mac_lomac_enabled)
1743 return (0);
1744
1745 p = SLOT(mlabel);
1746 i = SLOT(inplabel);
1747
1748 return (mac_lomac_equal_single(p, i) ? 0 : EACCES);
1749}
1750
1751static int
1752mac_lomac_check_kld_load(struct ucred *cred, struct vnode *vp,
1753 struct label *label)
1754{
1755 struct mac_lomac *subj, *obj;
1756
1757 if (!mac_lomac_enabled)
1758 return (0);
1759
1760 subj = SLOT(cred->cr_label);
1761 obj = SLOT(label);
1762
1763 if (mac_lomac_subject_privileged(subj))
1764 return (EPERM);
1765
1766 if (!mac_lomac_high_single(obj))
1767 return (EACCES);
1768
1769 return (0);
1770}
1771
1772static int
1773mac_lomac_check_kld_unload(struct ucred *cred)
1774{
1775 struct mac_lomac *subj;
1776
1777 if (!mac_lomac_enabled)
1778 return (0);
1779
1780 subj = SLOT(cred->cr_label);
1781
1782 if (mac_lomac_subject_privileged(subj))
1783 return (EPERM);
1784
1785 return (0);
1786}
1787
1788static int
1789mac_lomac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
1790 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1791{
1792
1793 if(!mac_lomac_enabled)
1794 return (0);
1795
1796 /* XXX: This will be implemented soon... */
1797
1798 return (0);
1799}
1800
1801static int
1802mac_lomac_check_pipe_read(struct ucred *cred, struct pipe *pipe,
1803 struct label *pipelabel)
1804{
1805 struct mac_lomac *subj, *obj;
1806
1807 if (!mac_lomac_enabled)
1808 return (0);
1809
1810 subj = SLOT(cred->cr_label);
1811 obj = SLOT((pipelabel));
1812
1813 if (!mac_lomac_dominate_single(obj, subj))
1814 return (maybe_demote(subj, obj, "reading", "pipe", NULL));
1815
1816 return (0);
1817}
1818
1819static int
1820mac_lomac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
1821 struct label *pipelabel, struct label *newlabel)
1822{
1823 struct mac_lomac *subj, *obj, *new;
1824 int error;
1825
1826 new = SLOT(newlabel);
1827 subj = SLOT(cred->cr_label);
1828 obj = SLOT(pipelabel);
1829
1830 /*
1831 * If there is a LOMAC label update for a pipe, it must be a
1832 * single update.
1833 */
1834 error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1835 if (error)
1836 return (error);
1837
1838 /*
1839 * To perform a relabel of a pipe (LOMAC label or not), LOMAC must
1840 * authorize the relabel.
1841 */
1842 if (!mac_lomac_single_in_range(obj, subj))
1843 return (EPERM);
1844
1845 /*
1846 * If the LOMAC label is to be changed, authorize as appropriate.
1847 */
1848 if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1849 /*
1850 * To change the LOMAC label on a pipe, the new pipe label
1851 * must be in the subject range.
1852 */
1853 if (!mac_lomac_single_in_range(new, subj))
1854 return (EPERM);
1855
1856 /*
1857 * To change the LOMAC label on a pipe to be EQUAL, the
1858 * subject must have appropriate privilege.
1859 */
1860 if (mac_lomac_contains_equal(new)) {
1861 error = mac_lomac_subject_privileged(subj);
1862 if (error)
1863 return (error);
1864 }
1865 }
1866
1867 return (0);
1868}
1869
1870static int
1871mac_lomac_check_pipe_write(struct ucred *cred, struct pipe *pipe,
1872 struct label *pipelabel)
1873{
1874 struct mac_lomac *subj, *obj;
1875
1876 if (!mac_lomac_enabled)
1877 return (0);
1878
1879 subj = SLOT(cred->cr_label);
1880 obj = SLOT((pipelabel));
1881
1882 if (!mac_lomac_subject_dominate(subj, obj))
1883 return (EACCES);
1884
1885 return (0);
1886}
1887
1888static int
1889mac_lomac_check_proc_debug(struct ucred *cred, struct proc *proc)
1890{
1891 struct mac_lomac *subj, *obj;
1892
1893 if (!mac_lomac_enabled)
1894 return (0);
1895
1896 subj = SLOT(cred->cr_label);
1897 obj = SLOT(proc->p_ucred->cr_label);
1898
1899 /* XXX: range checks */
1900 if (!mac_lomac_dominate_single(obj, subj))
1901 return (ESRCH);
1902 if (!mac_lomac_subject_dominate(subj, obj))
1903 return (EACCES);
1904
1905 return (0);
1906}
1907
1908static int
1909mac_lomac_check_proc_sched(struct ucred *cred, struct proc *proc)
1910{
1911 struct mac_lomac *subj, *obj;
1912
1913 if (!mac_lomac_enabled)
1914 return (0);
1915
1916 subj = SLOT(cred->cr_label);
1917 obj = SLOT(proc->p_ucred->cr_label);
1918
1919 /* XXX: range checks */
1920 if (!mac_lomac_dominate_single(obj, subj))
1921 return (ESRCH);
1922 if (!mac_lomac_subject_dominate(subj, obj))
1923 return (EACCES);
1924
1925 return (0);
1926}
1927
1928static int
1929mac_lomac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1930{
1931 struct mac_lomac *subj, *obj;
1932
1933 if (!mac_lomac_enabled)
1934 return (0);
1935
1936 subj = SLOT(cred->cr_label);
1937 obj = SLOT(proc->p_ucred->cr_label);
1938
1939 /* XXX: range checks */
1940 if (!mac_lomac_dominate_single(obj, subj))
1941 return (ESRCH);
1942 if (!mac_lomac_subject_dominate(subj, obj))
1943 return (EACCES);
1944
1945 return (0);
1946}
1947
1948static int
1949mac_lomac_check_socket_deliver(struct socket *so, struct label *socketlabel,
1950 struct mbuf *m, struct label *mbuflabel)
1951{
1952 struct mac_lomac *p, *s;
1953
1954 if (!mac_lomac_enabled)
1955 return (0);
1956
1957 p = SLOT(mbuflabel);
1958 s = SLOT(socketlabel);
1959
1960 return (mac_lomac_equal_single(p, s) ? 0 : EACCES);
1961}
1962
1963static int
1964mac_lomac_check_socket_relabel(struct ucred *cred, struct socket *socket,
1965 struct label *socketlabel, struct label *newlabel)
1966{
1967 struct mac_lomac *subj, *obj, *new;
1968 int error;
1969
1970 new = SLOT(newlabel);
1971 subj = SLOT(cred->cr_label);
1972 obj = SLOT(socketlabel);
1973
1974 /*
1975 * If there is a LOMAC label update for the socket, it may be
1976 * an update of single.
1977 */
1978 error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1979 if (error)
1980 return (error);
1981
1982 /*
1983 * To relabel a socket, the old socket single must be in the subject
1984 * range.
1985 */
1986 if (!mac_lomac_single_in_range(obj, subj))
1987 return (EPERM);
1988
1989 /*
1990 * If the LOMAC label is to be changed, authorize as appropriate.
1991 */
1992 if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1993 /*
1994 * To relabel a socket, the new socket single must be in
1995 * the subject range.
1996 */
1997 if (!mac_lomac_single_in_range(new, subj))
1998 return (EPERM);
1999
2000 /*
2001 * To change the LOMAC label on the socket to contain EQUAL,
2002 * the subject must have appropriate privilege.
2003 */
2004 if (mac_lomac_contains_equal(new)) {
2005 error = mac_lomac_subject_privileged(subj);
2006 if (error)
2007 return (error);
2008 }
2009 }
2010
2011 return (0);
2012}
2013
2014static int
2015mac_lomac_check_socket_visible(struct ucred *cred, struct socket *socket,
2016 struct label *socketlabel)
2017{
2018 struct mac_lomac *subj, *obj;
2019
2020 if (!mac_lomac_enabled)
2021 return (0);
2022
2023 subj = SLOT(cred->cr_label);
2024 obj = SLOT(socketlabel);
2025
2026 if (!mac_lomac_dominate_single(obj, subj))
2027 return (ENOENT);
2028
2029 return (0);
2030}
2031
2032static int
2033mac_lomac_check_system_swapon(struct ucred *cred, struct vnode *vp,
2034 struct label *label)
2035{
2036 struct mac_lomac *subj, *obj;
2037
2038 if (!mac_lomac_enabled)
2039 return (0);
2040
2041 subj = SLOT(cred->cr_label);
2042 obj = SLOT(label);
2043
2044 if (mac_lomac_subject_privileged(subj))
2045 return (EPERM);
2046
2047 if (!mac_lomac_high_single(obj))
2048 return (EACCES);
2049
2050 return (0);
2051}
2052
2053static int
2054mac_lomac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2055 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2056{
2057 struct mac_lomac *subj;
2058
2059 if (!mac_lomac_enabled)
2060 return (0);
2061
2062 subj = SLOT(cred->cr_label);
2063
2064 /*
2065 * In general, treat sysctl variables as lomac/high, but also
2066 * require privilege to change them, since they are a
2067 * communications channel between grades. Exempt MIB
2068 * queries from this due to undocmented sysctl magic.
2069 * XXXMAC: This probably requires some more review.
2070 */
2071 if (new != NULL) {
2072 if (namelen > 0 && name[0] == 0)
2073 return (0);
2074
2075#ifdef notdef
2076 if (!mac_lomac_subject_dominate_high(subj))
2077 return (EACCES);
2078#endif
2079
2080 if (mac_lomac_subject_privileged(subj))
2081 return (EPERM);
2082 }
2083
2084 return (0);
2085}
2086
2087static int
2088mac_lomac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2089 struct label *dlabel, struct componentname *cnp, struct vattr *vap)
2090{
2091 struct mac_lomac *subj, *obj;
2092
2093 if (!mac_lomac_enabled)
2094 return (0);
2095
2096 subj = SLOT(cred->cr_label);
2097 obj = SLOT(dlabel);
2098
2099 if (!mac_lomac_subject_dominate(subj, obj))
2100 return (EACCES);
2101 if (obj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2102 !mac_lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle))
2103 return (EACCES);
2104
2105 return (0);
2106}
2107
2108static int
2109mac_lomac_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
2110 struct label *dlabel, struct vnode *vp, struct label *label,
2111 struct componentname *cnp)
2112{
2113 struct mac_lomac *subj, *obj;
2114
2115 if (!mac_lomac_enabled)
2116 return (0);
2117
2118 subj = SLOT(cred->cr_label);
2119 obj = SLOT(dlabel);
2120
2121 if (!mac_lomac_subject_dominate(subj, obj))
2122 return (EACCES);
2123
2124 obj = SLOT(label);
2125
2126 if (!mac_lomac_subject_dominate(subj, obj))
2127 return (EACCES);
2128
2129 return (0);
2130}
2131
2132static int
2133mac_lomac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2134 struct label *label, acl_type_t type)
2135{
2136 struct mac_lomac *subj, *obj;
2137
2138 if (!mac_lomac_enabled)
2139 return (0);
2140
2141 subj = SLOT(cred->cr_label);
2142 obj = SLOT(label);
2143
2144 if (!mac_lomac_subject_dominate(subj, obj))
2145 return (EACCES);
2146
2147 return (0);
2148}
2149
2150static int
2151mac_lomac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2152 struct label *dlabel, struct vnode *vp, struct label *label,
2153 struct componentname *cnp)
2154{
2155 struct mac_lomac *subj, *obj;
2156
2157 if (!mac_lomac_enabled)
2158 return (0);
2159
2160 subj = SLOT(cred->cr_label);
2161 obj = SLOT(dlabel);
2162
2163 if (!mac_lomac_subject_dominate(subj, obj))
2164 return (EACCES);
2165
2166 obj = SLOT(label);
2167
2168 if (!mac_lomac_subject_dominate(subj, obj))
2169 return (EACCES);
2170
2171 return (0);
2172}
2173
2174static int
2175mac_lomac_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2176 struct label *label, int prot)
2177{
2178 struct mac_lomac *subj, *obj;
2179
2180 /*
2181 * Rely on the use of open()-time protections to handle
2182 * non-revocation cases.
2183 */
2184 if (!mac_lomac_enabled)
2185 return (0);
2186
2187 subj = SLOT(cred->cr_label);
2188 obj = SLOT(label);
2189
2190 if (prot & VM_PROT_WRITE) {
2191 if (!mac_lomac_subject_dominate(subj, obj))
2192 return (EACCES);
2193 }
2194 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2195 if (!mac_lomac_dominate_single(obj, subj))
2196 return (maybe_demote(subj, obj, "mapping", "file", vp));
2197 }
2198
2199 return (0);
2200}
2201
2202static int
2203mac_lomac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp,
2204 struct label *label, int prot)
2205{
2206 struct mac_lomac *subj, *obj;
2207
2208 /*
2209 * Rely on the use of open()-time protections to handle
2210 * non-revocation cases.
2211 */
2212 if (!mac_lomac_enabled || !revocation_enabled)
2213 return (0);
2214
2215 subj = SLOT(cred->cr_label);
2216 obj = SLOT(label);
2217
2218 if (prot & VM_PROT_WRITE) {
2219 if (!mac_lomac_subject_dominate(subj, obj))
2220 return (EACCES);
2221 }
2222 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2223 if (!mac_lomac_dominate_single(obj, subj))
2224 return (EACCES);
2225 }
2226
2227 return (0);
2228}
2229
2230static void
2231mac_lomac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp,
2232 struct label *label, /* XXX vm_prot_t */ int *prot)
2233{
2234 struct mac_lomac *subj, *obj;
2235
2236 /*
2237 * Rely on the use of open()-time protections to handle
2238 * non-revocation cases.
2239 */
2240 if (!mac_lomac_enabled || !revocation_enabled)
2241 return;
2242
2243 subj = SLOT(cred->cr_label);
2244 obj = SLOT(label);
2245
2246 if (!mac_lomac_subject_dominate(subj, obj))
2247 *prot &= ~VM_PROT_WRITE;
2248}
2249
2250static int
2251mac_lomac_check_vnode_open(struct ucred *cred, struct vnode *vp,
2252 struct label *vnodelabel, int acc_mode)
2253{
2254 struct mac_lomac *subj, *obj;
2255
2256 if (!mac_lomac_enabled)
2257 return (0);
2258
2259 subj = SLOT(cred->cr_label);
2260 obj = SLOT(vnodelabel);
2261
2262 /* XXX privilege override for admin? */
2263 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2264 if (!mac_lomac_subject_dominate(subj, obj))
2265 return (EACCES);
2266 }
2267
2268 return (0);
2269}
2270
2271static int
2272mac_lomac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2273 struct vnode *vp, struct label *label)
2274{
2275 struct mac_lomac *subj, *obj;
2276
2277 if (!mac_lomac_enabled || !revocation_enabled)
2278 return (0);
2279
2280 subj = SLOT(active_cred->cr_label);
2281 obj = SLOT(label);
2282
2283 if (!mac_lomac_dominate_single(obj, subj))
2284 return (maybe_demote(subj, obj, "reading", "file", vp));
2285
2286 return (0);
2287}
2288
2289static int
2290mac_lomac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2291 struct label *vnodelabel, struct label *newlabel)
2292{
2293 struct mac_lomac *old, *new, *subj;
2294 int error;
2295
2296 old = SLOT(vnodelabel);
2297 new = SLOT(newlabel);
2298 subj = SLOT(cred->cr_label);
2299
2300 /*
2301 * If there is a LOMAC label update for the vnode, it must be a
2302 * single label, with an optional explicit auxiliary single.
2303 */
2304 error = lomac_atmostflags(new,
2305 MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX);
2306 if (error)
2307 return (error);
2308
2309 /*
2310 * To perform a relabel of the vnode (LOMAC label or not), LOMAC must
2311 * authorize the relabel.
2312 */
2313 if (!mac_lomac_single_in_range(old, subj))
2314 return (EPERM);
2315
2316 /*
2317 * If the LOMAC label is to be changed, authorize as appropriate.
2318 */
2319 if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2320 /*
2321 * To change the LOMAC label on a vnode, the new vnode label
2322 * must be in the subject range.
2323 */
2324 if (!mac_lomac_single_in_range(new, subj))
2325 return (EPERM);
2326
2327 /*
2328 * To change the LOMAC label on the vnode to be EQUAL,
2329 * the subject must have appropriate privilege.
2330 */
2331 if (mac_lomac_contains_equal(new)) {
2332 error = mac_lomac_subject_privileged(subj);
2333 if (error)
2334 return (error);
2335 }
2336 }
2337 if (new->ml_flags & MAC_LOMAC_FLAG_AUX) {
2338 /*
2339 * Fill in the missing parts from the previous label.
2340 */
2341 if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
2342 mac_lomac_copy_single(subj, new);
2343
2344 /*
2345 * To change the auxiliary LOMAC label on a vnode, the new
2346 * vnode label must be in the subject range.
2347 */
2348 if (!mac_lomac_auxsingle_in_range(new, subj))
2349 return (EPERM);
2350
2351 /*
2352 * To change the auxiliary LOMAC label on the vnode to be
2353 * EQUAL, the subject must have appropriate privilege.
2354 */
2355 if (mac_lomac_contains_equal(new)) {
2356 error = mac_lomac_subject_privileged(subj);
2357 if (error)
2358 return (error);
2359 }
2360 }
2361
2362 return (0);
2363}
2364
2365static int
2366mac_lomac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2367 struct label *dlabel, struct vnode *vp, struct label *label,
2368 struct componentname *cnp)
2369{
2370 struct mac_lomac *subj, *obj;
2371
2372 if (!mac_lomac_enabled)
2373 return (0);
2374
2375 subj = SLOT(cred->cr_label);
2376 obj = SLOT(dlabel);
2377
2378 if (!mac_lomac_subject_dominate(subj, obj))
2379 return (EACCES);
2380
2381 obj = SLOT(label);
2382
2383 if (!mac_lomac_subject_dominate(subj, obj))
2384 return (EACCES);
2385
2386 return (0);
2387}
2388
2389static int
2390mac_lomac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2391 struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2392 struct componentname *cnp)
2393{
2394 struct mac_lomac *subj, *obj;
2395
2396 if (!mac_lomac_enabled)
2397 return (0);
2398
2399 subj = SLOT(cred->cr_label);
2400 obj = SLOT(dlabel);
2401
2402 if (!mac_lomac_subject_dominate(subj, obj))
2403 return (EACCES);
2404
2405 if (vp != NULL) {
2406 obj = SLOT(label);
2407
2408 if (!mac_lomac_subject_dominate(subj, obj))
2409 return (EACCES);
2410 }
2411
2412 return (0);
2413}
2414
2415static int
2416mac_lomac_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2417 struct label *label)
2418{
2419 struct mac_lomac *subj, *obj;
2420
2421 if (!mac_lomac_enabled)
2422 return (0);
2423
2424 subj = SLOT(cred->cr_label);
2425 obj = SLOT(label);
2426
2427 if (!mac_lomac_subject_dominate(subj, obj))
2428 return (EACCES);
2429
2430 return (0);
2431}
2432
2433static int
2434mac_lomac_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2435 struct label *label, acl_type_t type, struct acl *acl)
2436{
2437 struct mac_lomac *subj, *obj;
2438
2439 if (!mac_lomac_enabled)
2440 return (0);
2441
2442 subj = SLOT(cred->cr_label);
2443 obj = SLOT(label);
2444
2445 if (!mac_lomac_subject_dominate(subj, obj))
2446 return (EACCES);
2447
2448 return (0);
2449}
2450
2451static int
2452mac_lomac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2453 struct label *vnodelabel, int attrnamespace, const char *name,
2454 struct uio *uio)
2455{
2456 struct mac_lomac *subj, *obj;
2457
2458 if (!mac_lomac_enabled)
2459 return (0);
2460
2461 subj = SLOT(cred->cr_label);
2462 obj = SLOT(vnodelabel);
2463
2464 if (!mac_lomac_subject_dominate(subj, obj))
2465 return (EACCES);
2466
2467 /* XXX: protect the MAC EA in a special way? */
2468
2469 return (0);
2470}
2471
2472static int
2473mac_lomac_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2474 struct label *vnodelabel, u_long flags)
2475{
2476 struct mac_lomac *subj, *obj;
2477
2478 if (!mac_lomac_enabled)
2479 return (0);
2480
2481 subj = SLOT(cred->cr_label);
2482 obj = SLOT(vnodelabel);
2483
2484 if (!mac_lomac_subject_dominate(subj, obj))
2485 return (EACCES);
2486
2487 return (0);
2488}
2489
2490static int
2491mac_lomac_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2492 struct label *vnodelabel, mode_t mode)
2493{
2494 struct mac_lomac *subj, *obj;
2495
2496 if (!mac_lomac_enabled)
2497 return (0);
2498
2499 subj = SLOT(cred->cr_label);
2500 obj = SLOT(vnodelabel);
2501
2502 if (!mac_lomac_subject_dominate(subj, obj))
2503 return (EACCES);
2504
2505 return (0);
2506}
2507
2508static int
2509mac_lomac_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2510 struct label *vnodelabel, uid_t uid, gid_t gid)
2511{
2512 struct mac_lomac *subj, *obj;
2513
2514 if (!mac_lomac_enabled)
2515 return (0);
2516
2517 subj = SLOT(cred->cr_label);
2518 obj = SLOT(vnodelabel);
2519
2520 if (!mac_lomac_subject_dominate(subj, obj))
2521 return (EACCES);
2522
2523 return (0);
2524}
2525
2526static int
2527mac_lomac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2528 struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2529{
2530 struct mac_lomac *subj, *obj;
2531
2532 if (!mac_lomac_enabled)
2533 return (0);
2534
2535 subj = SLOT(cred->cr_label);
2536 obj = SLOT(vnodelabel);
2537
2538 if (!mac_lomac_subject_dominate(subj, obj))
2539 return (EACCES);
2540
2541 return (0);
2542}
2543
2544static int
2545mac_lomac_check_vnode_write(struct ucred *active_cred,
2546 struct ucred *file_cred, struct vnode *vp, struct label *label)
2547{
2548 struct mac_lomac *subj, *obj;
2549
2550 if (!mac_lomac_enabled || !revocation_enabled)
2551 return (0);
2552
2553 subj = SLOT(active_cred->cr_label);
2554 obj = SLOT(label);
2555
2556 if (!mac_lomac_subject_dominate(subj, obj))
2557 return (EACCES);
2558
2559 return (0);
2560}
2561
2562static void
2563mac_lomac_thread_userret(struct thread *td)
2564{
2565 struct proc *p = td->td_proc;
2566 struct mac_lomac_proc *subj = PSLOT(p->p_label);
2567 struct ucred *newcred, *oldcred;
2568 int dodrop;
2569
2570 mtx_lock(&subj->mtx);
2571 if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
2572 dodrop = 0;
2573 mtx_unlock(&subj->mtx);
2574 newcred = crget();
2575 /*
2576 * Prevent a lock order reversal in
2577 * mac_cred_mmapped_drop_perms; ideally, the other
2578 * user of subj->mtx wouldn't be holding Giant.
2579 */
2580 mtx_lock(&Giant);
2581 PROC_LOCK(p);
2582 mtx_lock(&subj->mtx);
2583 /*
2584 * Check if we lost the race while allocating the cred.
2585 */
2586 if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) {
2587 crfree(newcred);
2588 goto out;
2589 }
2590 oldcred = p->p_ucred;
2591 crcopy(newcred, oldcred);
2592 crhold(newcred);
2593 mac_lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label));
2594 p->p_ucred = newcred;
2595 crfree(oldcred);
2596 dodrop = 1;
2597 out:
2598 mtx_unlock(&subj->mtx);
2599 PROC_UNLOCK(p);
2600 if (dodrop)
2601 mac_cred_mmapped_drop_perms(curthread, newcred);
2602 mtx_unlock(&Giant);
2603 } else {
2604 mtx_unlock(&subj->mtx);
2605 }
2606}
2607
2608static struct mac_policy_ops mac_lomac_ops =
2609{
2610 .mpo_init = mac_lomac_init,
2611 .mpo_init_bpfdesc_label = mac_lomac_init_label,
2612 .mpo_init_cred_label = mac_lomac_init_label,
2613 .mpo_init_devfsdirent_label = mac_lomac_init_label,
2614 .mpo_init_ifnet_label = mac_lomac_init_label,
2615 .mpo_init_inpcb_label = mac_lomac_init_label_waitcheck,
2616 .mpo_init_ipq_label = mac_lomac_init_label_waitcheck,
2617 .mpo_init_mbuf_label = mac_lomac_init_label_waitcheck,
2618 .mpo_init_mount_label = mac_lomac_init_label,
2619 .mpo_init_mount_fs_label = mac_lomac_init_label,
2620 .mpo_init_pipe_label = mac_lomac_init_label,
2621 .mpo_init_proc_label = mac_lomac_init_proc_label,
2622 .mpo_init_socket_label = mac_lomac_init_label_waitcheck,
2623 .mpo_init_socket_peer_label = mac_lomac_init_label_waitcheck,
2624 .mpo_init_vnode_label = mac_lomac_init_label,
2625 .mpo_destroy_bpfdesc_label = mac_lomac_destroy_label,
2626 .mpo_destroy_cred_label = mac_lomac_destroy_label,
2627 .mpo_destroy_devfsdirent_label = mac_lomac_destroy_label,
2628 .mpo_destroy_ifnet_label = mac_lomac_destroy_label,
2629 .mpo_destroy_inpcb_label = mac_lomac_destroy_label,
2630 .mpo_destroy_ipq_label = mac_lomac_destroy_label,
2631 .mpo_destroy_mbuf_label = mac_lomac_destroy_label,
2632 .mpo_destroy_mount_label = mac_lomac_destroy_label,
2633 .mpo_destroy_mount_fs_label = mac_lomac_destroy_label,
2634 .mpo_destroy_pipe_label = mac_lomac_destroy_label,
2635 .mpo_destroy_proc_label = mac_lomac_destroy_proc_label,
2636 .mpo_destroy_socket_label = mac_lomac_destroy_label,
2637 .mpo_destroy_socket_peer_label = mac_lomac_destroy_label,
2638 .mpo_destroy_vnode_label = mac_lomac_destroy_label,
2639 .mpo_copy_cred_label = mac_lomac_copy_label,
2640 .mpo_copy_mbuf_label = mac_lomac_copy_label,
2641 .mpo_copy_pipe_label = mac_lomac_copy_label,
2642 .mpo_copy_socket_label = mac_lomac_copy_label,
2643 .mpo_copy_vnode_label = mac_lomac_copy_label,
2644 .mpo_externalize_cred_label = mac_lomac_externalize_label,
2645 .mpo_externalize_ifnet_label = mac_lomac_externalize_label,
2646 .mpo_externalize_pipe_label = mac_lomac_externalize_label,
2647 .mpo_externalize_socket_label = mac_lomac_externalize_label,
2648 .mpo_externalize_socket_peer_label = mac_lomac_externalize_label,
2649 .mpo_externalize_vnode_label = mac_lomac_externalize_label,
2650 .mpo_internalize_cred_label = mac_lomac_internalize_label,
2651 .mpo_internalize_ifnet_label = mac_lomac_internalize_label,
2652 .mpo_internalize_pipe_label = mac_lomac_internalize_label,
2653 .mpo_internalize_socket_label = mac_lomac_internalize_label,
2654 .mpo_internalize_vnode_label = mac_lomac_internalize_label,
2655 .mpo_create_devfs_device = mac_lomac_create_devfs_device,
2656 .mpo_create_devfs_directory = mac_lomac_create_devfs_directory,
2657 .mpo_create_devfs_symlink = mac_lomac_create_devfs_symlink,
2658 .mpo_create_mount = mac_lomac_create_mount,
2659 .mpo_create_root_mount = mac_lomac_create_root_mount,
2660 .mpo_relabel_vnode = mac_lomac_relabel_vnode,
2661 .mpo_update_devfsdirent = mac_lomac_update_devfsdirent,
2662 .mpo_associate_vnode_devfs = mac_lomac_associate_vnode_devfs,
2663 .mpo_associate_vnode_extattr = mac_lomac_associate_vnode_extattr,
2664 .mpo_associate_vnode_singlelabel =
2665 mac_lomac_associate_vnode_singlelabel,
2666 .mpo_create_vnode_extattr = mac_lomac_create_vnode_extattr,
2667 .mpo_setlabel_vnode_extattr = mac_lomac_setlabel_vnode_extattr,
2668 .mpo_create_mbuf_from_socket = mac_lomac_create_mbuf_from_socket,
2669 .mpo_create_pipe = mac_lomac_create_pipe,
2670 .mpo_create_socket = mac_lomac_create_socket,
2671 .mpo_create_socket_from_socket = mac_lomac_create_socket_from_socket,
2672 .mpo_relabel_pipe = mac_lomac_relabel_pipe,
2673 .mpo_relabel_socket = mac_lomac_relabel_socket,
2674 .mpo_set_socket_peer_from_mbuf = mac_lomac_set_socket_peer_from_mbuf,
2675 .mpo_set_socket_peer_from_socket =
2676 mac_lomac_set_socket_peer_from_socket,
2677 .mpo_create_bpfdesc = mac_lomac_create_bpfdesc,
2678 .mpo_create_datagram_from_ipq = mac_lomac_create_datagram_from_ipq,
2679 .mpo_create_fragment = mac_lomac_create_fragment,
2680 .mpo_create_ifnet = mac_lomac_create_ifnet,
2681 .mpo_create_inpcb_from_socket = mac_lomac_create_inpcb_from_socket,
2682 .mpo_create_ipq = mac_lomac_create_ipq,
2683 .mpo_create_mbuf_from_mbuf = mac_lomac_create_mbuf_from_mbuf,
2684 .mpo_create_mbuf_linklayer = mac_lomac_create_mbuf_linklayer,
2685 .mpo_create_mbuf_from_bpfdesc = mac_lomac_create_mbuf_from_bpfdesc,
2686 .mpo_create_mbuf_from_ifnet = mac_lomac_create_mbuf_from_ifnet,
2687 .mpo_create_mbuf_multicast_encap =
2688 mac_lomac_create_mbuf_multicast_encap,
2689 .mpo_create_mbuf_netlayer = mac_lomac_create_mbuf_netlayer,
2690 .mpo_fragment_match = mac_lomac_fragment_match,
2691 .mpo_relabel_ifnet = mac_lomac_relabel_ifnet,
2692 .mpo_update_ipq = mac_lomac_update_ipq,
2693 .mpo_inpcb_sosetlabel = mac_lomac_inpcb_sosetlabel,
2694 .mpo_execve_transition = mac_lomac_execve_transition,
2695 .mpo_execve_will_transition = mac_lomac_execve_will_transition,
2696 .mpo_create_proc0 = mac_lomac_create_proc0,
2697 .mpo_create_proc1 = mac_lomac_create_proc1,
2698 .mpo_relabel_cred = mac_lomac_relabel_cred,
2699 .mpo_check_bpfdesc_receive = mac_lomac_check_bpfdesc_receive,
2700 .mpo_check_cred_relabel = mac_lomac_check_cred_relabel,
2701 .mpo_check_cred_visible = mac_lomac_check_cred_visible,
2702 .mpo_check_ifnet_relabel = mac_lomac_check_ifnet_relabel,
2703 .mpo_check_ifnet_transmit = mac_lomac_check_ifnet_transmit,
2704 .mpo_check_inpcb_deliver = mac_lomac_check_inpcb_deliver,
2705 .mpo_check_kld_load = mac_lomac_check_kld_load,
2706 .mpo_check_kld_unload = mac_lomac_check_kld_unload,
2707 .mpo_check_pipe_ioctl = mac_lomac_check_pipe_ioctl,
2708 .mpo_check_pipe_read = mac_lomac_check_pipe_read,
2709 .mpo_check_pipe_relabel = mac_lomac_check_pipe_relabel,
2710 .mpo_check_pipe_write = mac_lomac_check_pipe_write,
2711 .mpo_check_proc_debug = mac_lomac_check_proc_debug,
2712 .mpo_check_proc_sched = mac_lomac_check_proc_sched,
2713 .mpo_check_proc_signal = mac_lomac_check_proc_signal,
2714 .mpo_check_socket_deliver = mac_lomac_check_socket_deliver,
2715 .mpo_check_socket_relabel = mac_lomac_check_socket_relabel,
2716 .mpo_check_socket_visible = mac_lomac_check_socket_visible,
2717 .mpo_check_system_swapon = mac_lomac_check_system_swapon,
2718 .mpo_check_system_sysctl = mac_lomac_check_system_sysctl,
2719 .mpo_check_vnode_access = mac_lomac_check_vnode_open,
2720 .mpo_check_vnode_create = mac_lomac_check_vnode_create,
2721 .mpo_check_vnode_delete = mac_lomac_check_vnode_delete,
2722 .mpo_check_vnode_deleteacl = mac_lomac_check_vnode_deleteacl,
2723 .mpo_check_vnode_link = mac_lomac_check_vnode_link,
2724 .mpo_check_vnode_mmap = mac_lomac_check_vnode_mmap,
2725 .mpo_check_vnode_mmap_downgrade = mac_lomac_check_vnode_mmap_downgrade,
2726 .mpo_check_vnode_mprotect = mac_lomac_check_vnode_mprotect,
2727 .mpo_check_vnode_open = mac_lomac_check_vnode_open,
2728 .mpo_check_vnode_read = mac_lomac_check_vnode_read,
2729 .mpo_check_vnode_relabel = mac_lomac_check_vnode_relabel,
2730 .mpo_check_vnode_rename_from = mac_lomac_check_vnode_rename_from,
2731 .mpo_check_vnode_rename_to = mac_lomac_check_vnode_rename_to,
2732 .mpo_check_vnode_revoke = mac_lomac_check_vnode_revoke,
2733 .mpo_check_vnode_setacl = mac_lomac_check_vnode_setacl,
2734 .mpo_check_vnode_setextattr = mac_lomac_check_vnode_setextattr,
2735 .mpo_check_vnode_setflags = mac_lomac_check_vnode_setflags,
2736 .mpo_check_vnode_setmode = mac_lomac_check_vnode_setmode,
2737 .mpo_check_vnode_setowner = mac_lomac_check_vnode_setowner,
2738 .mpo_check_vnode_setutimes = mac_lomac_check_vnode_setutimes,
2739 .mpo_check_vnode_write = mac_lomac_check_vnode_write,
2740 .mpo_thread_userret = mac_lomac_thread_userret,
2741};
2742
2743MAC_POLICY_SET(&mac_lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC",
2744 MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS,
2745 &mac_lomac_slot);