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