1101099Srwatson/*-
2225344Srwatson * Copyright (c) 1999-2002, 2007-2011 Robert N. M. Watson
3140629Srwatson * Copyright (c) 2001-2005 McAfee, Inc.
4172930Srwatson * Copyright (c) 2006 SPARTA, Inc.
5101099Srwatson * All rights reserved.
6101099Srwatson *
7101099Srwatson * This software was developed by Robert Watson for the TrustedBSD Project.
8101099Srwatson *
9140629Srwatson * This software was developed for the FreeBSD Project in part by McAfee
10140629Srwatson * Research, the Security Research Division of McAfee, Inc. under
11140629Srwatson * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
12140629Srwatson * CHATS research program.
13101099Srwatson *
14172930Srwatson * This software was enhanced by SPARTA ISSO under SPAWAR contract
15172930Srwatson * N66001-04-C-6019 ("SEFOS").
16172930Srwatson *
17225344Srwatson * This software was developed at the University of Cambridge Computer
18225344Srwatson * Laboratory with support from a grant from Google, Inc.
19225344Srwatson *
20101099Srwatson * Redistribution and use in source and binary forms, with or without
21101099Srwatson * modification, are permitted provided that the following conditions
22101099Srwatson * are met:
23101099Srwatson * 1. Redistributions of source code must retain the above copyright
24101099Srwatson *    notice, this list of conditions and the following disclaimer.
25101099Srwatson * 2. Redistributions in binary form must reproduce the above copyright
26101099Srwatson *    notice, this list of conditions and the following disclaimer in the
27101099Srwatson *    documentation and/or other materials provided with the distribution.
28101099Srwatson *
29101099Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
30101099Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31101099Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32101099Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
33101099Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34101099Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35101099Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36101099Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37101099Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38101099Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39101099Srwatson * SUCH DAMAGE.
40101099Srwatson *
41101099Srwatson * $FreeBSD$
42101099Srwatson */
43101099Srwatson
44101099Srwatson/*
45101099Srwatson * Developed by the TrustedBSD Project.
46168977Srwatson *
47101099Srwatson * MLS fixed label mandatory confidentiality policy.
48101099Srwatson */
49101099Srwatson
50101099Srwatson#include <sys/types.h>
51101099Srwatson#include <sys/param.h>
52101099Srwatson#include <sys/acl.h>
53101099Srwatson#include <sys/conf.h>
54105988Srwatson#include <sys/extattr.h>
55101099Srwatson#include <sys/kernel.h>
56164184Strhodes#include <sys/ksem.h>
57145076Scsjp#include <sys/mman.h>
58103183Sbde#include <sys/malloc.h>
59101099Srwatson#include <sys/mount.h>
60101099Srwatson#include <sys/proc.h>
61115497Srwatson#include <sys/sbuf.h>
62101099Srwatson#include <sys/systm.h>
63101099Srwatson#include <sys/sysproto.h>
64101099Srwatson#include <sys/sysent.h>
65105696Srwatson#include <sys/systm.h>
66101099Srwatson#include <sys/vnode.h>
67101099Srwatson#include <sys/file.h>
68101099Srwatson#include <sys/socket.h>
69101099Srwatson#include <sys/socketvar.h>
70101099Srwatson#include <sys/pipe.h>
71150340Sphk#include <sys/sx.h>
72101099Srwatson#include <sys/sysctl.h>
73140629Srwatson#include <sys/msg.h>
74140629Srwatson#include <sys/sem.h>
75140629Srwatson#include <sys/shm.h>
76101099Srwatson
77101099Srwatson#include <fs/devfs/devfs.h>
78101099Srwatson
79101099Srwatson#include <net/bpfdesc.h>
80101099Srwatson#include <net/if.h>
81101099Srwatson#include <net/if_types.h>
82101099Srwatson#include <net/if_var.h>
83101099Srwatson
84101099Srwatson#include <netinet/in.h>
85122875Srwatson#include <netinet/in_pcb.h>
86101099Srwatson#include <netinet/ip_var.h>
87101099Srwatson
88122879Srwatson#include <vm/uma.h>
89101099Srwatson#include <vm/vm.h>
90101099Srwatson
91165469Srwatson#include <security/mac/mac_policy.h>
92101099Srwatson#include <security/mac_mls/mac_mls.h>
93101099Srwatson
94101099SrwatsonSYSCTL_DECL(_security_mac);
95101099Srwatson
96227309Sedstatic SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
97101099Srwatson    "TrustedBSD mac_mls policy controls");
98101099Srwatson
99172955Srwatsonstatic int	mls_label_size = sizeof(struct mac_mls);
100105988SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
101172955Srwatson    &mls_label_size, 0, "Size of struct mac_mls");
102105988Srwatson
103172955Srwatsonstatic int	mls_enabled = 1;
104172955SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW, &mls_enabled, 0,
105172955Srwatson    "Enforce MAC/MLS policy");
106172955SrwatsonTUNABLE_INT("security.mac.mls.enabled", &mls_enabled);
107101099Srwatson
108101099Srwatsonstatic int	destroyed_not_inited;
109101099SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
110101099Srwatson    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
111101099Srwatson
112105606Srwatsonstatic int	ptys_equal = 0;
113105606SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
114105606Srwatson    &ptys_equal, 0, "Label pty devices as mls/equal on create");
115105606SrwatsonTUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
116105606Srwatson
117105640Srwatsonstatic int	revocation_enabled = 0;
118101099SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
119105640Srwatson    &revocation_enabled, 0, "Revoke access to objects on relabel");
120105640SrwatsonTUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled);
121101099Srwatson
122105643Srwatsonstatic int	max_compartments = MAC_MLS_MAX_COMPARTMENTS;
123105643SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
124105643Srwatson    &max_compartments, 0, "Maximum compartments the policy supports");
125105643Srwatson
126172955Srwatsonstatic int	mls_slot;
127172955Srwatson#define	SLOT(l)	((struct mac_mls *)mac_label_get((l), mls_slot))
128172955Srwatson#define	SLOT_SET(l, val) mac_label_set((l), mls_slot, (uintptr_t)(val))
129101099Srwatson
130122879Srwatsonstatic uma_zone_t	zone_mls;
131101099Srwatson
132105643Srwatsonstatic __inline int
133105643Srwatsonmls_bit_set_empty(u_char *set) {
134105643Srwatson	int i;
135105643Srwatson
136105643Srwatson	for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++)
137105643Srwatson		if (set[i] != 0)
138105643Srwatson			return (0);
139105643Srwatson	return (1);
140105643Srwatson}
141105643Srwatson
142101099Srwatsonstatic struct mac_mls *
143104514Srwatsonmls_alloc(int flag)
144101099Srwatson{
145101099Srwatson
146122879Srwatson	return (uma_zalloc(zone_mls, flag | M_ZERO));
147101099Srwatson}
148101099Srwatson
149101099Srwatsonstatic void
150172955Srwatsonmls_free(struct mac_mls *mm)
151101099Srwatson{
152101099Srwatson
153172955Srwatson	if (mm != NULL)
154172955Srwatson		uma_zfree(zone_mls, mm);
155101099Srwatson	else
156101099Srwatson		atomic_add_int(&destroyed_not_inited, 1);
157101099Srwatson}
158101099Srwatson
159101099Srwatsonstatic int
160172955Srwatsonmls_atmostflags(struct mac_mls *mm, int flags)
161105634Srwatson{
162105634Srwatson
163172955Srwatson	if ((mm->mm_flags & flags) != mm->mm_flags)
164105634Srwatson		return (EINVAL);
165105634Srwatson	return (0);
166105634Srwatson}
167105634Srwatson
168105634Srwatsonstatic int
169172955Srwatsonmls_dominate_element(struct mac_mls_element *a, struct mac_mls_element *b)
170101099Srwatson{
171105643Srwatson	int bit;
172101099Srwatson
173105736Srwatson	switch (a->mme_type) {
174101099Srwatson	case MAC_MLS_TYPE_EQUAL:
175101099Srwatson	case MAC_MLS_TYPE_HIGH:
176101099Srwatson		return (1);
177101099Srwatson
178101099Srwatson	case MAC_MLS_TYPE_LOW:
179101099Srwatson		switch (b->mme_type) {
180101099Srwatson		case MAC_MLS_TYPE_LEVEL:
181101099Srwatson		case MAC_MLS_TYPE_HIGH:
182101099Srwatson			return (0);
183101099Srwatson
184101099Srwatson		case MAC_MLS_TYPE_EQUAL:
185101099Srwatson		case MAC_MLS_TYPE_LOW:
186101099Srwatson			return (1);
187101099Srwatson
188101099Srwatson		default:
189172955Srwatson			panic("mls_dominate_element: b->mme_type invalid");
190101099Srwatson		}
191101099Srwatson
192101099Srwatson	case MAC_MLS_TYPE_LEVEL:
193101099Srwatson		switch (b->mme_type) {
194101099Srwatson		case MAC_MLS_TYPE_EQUAL:
195101099Srwatson		case MAC_MLS_TYPE_LOW:
196101099Srwatson			return (1);
197101099Srwatson
198101099Srwatson		case MAC_MLS_TYPE_HIGH:
199101099Srwatson			return (0);
200101099Srwatson
201101099Srwatson		case MAC_MLS_TYPE_LEVEL:
202105643Srwatson			for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++)
203105643Srwatson				if (!MAC_MLS_BIT_TEST(bit,
204105643Srwatson				    a->mme_compartments) &&
205105643Srwatson				    MAC_MLS_BIT_TEST(bit, b->mme_compartments))
206105643Srwatson					return (0);
207101099Srwatson			return (a->mme_level >= b->mme_level);
208101099Srwatson
209101099Srwatson		default:
210172955Srwatson			panic("mls_dominate_element: b->mme_type invalid");
211101099Srwatson		}
212101099Srwatson
213101099Srwatson	default:
214172955Srwatson		panic("mls_dominate_element: a->mme_type invalid");
215101099Srwatson	}
216101099Srwatson
217101099Srwatson	return (0);
218101099Srwatson}
219101099Srwatson
220101099Srwatsonstatic int
221172955Srwatsonmls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
222101099Srwatson{
223101099Srwatson
224172955Srwatson	return (mls_dominate_element(&rangeb->mm_rangehigh,
225101099Srwatson	    &rangea->mm_rangehigh) &&
226172955Srwatson	    mls_dominate_element(&rangea->mm_rangelow,
227101099Srwatson	    &rangeb->mm_rangelow));
228101099Srwatson}
229101099Srwatson
230101099Srwatsonstatic int
231172955Srwatsonmls_effective_in_range(struct mac_mls *effective, struct mac_mls *range)
232101099Srwatson{
233101099Srwatson
234132232Srwatson	KASSERT((effective->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
235172955Srwatson	    ("mls_effective_in_range: a not effective"));
236103750Srwatson	KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
237172955Srwatson	    ("mls_effective_in_range: b not range"));
238101099Srwatson
239172955Srwatson	return (mls_dominate_element(&range->mm_rangehigh,
240132232Srwatson	    &effective->mm_effective) &&
241172955Srwatson	    mls_dominate_element(&effective->mm_effective,
242101099Srwatson	    &range->mm_rangelow));
243101099Srwatson
244101099Srwatson	return (1);
245101099Srwatson}
246101099Srwatson
247101099Srwatsonstatic int
248172955Srwatsonmls_dominate_effective(struct mac_mls *a, struct mac_mls *b)
249101099Srwatson{
250132232Srwatson	KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
251172955Srwatson	    ("mls_dominate_effective: a not effective"));
252132232Srwatson	KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
253172955Srwatson	    ("mls_dominate_effective: b not effective"));
254101099Srwatson
255172955Srwatson	return (mls_dominate_element(&a->mm_effective, &b->mm_effective));
256101099Srwatson}
257101099Srwatson
258101099Srwatsonstatic int
259172955Srwatsonmls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
260101099Srwatson{
261101099Srwatson
262101099Srwatson	if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
263101099Srwatson	    b->mme_type == MAC_MLS_TYPE_EQUAL)
264101099Srwatson		return (1);
265101099Srwatson
266101099Srwatson	return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
267101099Srwatson}
268101099Srwatson
269101099Srwatsonstatic int
270172955Srwatsonmls_equal_effective(struct mac_mls *a, struct mac_mls *b)
271101099Srwatson{
272101099Srwatson
273132232Srwatson	KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
274172955Srwatson	    ("mls_equal_effective: a not effective"));
275132232Srwatson	KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
276172955Srwatson	    ("mls_equal_effective: b not effective"));
277101099Srwatson
278172955Srwatson	return (mls_equal_element(&a->mm_effective, &b->mm_effective));
279101099Srwatson}
280101099Srwatson
281101099Srwatsonstatic int
282172955Srwatsonmls_contains_equal(struct mac_mls *mm)
283105634Srwatson{
284105634Srwatson
285172955Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
286172955Srwatson		if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
287105634Srwatson			return (1);
288105634Srwatson
289172955Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
290172955Srwatson		if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL)
291105634Srwatson			return (1);
292172955Srwatson		if (mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
293105634Srwatson			return (1);
294105634Srwatson	}
295105634Srwatson
296105634Srwatson	return (0);
297105634Srwatson}
298105634Srwatson
299105634Srwatsonstatic int
300172955Srwatsonmls_subject_privileged(struct mac_mls *mm)
301105634Srwatson{
302105634Srwatson
303172955Srwatson	KASSERT((mm->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH,
304172955Srwatson	    ("mls_subject_privileged: subject doesn't have both labels"));
305105634Srwatson
306132232Srwatson	/* If the effective is EQUAL, it's ok. */
307172955Srwatson	if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
308105634Srwatson		return (0);
309105634Srwatson
310105634Srwatson	/* If either range endpoint is EQUAL, it's ok. */
311172955Srwatson	if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL ||
312172955Srwatson	    mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
313105634Srwatson		return (0);
314105634Srwatson
315105634Srwatson	/* If the range is low-high, it's ok. */
316172955Srwatson	if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW &&
317172955Srwatson	    mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH)
318105634Srwatson		return (0);
319105634Srwatson
320105634Srwatson	/* It's not ok. */
321105634Srwatson	return (EPERM);
322105634Srwatson}
323105634Srwatson
324105634Srwatsonstatic int
325172955Srwatsonmls_valid(struct mac_mls *mm)
326101099Srwatson{
327101099Srwatson
328172955Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
329172955Srwatson		switch (mm->mm_effective.mme_type) {
330101099Srwatson		case MAC_MLS_TYPE_LEVEL:
331101099Srwatson			break;
332101099Srwatson
333101099Srwatson		case MAC_MLS_TYPE_EQUAL:
334101099Srwatson		case MAC_MLS_TYPE_HIGH:
335101099Srwatson		case MAC_MLS_TYPE_LOW:
336172955Srwatson			if (mm->mm_effective.mme_level != 0 ||
337105643Srwatson			    !MAC_MLS_BIT_SET_EMPTY(
338172955Srwatson			    mm->mm_effective.mme_compartments))
339101099Srwatson				return (EINVAL);
340101099Srwatson			break;
341101099Srwatson
342101099Srwatson		default:
343101099Srwatson			return (EINVAL);
344101099Srwatson		}
345101099Srwatson	} else {
346172955Srwatson		if (mm->mm_effective.mme_type != MAC_MLS_TYPE_UNDEF)
347101099Srwatson			return (EINVAL);
348101099Srwatson	}
349101099Srwatson
350172955Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
351172955Srwatson		switch (mm->mm_rangelow.mme_type) {
352101099Srwatson		case MAC_MLS_TYPE_LEVEL:
353101099Srwatson			break;
354101099Srwatson
355101099Srwatson		case MAC_MLS_TYPE_EQUAL:
356101099Srwatson		case MAC_MLS_TYPE_HIGH:
357101099Srwatson		case MAC_MLS_TYPE_LOW:
358172955Srwatson			if (mm->mm_rangelow.mme_level != 0 ||
359105643Srwatson			    !MAC_MLS_BIT_SET_EMPTY(
360172955Srwatson			    mm->mm_rangelow.mme_compartments))
361101099Srwatson				return (EINVAL);
362101099Srwatson			break;
363101099Srwatson
364101099Srwatson		default:
365101099Srwatson			return (EINVAL);
366101099Srwatson		}
367101099Srwatson
368172955Srwatson		switch (mm->mm_rangehigh.mme_type) {
369101099Srwatson		case MAC_MLS_TYPE_LEVEL:
370101099Srwatson			break;
371101099Srwatson
372101099Srwatson		case MAC_MLS_TYPE_EQUAL:
373101099Srwatson		case MAC_MLS_TYPE_HIGH:
374101099Srwatson		case MAC_MLS_TYPE_LOW:
375172955Srwatson			if (mm->mm_rangehigh.mme_level != 0 ||
376105643Srwatson			    !MAC_MLS_BIT_SET_EMPTY(
377172955Srwatson			    mm->mm_rangehigh.mme_compartments))
378101099Srwatson				return (EINVAL);
379101099Srwatson			break;
380101099Srwatson
381101099Srwatson		default:
382101099Srwatson			return (EINVAL);
383101099Srwatson		}
384172955Srwatson		if (!mls_dominate_element(&mm->mm_rangehigh,
385172955Srwatson		    &mm->mm_rangelow))
386101099Srwatson			return (EINVAL);
387101099Srwatson	} else {
388172955Srwatson		if (mm->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
389172955Srwatson		    mm->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
390101099Srwatson			return (EINVAL);
391101099Srwatson	}
392101099Srwatson
393101099Srwatson	return (0);
394101099Srwatson}
395101099Srwatson
396101099Srwatsonstatic void
397172955Srwatsonmls_set_range(struct mac_mls *mm, u_short typelow, u_short levellow,
398172955Srwatson    u_char *compartmentslow, u_short typehigh, u_short levelhigh,
399172955Srwatson    u_char *compartmentshigh)
400101099Srwatson{
401101099Srwatson
402172955Srwatson	mm->mm_rangelow.mme_type = typelow;
403172955Srwatson	mm->mm_rangelow.mme_level = levellow;
404105643Srwatson	if (compartmentslow != NULL)
405181217Srwatson		memcpy(mm->mm_rangelow.mme_compartments, compartmentslow,
406172955Srwatson		    sizeof(mm->mm_rangelow.mme_compartments));
407172955Srwatson	mm->mm_rangehigh.mme_type = typehigh;
408172955Srwatson	mm->mm_rangehigh.mme_level = levelhigh;
409105643Srwatson	if (compartmentshigh != NULL)
410181217Srwatson		memcpy(mm->mm_rangehigh.mme_compartments, compartmentshigh,
411172955Srwatson		    sizeof(mm->mm_rangehigh.mme_compartments));
412172955Srwatson	mm->mm_flags |= MAC_MLS_FLAG_RANGE;
413101099Srwatson}
414101099Srwatson
415101099Srwatsonstatic void
416172955Srwatsonmls_set_effective(struct mac_mls *mm, u_short type, u_short level,
417105643Srwatson    u_char *compartments)
418101099Srwatson{
419101099Srwatson
420172955Srwatson	mm->mm_effective.mme_type = type;
421172955Srwatson	mm->mm_effective.mme_level = level;
422105643Srwatson	if (compartments != NULL)
423172955Srwatson		memcpy(mm->mm_effective.mme_compartments, compartments,
424172955Srwatson		    sizeof(mm->mm_effective.mme_compartments));
425172955Srwatson	mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
426101099Srwatson}
427101099Srwatson
428101099Srwatsonstatic void
429172955Srwatsonmls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
430101099Srwatson{
431105643Srwatson
432101099Srwatson	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
433172955Srwatson	    ("mls_copy_range: labelfrom not range"));
434101099Srwatson
435101099Srwatson	labelto->mm_rangelow = labelfrom->mm_rangelow;
436101099Srwatson	labelto->mm_rangehigh = labelfrom->mm_rangehigh;
437101099Srwatson	labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
438101099Srwatson}
439101099Srwatson
440101099Srwatsonstatic void
441172955Srwatsonmls_copy_effective(struct mac_mls *labelfrom, struct mac_mls *labelto)
442101099Srwatson{
443101099Srwatson
444132232Srwatson	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
445172955Srwatson	    ("mls_copy_effective: labelfrom not effective"));
446101099Srwatson
447132232Srwatson	labelto->mm_effective = labelfrom->mm_effective;
448132232Srwatson	labelto->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
449101099Srwatson}
450101099Srwatson
451105656Srwatsonstatic void
452172955Srwatsonmls_copy(struct mac_mls *source, struct mac_mls *dest)
453105656Srwatson{
454105656Srwatson
455132232Srwatson	if (source->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
456172955Srwatson		mls_copy_effective(source, dest);
457105656Srwatson	if (source->mm_flags & MAC_MLS_FLAG_RANGE)
458172955Srwatson		mls_copy_range(source, dest);
459105656Srwatson}
460105656Srwatson
461101099Srwatson/*
462101099Srwatson * Policy module operations.
463101099Srwatson */
464101099Srwatsonstatic void
465172955Srwatsonmls_init(struct mac_policy_conf *conf)
466101099Srwatson{
467101099Srwatson
468122879Srwatson	zone_mls = uma_zcreate("mac_mls", sizeof(struct mac_mls), NULL,
469122879Srwatson	    NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
470101099Srwatson}
471101099Srwatson
472101099Srwatson/*
473101099Srwatson * Label operations.
474101099Srwatson */
475101099Srwatsonstatic void
476172955Srwatsonmls_init_label(struct label *label)
477101099Srwatson{
478101099Srwatson
479132781Skan	SLOT_SET(label, mls_alloc(M_WAITOK));
480101099Srwatson}
481101099Srwatson
482101099Srwatsonstatic int
483172955Srwatsonmls_init_label_waitcheck(struct label *label, int flag)
484101099Srwatson{
485101099Srwatson
486132781Skan	SLOT_SET(label, mls_alloc(flag));
487101099Srwatson	if (SLOT(label) == NULL)
488101099Srwatson		return (ENOMEM);
489101099Srwatson
490101099Srwatson	return (0);
491101099Srwatson}
492101099Srwatson
493101099Srwatsonstatic void
494172955Srwatsonmls_destroy_label(struct label *label)
495101099Srwatson{
496101099Srwatson
497101099Srwatson	mls_free(SLOT(label));
498132781Skan	SLOT_SET(label, NULL);
499101099Srwatson}
500101099Srwatson
501105696Srwatson/*
502172955Srwatson * mls_element_to_string() accepts an sbuf and MLS element.  It converts the
503172955Srwatson * MLS element to a string and stores the result in the sbuf; if there isn't
504172955Srwatson * space in the sbuf, -1 is returned.
505105696Srwatson */
506115497Srwatsonstatic int
507172955Srwatsonmls_element_to_string(struct sbuf *sb, struct mac_mls_element *element)
508105696Srwatson{
509115497Srwatson	int i, first;
510105696Srwatson
511105696Srwatson	switch (element->mme_type) {
512105696Srwatson	case MAC_MLS_TYPE_HIGH:
513115497Srwatson		return (sbuf_printf(sb, "high"));
514105696Srwatson
515105696Srwatson	case MAC_MLS_TYPE_LOW:
516115497Srwatson		return (sbuf_printf(sb, "low"));
517105696Srwatson
518105696Srwatson	case MAC_MLS_TYPE_EQUAL:
519115497Srwatson		return (sbuf_printf(sb, "equal"));
520105696Srwatson
521105696Srwatson	case MAC_MLS_TYPE_LEVEL:
522115497Srwatson		if (sbuf_printf(sb, "%d", element->mme_level) == -1)
523115497Srwatson			return (-1);
524115497Srwatson
525115497Srwatson		first = 1;
526115497Srwatson		for (i = 1; i <= MAC_MLS_MAX_COMPARTMENTS; i++) {
527115497Srwatson			if (MAC_MLS_BIT_TEST(i, element->mme_compartments)) {
528115497Srwatson				if (first) {
529115497Srwatson					if (sbuf_putc(sb, ':') == -1)
530115497Srwatson						return (-1);
531115497Srwatson					if (sbuf_printf(sb, "%d", i) == -1)
532115497Srwatson						return (-1);
533115497Srwatson					first = 0;
534115497Srwatson				} else {
535115497Srwatson					if (sbuf_printf(sb, "+%d", i) == -1)
536115497Srwatson						return (-1);
537115497Srwatson				}
538115497Srwatson			}
539105696Srwatson		}
540115497Srwatson		return (0);
541105696Srwatson
542105696Srwatson	default:
543172955Srwatson		panic("mls_element_to_string: invalid type (%d)",
544105696Srwatson		    element->mme_type);
545105696Srwatson	}
546105696Srwatson}
547105696Srwatson
548115497Srwatson/*
549172955Srwatson * mls_to_string() converts an MLS label to a string, and places the results
550172955Srwatson * in the passed sbuf.  It returns 0 on success, or EINVAL if there isn't
551172955Srwatson * room in the sbuf.  Note: the sbuf will be modified even in a failure case,
552172955Srwatson * so the caller may need to revert the sbuf by restoring the offset if
553172955Srwatson * that's undesired.
554115497Srwatson */
555115497Srwatsonstatic int
556172955Srwatsonmls_to_string(struct sbuf *sb, struct mac_mls *mm)
557105696Srwatson{
558105696Srwatson
559172955Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
560172955Srwatson		if (mls_element_to_string(sb, &mm->mm_effective) == -1)
561105696Srwatson			return (EINVAL);
562105696Srwatson	}
563105696Srwatson
564172955Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
565116701Srwatson		if (sbuf_putc(sb, '(') == -1)
566105696Srwatson			return (EINVAL);
567105696Srwatson
568172955Srwatson		if (mls_element_to_string(sb, &mm->mm_rangelow) == -1)
569105696Srwatson			return (EINVAL);
570105696Srwatson
571116701Srwatson		if (sbuf_putc(sb, '-') == -1)
572105696Srwatson			return (EINVAL);
573105696Srwatson
574172955Srwatson		if (mls_element_to_string(sb, &mm->mm_rangehigh) == -1)
575105696Srwatson			return (EINVAL);
576105696Srwatson
577116701Srwatson		if (sbuf_putc(sb, ')') == -1)
578105696Srwatson			return (EINVAL);
579105696Srwatson	}
580105696Srwatson
581105696Srwatson	return (0);
582105696Srwatson}
583105696Srwatson
584101099Srwatsonstatic int
585172955Srwatsonmls_externalize_label(struct label *label, char *element_name,
586116701Srwatson    struct sbuf *sb, int *claimed)
587101099Srwatson{
588172955Srwatson	struct mac_mls *mm;
589101099Srwatson
590105696Srwatson	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
591105696Srwatson		return (0);
592105696Srwatson
593105696Srwatson	(*claimed)++;
594105696Srwatson
595172955Srwatson	mm = SLOT(label);
596101099Srwatson
597172955Srwatson	return (mls_to_string(sb, mm));
598105696Srwatson}
599105696Srwatson
600105696Srwatsonstatic int
601172955Srwatsonmls_parse_element(struct mac_mls_element *element, char *string)
602101099Srwatson{
603115395Srwatson	char *compartment, *end, *level;
604115395Srwatson	int value;
605105696Srwatson
606172955Srwatson	if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) {
607105696Srwatson		element->mme_type = MAC_MLS_TYPE_HIGH;
608105696Srwatson		element->mme_level = MAC_MLS_TYPE_UNDEF;
609172955Srwatson	} else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) {
610105696Srwatson		element->mme_type = MAC_MLS_TYPE_LOW;
611105696Srwatson		element->mme_level = MAC_MLS_TYPE_UNDEF;
612105696Srwatson	} else if (strcmp(string, "equal") == 0 ||
613105696Srwatson	    strcmp(string, "eq") == 0) {
614105696Srwatson		element->mme_type = MAC_MLS_TYPE_EQUAL;
615105696Srwatson		element->mme_level = MAC_MLS_TYPE_UNDEF;
616105696Srwatson	} else {
617115395Srwatson		element->mme_type = MAC_MLS_TYPE_LEVEL;
618105696Srwatson
619115395Srwatson		/*
620115395Srwatson		 * Numeric level piece of the element.
621115395Srwatson		 */
622115395Srwatson		level = strsep(&string, ":");
623115395Srwatson		value = strtol(level, &end, 10);
624115395Srwatson		if (end == level || *end != '\0')
625105696Srwatson			return (EINVAL);
626115395Srwatson		if (value < 0 || value > 65535)
627115395Srwatson			return (EINVAL);
628115395Srwatson		element->mme_level = value;
629105696Srwatson
630115395Srwatson		/*
631172955Srwatson		 * Optional compartment piece of the element.  If none are
632172955Srwatson		 * included, we assume that the label has no compartments.
633115395Srwatson		 */
634115395Srwatson		if (string == NULL)
635115395Srwatson			return (0);
636115395Srwatson		if (*string == '\0')
637115395Srwatson			return (0);
638105696Srwatson
639115395Srwatson		while ((compartment = strsep(&string, "+")) != NULL) {
640115395Srwatson			value = strtol(compartment, &end, 10);
641115395Srwatson			if (compartment == end || *end != '\0')
642105696Srwatson				return (EINVAL);
643115395Srwatson			if (value < 1 || value > MAC_MLS_MAX_COMPARTMENTS)
644105696Srwatson				return (EINVAL);
645115395Srwatson			MAC_MLS_BIT_SET(value, element->mme_compartments);
646105696Srwatson		}
647105696Srwatson	}
648105696Srwatson
649105696Srwatson	return (0);
650105696Srwatson}
651105696Srwatson
652105696Srwatson/*
653172955Srwatson * Note: destructively consumes the string, make a local copy before calling
654172955Srwatson * if that's a problem.
655105696Srwatson */
656105696Srwatsonstatic int
657172955Srwatsonmls_parse(struct mac_mls *mm, char *string)
658105696Srwatson{
659132232Srwatson	char *rangehigh, *rangelow, *effective;
660101099Srwatson	int error;
661101099Srwatson
662132232Srwatson	effective = strsep(&string, "(");
663132232Srwatson	if (*effective == '\0')
664132232Srwatson		effective = NULL;
665115395Srwatson
666115395Srwatson	if (string != NULL) {
667115395Srwatson		rangelow = strsep(&string, "-");
668115395Srwatson		if (string == NULL)
669105696Srwatson			return (EINVAL);
670115395Srwatson		rangehigh = strsep(&string, ")");
671115395Srwatson		if (string == NULL)
672105696Srwatson			return (EINVAL);
673115395Srwatson		if (*string != '\0')
674105696Srwatson			return (EINVAL);
675115414Srwatson	} else {
676115414Srwatson		rangelow = NULL;
677115414Srwatson		rangehigh = NULL;
678105696Srwatson	}
679115395Srwatson
680105696Srwatson	KASSERT((rangelow != NULL && rangehigh != NULL) ||
681105696Srwatson	    (rangelow == NULL && rangehigh == NULL),
682172955Srwatson	    ("mls_parse: range mismatch"));
683101099Srwatson
684172955Srwatson	bzero(mm, sizeof(*mm));
685132232Srwatson	if (effective != NULL) {
686172955Srwatson		error = mls_parse_element(&mm->mm_effective, effective);
687105696Srwatson		if (error)
688105696Srwatson			return (error);
689172955Srwatson		mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
690105696Srwatson	}
691105696Srwatson
692105696Srwatson	if (rangelow != NULL) {
693181217Srwatson		error = mls_parse_element(&mm->mm_rangelow, rangelow);
694105696Srwatson		if (error)
695105696Srwatson			return (error);
696181217Srwatson		error = mls_parse_element(&mm->mm_rangehigh, rangehigh);
697105696Srwatson		if (error)
698105696Srwatson			return (error);
699172955Srwatson		mm->mm_flags |= MAC_MLS_FLAG_RANGE;
700105696Srwatson	}
701105696Srwatson
702172955Srwatson	error = mls_valid(mm);
703101099Srwatson	if (error)
704101099Srwatson		return (error);
705101099Srwatson
706105696Srwatson	return (0);
707105696Srwatson}
708101099Srwatson
709105696Srwatsonstatic int
710172955Srwatsonmls_internalize_label(struct label *label, char *element_name,
711105696Srwatson    char *element_data, int *claimed)
712105696Srwatson{
713172955Srwatson	struct mac_mls *mm, mm_temp;
714105696Srwatson	int error;
715105696Srwatson
716105696Srwatson	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
717105696Srwatson		return (0);
718105696Srwatson
719105696Srwatson	(*claimed)++;
720105696Srwatson
721172955Srwatson	error = mls_parse(&mm_temp, element_data);
722105696Srwatson	if (error)
723105696Srwatson		return (error);
724105696Srwatson
725172955Srwatson	mm = SLOT(label);
726172955Srwatson	*mm = mm_temp;
727105696Srwatson
728101099Srwatson	return (0);
729101099Srwatson}
730101099Srwatson
731105696Srwatsonstatic void
732172955Srwatsonmls_copy_label(struct label *src, struct label *dest)
733105696Srwatson{
734105696Srwatson
735105696Srwatson	*SLOT(dest) = *SLOT(src);
736105696Srwatson}
737105696Srwatson
738101099Srwatson/*
739173138Srwatson * Object-specific entry point implementations are sorted alphabetically by
740173138Srwatson * object type name and then by operation.
741101099Srwatson */
742173138Srwatsonstatic int
743173138Srwatsonmls_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel,
744173138Srwatson     struct ifnet *ifp, struct label *ifplabel)
745173138Srwatson{
746173138Srwatson	struct mac_mls *a, *b;
747173138Srwatson
748173138Srwatson	if (!mls_enabled)
749173138Srwatson		return (0);
750173138Srwatson
751173138Srwatson	a = SLOT(dlabel);
752173138Srwatson	b = SLOT(ifplabel);
753173138Srwatson
754173138Srwatson	if (mls_equal_effective(a, b))
755173138Srwatson		return (0);
756173138Srwatson	return (EACCES);
757173138Srwatson}
758173138Srwatson
759101099Srwatsonstatic void
760173138Srwatsonmls_bpfdesc_create(struct ucred *cred, struct bpf_d *d, struct label *dlabel)
761173138Srwatson{
762173138Srwatson	struct mac_mls *source, *dest;
763173138Srwatson
764173138Srwatson	source = SLOT(cred->cr_label);
765173138Srwatson	dest = SLOT(dlabel);
766173138Srwatson
767173138Srwatson	mls_copy_effective(source, dest);
768173138Srwatson}
769173138Srwatson
770173138Srwatsonstatic void
771173138Srwatsonmls_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel,
772173138Srwatson    struct mbuf *m, struct label *mlabel)
773173138Srwatson{
774173138Srwatson	struct mac_mls *source, *dest;
775173138Srwatson
776173138Srwatson	source = SLOT(dlabel);
777173138Srwatson	dest = SLOT(mlabel);
778173138Srwatson
779173138Srwatson	mls_copy_effective(source, dest);
780173138Srwatson}
781173138Srwatson
782184407Srwatsonstatic void
783184407Srwatsonmls_cred_associate_nfsd(struct ucred *cred)
784184407Srwatson{
785184407Srwatson	struct mac_mls *label;
786184407Srwatson
787184407Srwatson	label = SLOT(cred->cr_label);
788184407Srwatson	mls_set_effective(label, MAC_MLS_TYPE_LOW, 0, NULL);
789184407Srwatson	mls_set_range(label, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
790184407Srwatson	    NULL);
791184407Srwatson}
792184407Srwatson
793173138Srwatsonstatic int
794173138Srwatsonmls_cred_check_relabel(struct ucred *cred, struct label *newlabel)
795173138Srwatson{
796173138Srwatson	struct mac_mls *subj, *new;
797173138Srwatson	int error;
798173138Srwatson
799173138Srwatson	subj = SLOT(cred->cr_label);
800173138Srwatson	new = SLOT(newlabel);
801173138Srwatson
802173138Srwatson	/*
803173138Srwatson	 * If there is an MLS label update for the credential, it may be an
804173138Srwatson	 * update of effective, range, or both.
805173138Srwatson	 */
806173138Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
807173138Srwatson	if (error)
808173138Srwatson		return (error);
809173138Srwatson
810173138Srwatson	/*
811173138Srwatson	 * If the MLS label is to be changed, authorize as appropriate.
812173138Srwatson	 */
813173138Srwatson	if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
814173138Srwatson		/*
815173138Srwatson		 * If the change request modifies both the MLS label
816173138Srwatson		 * effective and range, check that the new effective will be
817173138Srwatson		 * in the new range.
818173138Srwatson		 */
819173138Srwatson		if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) ==
820173138Srwatson		    MAC_MLS_FLAGS_BOTH && !mls_effective_in_range(new, new))
821173138Srwatson			return (EINVAL);
822173138Srwatson
823173138Srwatson		/*
824173138Srwatson		 * To change the MLS effective label on a credential, the new
825173138Srwatson		 * effective label must be in the current range.
826173138Srwatson		 */
827173138Srwatson		if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE &&
828173138Srwatson		    !mls_effective_in_range(new, subj))
829173138Srwatson			return (EPERM);
830173138Srwatson
831173138Srwatson		/*
832173138Srwatson		 * To change the MLS range label on a credential, the new
833173138Srwatson		 * range must be in the current range.
834173138Srwatson		 */
835173138Srwatson		if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
836173138Srwatson		    !mls_range_in_range(new, subj))
837173138Srwatson			return (EPERM);
838173138Srwatson
839173138Srwatson		/*
840173138Srwatson		 * To have EQUAL in any component of the new credential MLS
841173138Srwatson		 * label, the subject must already have EQUAL in their label.
842173138Srwatson		 */
843173138Srwatson		if (mls_contains_equal(new)) {
844173138Srwatson			error = mls_subject_privileged(subj);
845173138Srwatson			if (error)
846173138Srwatson				return (error);
847173138Srwatson		}
848173138Srwatson	}
849173138Srwatson
850173138Srwatson	return (0);
851173138Srwatson}
852173138Srwatson
853173138Srwatsonstatic int
854173138Srwatsonmls_cred_check_visible(struct ucred *cr1, struct ucred *cr2)
855173138Srwatson{
856173138Srwatson	struct mac_mls *subj, *obj;
857173138Srwatson
858173138Srwatson	if (!mls_enabled)
859173138Srwatson		return (0);
860173138Srwatson
861173138Srwatson	subj = SLOT(cr1->cr_label);
862173138Srwatson	obj = SLOT(cr2->cr_label);
863173138Srwatson
864173138Srwatson	/* XXX: range */
865173138Srwatson	if (!mls_dominate_effective(subj, obj))
866173138Srwatson		return (ESRCH);
867173138Srwatson
868173138Srwatson	return (0);
869173138Srwatson}
870173138Srwatson
871173138Srwatsonstatic void
872184407Srwatsonmls_cred_create_init(struct ucred *cred)
873184407Srwatson{
874184407Srwatson	struct mac_mls *dest;
875184407Srwatson
876184407Srwatson	dest = SLOT(cred->cr_label);
877184407Srwatson
878184407Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_LOW, 0, NULL);
879184407Srwatson	mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
880184407Srwatson	    NULL);
881184407Srwatson}
882184407Srwatson
883184407Srwatsonstatic void
884184407Srwatsonmls_cred_create_swapper(struct ucred *cred)
885184407Srwatson{
886184407Srwatson	struct mac_mls *dest;
887184407Srwatson
888184407Srwatson	dest = SLOT(cred->cr_label);
889184407Srwatson
890184407Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
891184407Srwatson	mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
892184407Srwatson	    NULL);
893184407Srwatson}
894184407Srwatson
895184407Srwatsonstatic void
896173138Srwatsonmls_cred_relabel(struct ucred *cred, struct label *newlabel)
897173138Srwatson{
898173138Srwatson	struct mac_mls *source, *dest;
899173138Srwatson
900173138Srwatson	source = SLOT(newlabel);
901173138Srwatson	dest = SLOT(cred->cr_label);
902173138Srwatson
903173138Srwatson	mls_copy(source, dest);
904173138Srwatson}
905173138Srwatson
906173138Srwatsonstatic void
907172955Srwatsonmls_devfs_create_device(struct ucred *cred, struct mount *mp,
908168976Srwatson    struct cdev *dev, struct devfs_dirent *de, struct label *delabel)
909101099Srwatson{
910172955Srwatson	struct mac_mls *mm;
911231378Sed	const char *dn;
912101099Srwatson	int mls_type;
913101099Srwatson
914172955Srwatson	mm = SLOT(delabel);
915231378Sed	dn = devtoname(dev);
916231378Sed	if (strcmp(dn, "null") == 0 ||
917231378Sed	    strcmp(dn, "zero") == 0 ||
918231378Sed	    strcmp(dn, "random") == 0 ||
919231378Sed	    strncmp(dn, "fd/", strlen("fd/")) == 0)
920101099Srwatson		mls_type = MAC_MLS_TYPE_EQUAL;
921231378Sed	else if (strcmp(dn, "kmem") == 0 ||
922231378Sed	    strcmp(dn, "mem") == 0)
923101099Srwatson		mls_type = MAC_MLS_TYPE_HIGH;
924105606Srwatson	else if (ptys_equal &&
925231378Sed	    (strncmp(dn, "ttyp", strlen("ttyp")) == 0 ||
926231378Sed	    strncmp(dn, "pts/", strlen("pts/")) == 0 ||
927231378Sed	    strncmp(dn, "ptyp", strlen("ptyp")) == 0))
928105606Srwatson		mls_type = MAC_MLS_TYPE_EQUAL;
929101099Srwatson	else
930101099Srwatson		mls_type = MAC_MLS_TYPE_LOW;
931172955Srwatson	mls_set_effective(mm, mls_type, 0, NULL);
932101099Srwatson}
933101099Srwatson
934101099Srwatsonstatic void
935172955Srwatsonmls_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
936172955Srwatson    struct devfs_dirent *de, struct label *delabel)
937101099Srwatson{
938172955Srwatson	struct mac_mls *mm;
939101099Srwatson
940172955Srwatson	mm = SLOT(delabel);
941172955Srwatson	mls_set_effective(mm, MAC_MLS_TYPE_LOW, 0, NULL);
942101099Srwatson}
943101099Srwatson
944101099Srwatsonstatic void
945172955Srwatsonmls_devfs_create_symlink(struct ucred *cred, struct mount *mp,
946107698Srwatson    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
947122563Srwatson    struct label *delabel)
948104535Srwatson{
949104535Srwatson	struct mac_mls *source, *dest;
950104535Srwatson
951122524Srwatson	source = SLOT(cred->cr_label);
952104535Srwatson	dest = SLOT(delabel);
953104535Srwatson
954172955Srwatson	mls_copy_effective(source, dest);
955104535Srwatson}
956104535Srwatson
957104535Srwatsonstatic void
958172955Srwatsonmls_devfs_update(struct mount *mp, struct devfs_dirent *de,
959168976Srwatson    struct label *delabel, struct vnode *vp, struct label *vplabel)
960101099Srwatson{
961101099Srwatson	struct mac_mls *source, *dest;
962101099Srwatson
963168976Srwatson	source = SLOT(vplabel);
964168976Srwatson	dest = SLOT(delabel);
965101099Srwatson
966172955Srwatson	mls_copy_effective(source, dest);
967101099Srwatson}
968101099Srwatson
969101099Srwatsonstatic void
970172955Srwatsonmls_devfs_vnode_associate(struct mount *mp, struct label *mplabel,
971105988Srwatson    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
972168976Srwatson    struct label *vplabel)
973101099Srwatson{
974101099Srwatson	struct mac_mls *source, *dest;
975101099Srwatson
976105988Srwatson	source = SLOT(delabel);
977168976Srwatson	dest = SLOT(vplabel);
978101099Srwatson
979172955Srwatson	mls_copy_effective(source, dest);
980101099Srwatson}
981101099Srwatson
982101099Srwatsonstatic int
983173138Srwatsonmls_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp,
984173138Srwatson    struct label *ifplabel, struct label *newlabel)
985101099Srwatson{
986173138Srwatson	struct mac_mls *subj, *new;
987173138Srwatson	int error;
988101099Srwatson
989173138Srwatson	subj = SLOT(cred->cr_label);
990173138Srwatson	new = SLOT(newlabel);
991101099Srwatson
992173138Srwatson	/*
993173138Srwatson	 * If there is an MLS label update for the interface, it may be an
994173138Srwatson	 * update of effective, range, or both.
995173138Srwatson	 */
996173138Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
997173138Srwatson	if (error)
998101099Srwatson		return (error);
999101099Srwatson
1000173138Srwatson	/*
1001173138Srwatson	 * Relabeling network interfaces requires MLS privilege.
1002173138Srwatson	 */
1003175747Srwatson	return (mls_subject_privileged(subj));
1004101099Srwatson}
1005101099Srwatson
1006105988Srwatsonstatic int
1007173138Srwatsonmls_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel,
1008173138Srwatson    struct mbuf *m, struct label *mlabel)
1009105988Srwatson{
1010173138Srwatson	struct mac_mls *p, *i;
1011105988Srwatson
1012173138Srwatson	if (!mls_enabled)
1013105988Srwatson		return (0);
1014105988Srwatson
1015173138Srwatson	p = SLOT(mlabel);
1016173138Srwatson	i = SLOT(ifplabel);
1017105988Srwatson
1018173138Srwatson	return (mls_effective_in_range(p, i) ? 0 : EACCES);
1019105988Srwatson}
1020105988Srwatson
1021101099Srwatsonstatic void
1022173138Srwatsonmls_ifnet_create(struct ifnet *ifp, struct label *ifplabel)
1023122875Srwatson{
1024173138Srwatson	struct mac_mls *dest;
1025173138Srwatson	int type;
1026122875Srwatson
1027173138Srwatson	dest = SLOT(ifplabel);
1028122875Srwatson
1029173138Srwatson	if (ifp->if_type == IFT_LOOP)
1030173138Srwatson		type = MAC_MLS_TYPE_EQUAL;
1031173138Srwatson	else
1032173138Srwatson		type = MAC_MLS_TYPE_LOW;
1033173138Srwatson
1034173138Srwatson	mls_set_effective(dest, type, 0, NULL);
1035173138Srwatson	mls_set_range(dest, type, 0, NULL, type, 0, NULL);
1036122875Srwatson}
1037122875Srwatson
1038122875Srwatsonstatic void
1039173138Srwatsonmls_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel,
1040168976Srwatson    struct mbuf *m, struct label *mlabel)
1041101099Srwatson{
1042101099Srwatson	struct mac_mls *source, *dest;
1043101099Srwatson
1044173138Srwatson	source = SLOT(ifplabel);
1045168976Srwatson	dest = SLOT(mlabel);
1046101099Srwatson
1047172955Srwatson	mls_copy_effective(source, dest);
1048101099Srwatson}
1049101099Srwatson
1050101099Srwatsonstatic void
1051173138Srwatsonmls_ifnet_relabel(struct ucred *cred, struct ifnet *ifp,
1052173138Srwatson    struct label *ifplabel, struct label *newlabel)
1053101099Srwatson{
1054101099Srwatson	struct mac_mls *source, *dest;
1055101099Srwatson
1056173138Srwatson	source = SLOT(newlabel);
1057173138Srwatson	dest = SLOT(ifplabel);
1058101099Srwatson
1059173138Srwatson	mls_copy(source, dest);
1060101099Srwatson}
1061101099Srwatson
1062173138Srwatsonstatic int
1063173138Srwatsonmls_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel,
1064173138Srwatson    struct mbuf *m, struct label *mlabel)
1065101099Srwatson{
1066173138Srwatson	struct mac_mls *p, *i;
1067101099Srwatson
1068173138Srwatson	if (!mls_enabled)
1069173138Srwatson		return (0);
1070101099Srwatson
1071173138Srwatson	p = SLOT(mlabel);
1072173138Srwatson	i = SLOT(inplabel);
1073173138Srwatson
1074173138Srwatson	return (mls_equal_effective(p, i) ? 0 : EACCES);
1075101099Srwatson}
1076101099Srwatson
1077183980Sbzstatic int
1078183980Sbzmls_inpcb_check_visible(struct ucred *cred, struct inpcb *inp,
1079183980Sbz    struct label *inplabel)
1080183980Sbz{
1081183980Sbz	struct mac_mls *subj, *obj;
1082183980Sbz
1083183980Sbz	if (!mls_enabled)
1084183980Sbz		return (0);
1085183980Sbz
1086183980Sbz	subj = SLOT(cred->cr_label);
1087183980Sbz	obj = SLOT(inplabel);
1088183980Sbz
1089183980Sbz	if (!mls_dominate_effective(subj, obj))
1090183980Sbz		return (ENOENT);
1091183980Sbz
1092183980Sbz	return (0);
1093183980Sbz}
1094183980Sbz
1095101099Srwatsonstatic void
1096173138Srwatsonmls_inpcb_create(struct socket *so, struct label *solabel, struct inpcb *inp,
1097173138Srwatson    struct label *inplabel)
1098145855Srwatson{
1099145855Srwatson	struct mac_mls *source, *dest;
1100145855Srwatson
1101173138Srwatson	source = SLOT(solabel);
1102173138Srwatson	dest = SLOT(inplabel);
1103145855Srwatson
1104172955Srwatson	mls_copy_effective(source, dest);
1105145855Srwatson}
1106145855Srwatson
1107145855Srwatsonstatic void
1108173138Srwatsonmls_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel,
1109173138Srwatson    struct mbuf *m, struct label *mlabel)
1110101099Srwatson{
1111101099Srwatson	struct mac_mls *source, *dest;
1112101099Srwatson
1113173138Srwatson	source = SLOT(inplabel);
1114173138Srwatson	dest = SLOT(mlabel);
1115101099Srwatson
1116172955Srwatson	mls_copy_effective(source, dest);
1117101099Srwatson}
1118101099Srwatson
1119101099Srwatsonstatic void
1120173138Srwatsonmls_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1121173138Srwatson    struct inpcb *inp, struct label *inplabel)
1122101099Srwatson{
1123101099Srwatson	struct mac_mls *source, *dest;
1124101099Srwatson
1125193391Srwatson	SOCK_LOCK_ASSERT(so);
1126193391Srwatson
1127173138Srwatson	source = SLOT(solabel);
1128173138Srwatson	dest = SLOT(inplabel);
1129101099Srwatson
1130172955Srwatson	mls_copy(source, dest);
1131101099Srwatson}
1132101099Srwatson
1133101099Srwatsonstatic void
1134184308Srwatsonmls_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1135184308Srwatson    struct label *q6label)
1136184308Srwatson{
1137184308Srwatson	struct mac_mls *source, *dest;
1138184308Srwatson
1139184308Srwatson	source = SLOT(mlabel);
1140184308Srwatson	dest = SLOT(q6label);
1141184308Srwatson
1142184308Srwatson	mls_copy_effective(source, dest);
1143184308Srwatson}
1144184308Srwatson
1145184308Srwatsonstatic int
1146184308Srwatsonmls_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1147184308Srwatson    struct label *q6label)
1148184308Srwatson{
1149184308Srwatson	struct mac_mls *a, *b;
1150184308Srwatson
1151184308Srwatson	a = SLOT(q6label);
1152184308Srwatson	b = SLOT(mlabel);
1153184308Srwatson
1154184308Srwatson	return (mls_equal_effective(a, b));
1155184308Srwatson}
1156184308Srwatson
1157184308Srwatsonstatic void
1158184308Srwatsonmls_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m,
1159184308Srwatson    struct label *mlabel)
1160184308Srwatson{
1161184308Srwatson	struct mac_mls *source, *dest;
1162184308Srwatson
1163184308Srwatson	source = SLOT(q6label);
1164184308Srwatson	dest = SLOT(mlabel);
1165184308Srwatson
1166184308Srwatson	/* Just use the head, since we require them all to match. */
1167184308Srwatson	mls_copy_effective(source, dest);
1168184308Srwatson}
1169184308Srwatson
1170184308Srwatsonstatic void
1171184308Srwatsonmls_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1172184308Srwatson    struct label *q6label)
1173184308Srwatson{
1174184308Srwatson
1175184308Srwatson	/* NOOP: we only accept matching labels, so no need to update */
1176184308Srwatson}
1177184308Srwatson
1178184308Srwatsonstatic void
1179179781Srwatsonmls_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q,
1180179781Srwatson    struct label *qlabel)
1181101099Srwatson{
1182101099Srwatson	struct mac_mls *source, *dest;
1183101099Srwatson
1184173138Srwatson	source = SLOT(mlabel);
1185179781Srwatson	dest = SLOT(qlabel);
1186101099Srwatson
1187173138Srwatson	mls_copy_effective(source, dest);
1188101099Srwatson}
1189101099Srwatson
1190173138Srwatsonstatic int
1191179781Srwatsonmls_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
1192179781Srwatson    struct label *qlabel)
1193101099Srwatson{
1194173138Srwatson	struct mac_mls *a, *b;
1195101099Srwatson
1196179781Srwatson	a = SLOT(qlabel);
1197173138Srwatson	b = SLOT(mlabel);
1198101099Srwatson
1199173138Srwatson	return (mls_equal_effective(a, b));
1200101099Srwatson}
1201101099Srwatson
1202140629Srwatsonstatic void
1203179781Srwatsonmls_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m,
1204173138Srwatson    struct label *mlabel)
1205140629Srwatson{
1206140629Srwatson	struct mac_mls *source, *dest;
1207140629Srwatson
1208179781Srwatson	source = SLOT(qlabel);
1209173138Srwatson	dest = SLOT(mlabel);
1210140629Srwatson
1211173138Srwatson	/* Just use the head, since we require them all to match. */
1212172955Srwatson	mls_copy_effective(source, dest);
1213140629Srwatson}
1214140629Srwatson
1215140629Srwatsonstatic void
1216179781Srwatsonmls_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
1217179781Srwatson    struct label *qlabel)
1218140629Srwatson{
1219140629Srwatson
1220173138Srwatson	/* NOOP: we only accept matching labels, so no need to update */
1221140629Srwatson}
1222140629Srwatson
1223173138Srwatsonstatic int
1224173138Srwatsonmls_mount_check_stat(struct ucred *cred, struct mount *mp,
1225173138Srwatson    struct label *mntlabel)
1226140629Srwatson{
1227173138Srwatson	struct mac_mls *subj, *obj;
1228140629Srwatson
1229173138Srwatson	if (!mls_enabled)
1230173138Srwatson		return (0);
1231140629Srwatson
1232173138Srwatson	subj = SLOT(cred->cr_label);
1233173138Srwatson	obj = SLOT(mntlabel);
1234140629Srwatson
1235173138Srwatson	if (!mls_dominate_effective(subj, obj))
1236173138Srwatson		return (EACCES);
1237140629Srwatson
1238173138Srwatson	return (0);
1239140629Srwatson}
1240140629Srwatson
1241101099Srwatsonstatic void
1242173138Srwatsonmls_mount_create(struct ucred *cred, struct mount *mp, struct label *mplabel)
1243101099Srwatson{
1244101099Srwatson	struct mac_mls *source, *dest;
1245101099Srwatson
1246173138Srwatson	source = SLOT(cred->cr_label);
1247173138Srwatson	dest = SLOT(mplabel);
1248101099Srwatson
1249172955Srwatson	mls_copy_effective(source, dest);
1250101099Srwatson}
1251101099Srwatson
1252101099Srwatsonstatic void
1253173138Srwatsonmls_netatalk_aarp_send(struct ifnet *ifp, struct label *ifplabel,
1254173138Srwatson    struct mbuf *m, struct label *mlabel)
1255101099Srwatson{
1256173138Srwatson	struct mac_mls *dest;
1257101099Srwatson
1258173138Srwatson	dest = SLOT(mlabel);
1259101099Srwatson
1260173138Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1261101099Srwatson}
1262101099Srwatson
1263101099Srwatsonstatic void
1264173138Srwatsonmls_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel,
1265173138Srwatson    struct mbuf *m, struct label *mlabel)
1266101099Srwatson{
1267101099Srwatson	struct mac_mls *dest;
1268101099Srwatson
1269173138Srwatson	dest = SLOT(mlabel);
1270101099Srwatson
1271173138Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1272101099Srwatson}
1273101099Srwatson
1274101099Srwatsonstatic void
1275173138Srwatsonmls_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1276173138Srwatson    struct mbuf *msend, struct label *msendlabel)
1277101099Srwatson{
1278101099Srwatson	struct mac_mls *source, *dest;
1279101099Srwatson
1280173138Srwatson	source = SLOT(mrecvlabel);
1281173138Srwatson	dest = SLOT(msendlabel);
1282101099Srwatson
1283172955Srwatson	mls_copy_effective(source, dest);
1284101099Srwatson}
1285101099Srwatson
1286101099Srwatsonstatic void
1287173138Srwatsonmls_netinet_firewall_send(struct mbuf *m, struct label *mlabel)
1288101099Srwatson{
1289173138Srwatson	struct mac_mls *dest;
1290101099Srwatson
1291168976Srwatson	dest = SLOT(mlabel);
1292101099Srwatson
1293173138Srwatson	/* XXX: where is the label for the firewall really comming from? */
1294173138Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1295101099Srwatson}
1296101099Srwatson
1297101099Srwatsonstatic void
1298172955Srwatsonmls_netinet_fragment(struct mbuf *m, struct label *mlabel, struct mbuf *frag,
1299172955Srwatson    struct label *fraglabel)
1300101099Srwatson{
1301101099Srwatson	struct mac_mls *source, *dest;
1302101099Srwatson
1303168976Srwatson	source = SLOT(mlabel);
1304168976Srwatson	dest = SLOT(fraglabel);
1305101099Srwatson
1306172955Srwatson	mls_copy_effective(source, dest);
1307101099Srwatson}
1308101099Srwatson
1309101099Srwatsonstatic void
1310173138Srwatsonmls_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1311173138Srwatson    struct mbuf *msend, struct label *msendlabel)
1312123607Srwatson{
1313123607Srwatson	struct mac_mls *source, *dest;
1314123607Srwatson
1315173138Srwatson	source = SLOT(mrecvlabel);
1316173138Srwatson	dest = SLOT(msendlabel);
1317123607Srwatson
1318172955Srwatson	mls_copy_effective(source, dest);
1319123607Srwatson}
1320123607Srwatson
1321123607Srwatsonstatic void
1322173138Srwatsonmls_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel,
1323168976Srwatson    struct mbuf *m, struct label *mlabel)
1324101099Srwatson{
1325173138Srwatson	struct mac_mls *dest;
1326101099Srwatson
1327168976Srwatson	dest = SLOT(mlabel);
1328101099Srwatson
1329173138Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1330101099Srwatson}
1331101099Srwatson
1332101099Srwatsonstatic void
1333173138Srwatsonmls_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel,
1334168976Srwatson    struct mbuf *m, struct label *mlabel)
1335101099Srwatson{
1336173138Srwatson	struct mac_mls *dest;
1337101099Srwatson
1338168976Srwatson	dest = SLOT(mlabel);
1339101099Srwatson
1340173138Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1341101099Srwatson}
1342101099Srwatson
1343101099Srwatsonstatic int
1344173138Srwatsonmls_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
1345173138Srwatson    struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1346101099Srwatson{
1347101099Srwatson
1348173138Srwatson	if (!mls_enabled)
1349173138Srwatson		return (0);
1350101099Srwatson
1351173138Srwatson	/* XXX: This will be implemented soon... */
1352173138Srwatson
1353173138Srwatson	return (0);
1354101099Srwatson}
1355101099Srwatson
1356173138Srwatsonstatic int
1357173138Srwatsonmls_pipe_check_poll(struct ucred *cred, struct pipepair *pp,
1358173138Srwatson    struct label *pplabel)
1359101099Srwatson{
1360173138Srwatson	struct mac_mls *subj, *obj;
1361101099Srwatson
1362173138Srwatson	if (!mls_enabled)
1363173138Srwatson		return (0);
1364101099Srwatson
1365173138Srwatson	subj = SLOT(cred->cr_label);
1366173138Srwatson	obj = SLOT(pplabel);
1367101099Srwatson
1368173138Srwatson	if (!mls_dominate_effective(subj, obj))
1369173138Srwatson		return (EACCES);
1370101099Srwatson
1371173138Srwatson	return (0);
1372101099Srwatson}
1373101099Srwatson
1374173138Srwatsonstatic int
1375173138Srwatsonmls_pipe_check_read(struct ucred *cred, struct pipepair *pp,
1376173138Srwatson    struct label *pplabel)
1377122875Srwatson{
1378173138Srwatson	struct mac_mls *subj, *obj;
1379122875Srwatson
1380173138Srwatson	if (!mls_enabled)
1381173138Srwatson		return (0);
1382122875Srwatson
1383173138Srwatson	subj = SLOT(cred->cr_label);
1384173138Srwatson	obj = SLOT(pplabel);
1385173138Srwatson
1386173138Srwatson	if (!mls_dominate_effective(subj, obj))
1387173138Srwatson		return (EACCES);
1388173138Srwatson
1389173138Srwatson	return (0);
1390122875Srwatson}
1391122875Srwatson
1392173138Srwatsonstatic int
1393173138Srwatsonmls_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
1394173138Srwatson    struct label *pplabel, struct label *newlabel)
1395173095Srwatson{
1396173138Srwatson	struct mac_mls *subj, *obj, *new;
1397173138Srwatson	int error;
1398173095Srwatson
1399173138Srwatson	new = SLOT(newlabel);
1400173138Srwatson	subj = SLOT(cred->cr_label);
1401173138Srwatson	obj = SLOT(pplabel);
1402173095Srwatson
1403173138Srwatson	/*
1404173138Srwatson	 * If there is an MLS label update for a pipe, it must be a effective
1405173138Srwatson	 * update.
1406173138Srwatson	 */
1407173138Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1408173138Srwatson	if (error)
1409173138Srwatson		return (error);
1410173095Srwatson
1411173138Srwatson	/*
1412173138Srwatson	 * To perform a relabel of a pipe (MLS label or not), MLS must
1413173138Srwatson	 * authorize the relabel.
1414173138Srwatson	 */
1415173138Srwatson	if (!mls_effective_in_range(obj, subj))
1416173138Srwatson		return (EPERM);
1417173095Srwatson
1418173138Srwatson	/*
1419173138Srwatson	 * If the MLS label is to be changed, authorize as appropriate.
1420173138Srwatson	 */
1421173138Srwatson	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1422173138Srwatson		/*
1423173138Srwatson		 * To change the MLS label on a pipe, the new pipe label must
1424173138Srwatson		 * be in the subject range.
1425173138Srwatson		 */
1426173138Srwatson		if (!mls_effective_in_range(new, subj))
1427173138Srwatson			return (EPERM);
1428173095Srwatson
1429173138Srwatson		/*
1430173138Srwatson		 * To change the MLS label on a pipe to be EQUAL, the subject
1431173138Srwatson		 * must have appropriate privilege.
1432173138Srwatson		 */
1433173138Srwatson		if (mls_contains_equal(new)) {
1434173138Srwatson			error = mls_subject_privileged(subj);
1435173138Srwatson			if (error)
1436173138Srwatson				return (error);
1437173138Srwatson		}
1438173138Srwatson	}
1439173138Srwatson
1440173138Srwatson	return (0);
1441173095Srwatson}
1442173095Srwatson
1443173138Srwatsonstatic int
1444173138Srwatsonmls_pipe_check_stat(struct ucred *cred, struct pipepair *pp,
1445173138Srwatson    struct label *pplabel)
1446173102Srwatson{
1447173138Srwatson	struct mac_mls *subj, *obj;
1448173102Srwatson
1449173138Srwatson	if (!mls_enabled)
1450173138Srwatson		return (0);
1451173102Srwatson
1452173138Srwatson	subj = SLOT(cred->cr_label);
1453173138Srwatson	obj = SLOT(pplabel);
1454173138Srwatson
1455173138Srwatson	if (!mls_dominate_effective(subj, obj))
1456173138Srwatson		return (EACCES);
1457173138Srwatson
1458173138Srwatson	return (0);
1459173102Srwatson}
1460173102Srwatson
1461173138Srwatsonstatic int
1462173138Srwatsonmls_pipe_check_write(struct ucred *cred, struct pipepair *pp,
1463173138Srwatson    struct label *pplabel)
1464162238Scsjp{
1465173138Srwatson	struct mac_mls *subj, *obj;
1466162238Scsjp
1467173138Srwatson	if (!mls_enabled)
1468173138Srwatson		return (0);
1469162238Scsjp
1470173138Srwatson	subj = SLOT(cred->cr_label);
1471173138Srwatson	obj = SLOT(pplabel);
1472173138Srwatson
1473173138Srwatson	if (!mls_dominate_effective(obj, subj))
1474173138Srwatson		return (EACCES);
1475173138Srwatson
1476173138Srwatson	return (0);
1477162238Scsjp}
1478162238Scsjp
1479165150Scsjpstatic void
1480173138Srwatsonmls_pipe_create(struct ucred *cred, struct pipepair *pp,
1481173138Srwatson    struct label *pplabel)
1482173102Srwatson{
1483173102Srwatson	struct mac_mls *source, *dest;
1484173102Srwatson
1485173138Srwatson	source = SLOT(cred->cr_label);
1486173138Srwatson	dest = SLOT(pplabel);
1487173102Srwatson
1488173102Srwatson	mls_copy_effective(source, dest);
1489173102Srwatson}
1490173102Srwatson
1491173102Srwatsonstatic void
1492173138Srwatsonmls_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1493173138Srwatson    struct label *pplabel, struct label *newlabel)
1494173095Srwatson{
1495173138Srwatson	struct mac_mls *source, *dest;
1496173095Srwatson
1497173138Srwatson	source = SLOT(newlabel);
1498173138Srwatson	dest = SLOT(pplabel);
1499173095Srwatson
1500173138Srwatson	mls_copy(source, dest);
1501173095Srwatson}
1502173095Srwatson
1503173138Srwatsonstatic int
1504180059Sjhbmls_posixsem_check_openunlink(struct ucred *cred, struct ksem *ks,
1505173138Srwatson    struct label *kslabel)
1506173095Srwatson{
1507173138Srwatson	struct mac_mls *subj, *obj;
1508173095Srwatson
1509173138Srwatson	if (!mls_enabled)
1510173138Srwatson		return (0);
1511173095Srwatson
1512173138Srwatson	subj = SLOT(cred->cr_label);
1513173138Srwatson	obj = SLOT(kslabel);
1514173095Srwatson
1515180059Sjhb	if (!mls_dominate_effective(obj, subj))
1516180059Sjhb		return (EACCES);
1517180059Sjhb
1518180059Sjhb	return (0);
1519180059Sjhb}
1520180059Sjhb
1521180059Sjhbstatic int
1522180059Sjhbmls_posixsem_check_rdonly(struct ucred *active_cred, struct ucred *file_cred,
1523180059Sjhb    struct ksem *ks, struct label *kslabel)
1524180059Sjhb{
1525180059Sjhb	struct mac_mls *subj, *obj;
1526180059Sjhb
1527180059Sjhb	if (!mls_enabled)
1528180059Sjhb		return (0);
1529180059Sjhb
1530180059Sjhb	subj = SLOT(active_cred->cr_label);
1531180059Sjhb	obj = SLOT(kslabel);
1532180059Sjhb
1533173138Srwatson	if (!mls_dominate_effective(subj, obj))
1534173138Srwatson		return (EACCES);
1535165150Scsjp
1536173138Srwatson	return (0);
1537165150Scsjp}
1538165150Scsjp
1539173138Srwatsonstatic int
1540225344Srwatsonmls_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
1541225344Srwatson    struct label *shmlabel, mode_t mode)
1542225344Srwatson{
1543225344Srwatson	struct mac_mls *subj, *obj;
1544225344Srwatson
1545225344Srwatson	if (!mls_enabled)
1546225344Srwatson		return (0);
1547225344Srwatson
1548225344Srwatson	subj = SLOT(cred->cr_label);
1549225344Srwatson	obj = SLOT(shmlabel);
1550225344Srwatson
1551225344Srwatson	if (!mls_dominate_effective(obj, subj))
1552225344Srwatson		return (EACCES);
1553225344Srwatson
1554225344Srwatson	return (0);
1555225344Srwatson}
1556225344Srwatson
1557225344Srwatsonstatic int
1558225344Srwatsonmls_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
1559225344Srwatson    struct label *shmlabel, uid_t uid, gid_t gid)
1560225344Srwatson{
1561225344Srwatson	struct mac_mls *subj, *obj;
1562225344Srwatson
1563225344Srwatson	if (!mls_enabled)
1564225344Srwatson		return (0);
1565225344Srwatson
1566225344Srwatson	subj = SLOT(cred->cr_label);
1567225344Srwatson	obj = SLOT(shmlabel);
1568225344Srwatson
1569225344Srwatson	if (!mls_dominate_effective(obj, subj))
1570225344Srwatson		return (EACCES);
1571225344Srwatson
1572225344Srwatson	return (0);
1573225344Srwatson}
1574225344Srwatson
1575225344Srwatsonstatic int
1576180059Sjhbmls_posixsem_check_write(struct ucred *active_cred, struct ucred *file_cred,
1577180059Sjhb    struct ksem *ks, struct label *kslabel)
1578165150Scsjp{
1579173138Srwatson	struct mac_mls *subj, *obj;
1580165150Scsjp
1581173138Srwatson	if (!mls_enabled)
1582173138Srwatson		return (0);
1583172955Srwatson
1584180059Sjhb	subj = SLOT(active_cred->cr_label);
1585173138Srwatson	obj = SLOT(kslabel);
1586165150Scsjp
1587173138Srwatson	if (!mls_dominate_effective(obj, subj))
1588173138Srwatson		return (EACCES);
1589101099Srwatson
1590173138Srwatson	return (0);
1591101099Srwatson}
1592101099Srwatson
1593101099Srwatsonstatic void
1594173138Srwatsonmls_posixsem_create(struct ucred *cred, struct ksem *ks,
1595173138Srwatson    struct label *kslabel)
1596101099Srwatson{
1597173138Srwatson	struct mac_mls *source, *dest;
1598101099Srwatson
1599173138Srwatson	source = SLOT(cred->cr_label);
1600173138Srwatson	dest = SLOT(kslabel);
1601101099Srwatson
1602173138Srwatson	mls_copy_effective(source, dest);
1603101099Srwatson}
1604101099Srwatson
1605173138Srwatsonstatic int
1606225344Srwatsonmls_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
1607225344Srwatson    struct label *shmlabel, int prot, int flags)
1608225344Srwatson{
1609225344Srwatson	struct mac_mls *subj, *obj;
1610225344Srwatson
1611225344Srwatson	if (!mls_enabled)
1612225344Srwatson		return (0);
1613225344Srwatson
1614225344Srwatson	subj = SLOT(cred->cr_label);
1615225344Srwatson	obj = SLOT(shmlabel);
1616225344Srwatson
1617225344Srwatson	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
1618225344Srwatson		if (!mls_dominate_effective(subj, obj))
1619225344Srwatson			return (EACCES);
1620225344Srwatson	}
1621225344Srwatson	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
1622225344Srwatson		if (!mls_dominate_effective(obj, subj))
1623225344Srwatson			return (EACCES);
1624225344Srwatson	}
1625225344Srwatson
1626225344Srwatson	return (0);
1627225344Srwatson}
1628225344Srwatson
1629225344Srwatsonstatic int
1630225344Srwatsonmls_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
1631225344Srwatson    struct label *shmlabel, accmode_t accmode)
1632225344Srwatson{
1633225344Srwatson	struct mac_mls *subj, *obj;
1634225344Srwatson
1635225344Srwatson	if (!mls_enabled)
1636225344Srwatson		return (0);
1637225344Srwatson
1638225344Srwatson	subj = SLOT(cred->cr_label);
1639225344Srwatson	obj = SLOT(shmlabel);
1640225344Srwatson
1641225344Srwatson	if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
1642225344Srwatson		if (!mls_dominate_effective(subj, obj))
1643225344Srwatson			return (EACCES);
1644225344Srwatson	}
1645225344Srwatson	if (accmode & VMODIFY_PERMS) {
1646225344Srwatson		if (!mls_dominate_effective(obj, subj))
1647225344Srwatson			return (EACCES);
1648225344Srwatson	}
1649225344Srwatson
1650225344Srwatson	return (0);
1651225344Srwatson}
1652225344Srwatson
1653225344Srwatsonstatic int
1654254603Skibmls_posixshm_check_read(struct ucred *active_cred, struct ucred *file_cred,
1655254603Skib    struct shmfd *shm, struct label *shmlabel)
1656254603Skib{
1657254603Skib	struct mac_mls *subj, *obj;
1658254603Skib
1659254603Skib	if (!mls_enabled || !revocation_enabled)
1660254603Skib		return (0);
1661254603Skib
1662254603Skib	subj = SLOT(active_cred->cr_label);
1663254603Skib	obj = SLOT(shmlabel);
1664254603Skib
1665254603Skib	if (!mls_dominate_effective(subj, obj))
1666254603Skib		return (EACCES);
1667254603Skib
1668254603Skib	return (0);
1669254603Skib}
1670254603Skib
1671254603Skibstatic int
1672225344Srwatsonmls_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
1673225344Srwatson    struct label *shmlabel, mode_t mode)
1674225344Srwatson{
1675225344Srwatson	struct mac_mls *subj, *obj;
1676225344Srwatson
1677225344Srwatson	if (!mls_enabled)
1678225344Srwatson		return (0);
1679225344Srwatson
1680225344Srwatson	subj = SLOT(cred->cr_label);
1681225344Srwatson	obj = SLOT(shmlabel);
1682225344Srwatson
1683225344Srwatson	if (!mls_dominate_effective(obj, subj))
1684225344Srwatson		return (EACCES);
1685225344Srwatson
1686225344Srwatson	return (0);
1687225344Srwatson}
1688225344Srwatson
1689225344Srwatsonstatic int
1690225344Srwatsonmls_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
1691225344Srwatson    struct label *shmlabel, uid_t uid, gid_t gid)
1692225344Srwatson{
1693225344Srwatson	struct mac_mls *subj, *obj;
1694225344Srwatson
1695225344Srwatson	if (!mls_enabled)
1696225344Srwatson		return (0);
1697225344Srwatson
1698225344Srwatson	subj = SLOT(cred->cr_label);
1699225344Srwatson	obj = SLOT(shmlabel);
1700225344Srwatson
1701225344Srwatson	if (!mls_dominate_effective(obj, subj))
1702225344Srwatson		return (EACCES);
1703225344Srwatson
1704225344Srwatson	return (0);
1705225344Srwatson}
1706225344Srwatson
1707225344Srwatsonstatic int
1708225344Srwatsonmls_posixshm_check_stat(struct ucred *active_cred, struct ucred *file_cred,
1709225344Srwatson    struct shmfd *shmfd, struct label *shmlabel)
1710225344Srwatson{
1711225344Srwatson	struct mac_mls *subj, *obj;
1712225344Srwatson
1713225344Srwatson	if (!mls_enabled)
1714225344Srwatson		return (0);
1715225344Srwatson
1716225344Srwatson	subj = SLOT(active_cred->cr_label);
1717225344Srwatson	obj = SLOT(shmlabel);
1718225344Srwatson
1719225344Srwatson	if (!mls_dominate_effective(subj, obj))
1720225344Srwatson		return (EACCES);
1721225344Srwatson
1722225344Srwatson	return (0);
1723225344Srwatson}
1724225344Srwatson
1725225344Srwatsonstatic int
1726225344Srwatsonmls_posixshm_check_truncate(struct ucred *active_cred,
1727225344Srwatson    struct ucred *file_cred, struct shmfd *shmfd, struct label *shmlabel)
1728225344Srwatson{
1729225344Srwatson	struct mac_mls *subj, *obj;
1730225344Srwatson
1731225344Srwatson	if (!mls_enabled)
1732225344Srwatson		return (0);
1733225344Srwatson
1734225344Srwatson	subj = SLOT(active_cred->cr_label);
1735225344Srwatson	obj = SLOT(shmlabel);
1736225344Srwatson
1737225344Srwatson	if (!mls_dominate_effective(obj, subj))
1738225344Srwatson		return (EACCES);
1739225344Srwatson
1740225344Srwatson	return (0);
1741225344Srwatson}
1742225344Srwatson
1743225344Srwatsonstatic int
1744225344Srwatsonmls_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd,
1745225344Srwatson    struct label *shmlabel)
1746225344Srwatson{
1747225344Srwatson	struct mac_mls *subj, *obj;
1748225344Srwatson
1749225344Srwatson	if (!mls_enabled)
1750225344Srwatson		return (0);
1751225344Srwatson
1752225344Srwatson	subj = SLOT(cred->cr_label);
1753225344Srwatson	obj = SLOT(shmlabel);
1754225344Srwatson
1755225344Srwatson	if (!mls_dominate_effective(obj, subj))
1756225344Srwatson		return (EACCES);
1757225344Srwatson
1758225344Srwatson	return (0);
1759225344Srwatson}
1760225344Srwatson
1761254603Skibstatic int
1762254603Skibmls_posixshm_check_write(struct ucred *active_cred, struct ucred *file_cred,
1763254603Skib    struct shmfd *shm, struct label *shmlabel)
1764254603Skib{
1765254603Skib	struct mac_mls *subj, *obj;
1766254603Skib
1767254603Skib	if (!mls_enabled || !revocation_enabled)
1768254603Skib		return (0);
1769254603Skib
1770254603Skib	subj = SLOT(active_cred->cr_label);
1771254603Skib	obj = SLOT(shmlabel);
1772254603Skib
1773254603Skib	if (!mls_dominate_effective(subj, obj))
1774254603Skib		return (EACCES);
1775254603Skib
1776254603Skib	return (0);
1777254603Skib}
1778254603Skib
1779225344Srwatsonstatic void
1780225344Srwatsonmls_posixshm_create(struct ucred *cred, struct shmfd *shmfd,
1781225344Srwatson    struct label *shmlabel)
1782225344Srwatson{
1783225344Srwatson	struct mac_mls *source, *dest;
1784225344Srwatson
1785225344Srwatson	source = SLOT(cred->cr_label);
1786225344Srwatson	dest = SLOT(shmlabel);
1787225344Srwatson
1788225344Srwatson	mls_copy_effective(source, dest);
1789225344Srwatson}
1790225344Srwatson
1791225344Srwatsonstatic int
1792173138Srwatsonmls_proc_check_debug(struct ucred *cred, struct proc *p)
1793101099Srwatson{
1794173138Srwatson	struct mac_mls *subj, *obj;
1795101099Srwatson
1796173138Srwatson	if (!mls_enabled)
1797173138Srwatson		return (0);
1798101099Srwatson
1799173138Srwatson	subj = SLOT(cred->cr_label);
1800173138Srwatson	obj = SLOT(p->p_ucred->cr_label);
1801173138Srwatson
1802173138Srwatson	/* XXX: range checks */
1803173138Srwatson	if (!mls_dominate_effective(subj, obj))
1804173138Srwatson		return (ESRCH);
1805173138Srwatson	if (!mls_dominate_effective(obj, subj))
1806173138Srwatson		return (EACCES);
1807173138Srwatson
1808173138Srwatson	return (0);
1809101099Srwatson}
1810101099Srwatson
1811173138Srwatsonstatic int
1812173138Srwatsonmls_proc_check_sched(struct ucred *cred, struct proc *p)
1813140629Srwatson{
1814173138Srwatson	struct mac_mls *subj, *obj;
1815140629Srwatson
1816173138Srwatson	if (!mls_enabled)
1817173138Srwatson		return (0);
1818173138Srwatson
1819173138Srwatson	subj = SLOT(cred->cr_label);
1820173138Srwatson	obj = SLOT(p->p_ucred->cr_label);
1821173138Srwatson
1822173138Srwatson	/* XXX: range checks */
1823173138Srwatson	if (!mls_dominate_effective(subj, obj))
1824173138Srwatson		return (ESRCH);
1825173138Srwatson	if (!mls_dominate_effective(obj, subj))
1826173138Srwatson		return (EACCES);
1827173138Srwatson
1828173138Srwatson	return (0);
1829140629Srwatson}
1830140629Srwatson
1831173138Srwatsonstatic int
1832173138Srwatsonmls_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
1833140629Srwatson{
1834173138Srwatson	struct mac_mls *subj, *obj;
1835140629Srwatson
1836173138Srwatson	if (!mls_enabled)
1837173138Srwatson		return (0);
1838173138Srwatson
1839173138Srwatson	subj = SLOT(cred->cr_label);
1840173138Srwatson	obj = SLOT(p->p_ucred->cr_label);
1841173138Srwatson
1842173138Srwatson	/* XXX: range checks */
1843173138Srwatson	if (!mls_dominate_effective(subj, obj))
1844173138Srwatson		return (ESRCH);
1845173138Srwatson	if (!mls_dominate_effective(obj, subj))
1846173138Srwatson		return (EACCES);
1847173138Srwatson
1848173138Srwatson	return (0);
1849140629Srwatson}
1850140629Srwatson
1851101099Srwatsonstatic int
1852173138Srwatsonmls_socket_check_deliver(struct socket *so, struct label *solabel,
1853173138Srwatson    struct mbuf *m, struct label *mlabel)
1854101099Srwatson{
1855173138Srwatson	struct mac_mls *p, *s;
1856193391Srwatson	int error;
1857101099Srwatson
1858172955Srwatson	if (!mls_enabled)
1859101099Srwatson		return (0);
1860101099Srwatson
1861173138Srwatson	p = SLOT(mlabel);
1862173138Srwatson	s = SLOT(solabel);
1863101099Srwatson
1864193391Srwatson	SOCK_LOCK(so);
1865193391Srwatson	error = mls_equal_effective(p, s) ? 0 : EACCES;
1866193391Srwatson	SOCK_UNLOCK(so);
1867193391Srwatson
1868193391Srwatson	return (error);
1869101099Srwatson}
1870101099Srwatson
1871101099Srwatsonstatic int
1872173138Srwatsonmls_socket_check_relabel(struct ucred *cred, struct socket *so,
1873173138Srwatson    struct label *solabel, struct label *newlabel)
1874101099Srwatson{
1875173138Srwatson	struct mac_mls *subj, *obj, *new;
1876105634Srwatson	int error;
1877101099Srwatson
1878193391Srwatson	SOCK_LOCK_ASSERT(so);
1879193391Srwatson
1880173138Srwatson	new = SLOT(newlabel);
1881122524Srwatson	subj = SLOT(cred->cr_label);
1882173138Srwatson	obj = SLOT(solabel);
1883101099Srwatson
1884101099Srwatson	/*
1885173138Srwatson	 * If there is an MLS label update for the socket, it may be an
1886173138Srwatson	 * update of effective.
1887101099Srwatson	 */
1888173138Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1889105634Srwatson	if (error)
1890105634Srwatson		return (error);
1891101099Srwatson
1892101099Srwatson	/*
1893173138Srwatson	 * To relabel a socket, the old socket effective must be in the
1894173138Srwatson	 * subject range.
1895173138Srwatson	 */
1896173138Srwatson	if (!mls_effective_in_range(obj, subj))
1897173138Srwatson		return (EPERM);
1898173138Srwatson
1899173138Srwatson	/*
1900105634Srwatson	 * If the MLS label is to be changed, authorize as appropriate.
1901101099Srwatson	 */
1902173138Srwatson	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1903105634Srwatson		/*
1904173138Srwatson		 * To relabel a socket, the new socket effective must be in
1905173138Srwatson		 * the subject range.
1906110351Srwatson		 */
1907173138Srwatson		if (!mls_effective_in_range(new, subj))
1908105634Srwatson			return (EPERM);
1909101099Srwatson
1910105634Srwatson		/*
1911173138Srwatson		 * To change the MLS label on the socket to contain EQUAL,
1912173138Srwatson		 * the subject must have appropriate privilege.
1913105634Srwatson		 */
1914172955Srwatson		if (mls_contains_equal(new)) {
1915172955Srwatson			error = mls_subject_privileged(subj);
1916105634Srwatson			if (error)
1917105634Srwatson				return (error);
1918105634Srwatson		}
1919105634Srwatson	}
1920105634Srwatson
1921101099Srwatson	return (0);
1922101099Srwatson}
1923101099Srwatson
1924101099Srwatsonstatic int
1925173138Srwatsonmls_socket_check_visible(struct ucred *cred, struct socket *so,
1926173138Srwatson    struct label *solabel)
1927101099Srwatson{
1928101099Srwatson	struct mac_mls *subj, *obj;
1929101099Srwatson
1930172955Srwatson	if (!mls_enabled)
1931101099Srwatson		return (0);
1932101099Srwatson
1933173138Srwatson	subj = SLOT(cred->cr_label);
1934173138Srwatson	obj = SLOT(solabel);
1935101099Srwatson
1936193391Srwatson	SOCK_LOCK(so);
1937193391Srwatson	if (!mls_dominate_effective(subj, obj)) {
1938193391Srwatson		SOCK_UNLOCK(so);
1939173138Srwatson		return (ENOENT);
1940193391Srwatson	}
1941193391Srwatson	SOCK_UNLOCK(so);
1942101099Srwatson
1943101099Srwatson	return (0);
1944101099Srwatson}
1945101099Srwatson
1946173138Srwatsonstatic void
1947173138Srwatsonmls_socket_create(struct ucred *cred, struct socket *so,
1948173138Srwatson    struct label *solabel)
1949173138Srwatson{
1950173138Srwatson	struct mac_mls *source, *dest;
1951173138Srwatson
1952173138Srwatson	source = SLOT(cred->cr_label);
1953173138Srwatson	dest = SLOT(solabel);
1954173138Srwatson
1955173138Srwatson	mls_copy_effective(source, dest);
1956173138Srwatson}
1957173138Srwatson
1958173138Srwatsonstatic void
1959173138Srwatsonmls_socket_create_mbuf(struct socket *so, struct label *solabel,
1960173138Srwatson    struct mbuf *m, struct label *mlabel)
1961173138Srwatson{
1962173138Srwatson	struct mac_mls *source, *dest;
1963173138Srwatson
1964173138Srwatson	source = SLOT(solabel);
1965173138Srwatson	dest = SLOT(mlabel);
1966173138Srwatson
1967193391Srwatson	SOCK_LOCK(so);
1968173138Srwatson	mls_copy_effective(source, dest);
1969193391Srwatson	SOCK_UNLOCK(so);
1970173138Srwatson}
1971173138Srwatson
1972173138Srwatsonstatic void
1973173138Srwatsonmls_socket_newconn(struct socket *oldso, struct label *oldsolabel,
1974173138Srwatson    struct socket *newso, struct label *newsolabel)
1975173138Srwatson{
1976193391Srwatson	struct mac_mls source, *dest;
1977173138Srwatson
1978193391Srwatson	SOCK_LOCK(oldso);
1979193391Srwatson	source = *SLOT(oldsolabel);
1980193391Srwatson	SOCK_UNLOCK(oldso);
1981193391Srwatson
1982173138Srwatson	dest = SLOT(newsolabel);
1983173138Srwatson
1984193391Srwatson	SOCK_LOCK(newso);
1985193391Srwatson	mls_copy_effective(&source, dest);
1986193391Srwatson	SOCK_UNLOCK(newso);
1987173138Srwatson}
1988173138Srwatson
1989173138Srwatsonstatic void
1990173138Srwatsonmls_socket_relabel(struct ucred *cred, struct socket *so,
1991173138Srwatson    struct label *solabel, struct label *newlabel)
1992173138Srwatson{
1993173138Srwatson	struct mac_mls *source, *dest;
1994173138Srwatson
1995193391Srwatson	SOCK_LOCK_ASSERT(so);
1996193391Srwatson
1997173138Srwatson	source = SLOT(newlabel);
1998173138Srwatson	dest = SLOT(solabel);
1999173138Srwatson
2000173138Srwatson	mls_copy(source, dest);
2001173138Srwatson}
2002173138Srwatson
2003173138Srwatsonstatic void
2004173138Srwatsonmls_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel,
2005173138Srwatson    struct socket *so, struct label *sopeerlabel)
2006173138Srwatson{
2007173138Srwatson	struct mac_mls *source, *dest;
2008173138Srwatson
2009173138Srwatson	source = SLOT(mlabel);
2010173138Srwatson	dest = SLOT(sopeerlabel);
2011173138Srwatson
2012193391Srwatson	SOCK_LOCK(so);
2013173138Srwatson	mls_copy_effective(source, dest);
2014193391Srwatson	SOCK_UNLOCK(so);
2015173138Srwatson}
2016173138Srwatson
2017173138Srwatsonstatic void
2018173138Srwatsonmls_socketpeer_set_from_socket(struct socket *oldso,
2019173138Srwatson    struct label *oldsolabel, struct socket *newso,
2020173138Srwatson    struct label *newsopeerlabel)
2021173138Srwatson{
2022193391Srwatson	struct mac_mls source, *dest;
2023173138Srwatson
2024193391Srwatson	SOCK_LOCK(oldso);
2025193391Srwatson	source = *SLOT(oldsolabel);
2026193391Srwatson	SOCK_UNLOCK(oldso);
2027193391Srwatson
2028173138Srwatson	dest = SLOT(newsopeerlabel);
2029173138Srwatson
2030193391Srwatson	SOCK_LOCK(newso);
2031193391Srwatson	mls_copy_effective(&source, dest);
2032193391Srwatson	SOCK_UNLOCK(newso);
2033173138Srwatson}
2034173138Srwatson
2035173138Srwatsonstatic void
2036173138Srwatsonmls_syncache_create(struct label *label, struct inpcb *inp)
2037173138Srwatson{
2038173138Srwatson	struct mac_mls *source, *dest;
2039173138Srwatson
2040173138Srwatson	source = SLOT(inp->inp_label);
2041173138Srwatson	dest = SLOT(label);
2042173138Srwatson
2043173138Srwatson	mls_copy_effective(source, dest);
2044173138Srwatson}
2045173138Srwatson
2046173138Srwatsonstatic void
2047173138Srwatsonmls_syncache_create_mbuf(struct label *sc_label, struct mbuf *m,
2048173138Srwatson    struct label *mlabel)
2049173138Srwatson{
2050173138Srwatson	struct mac_mls *source, *dest;
2051173138Srwatson
2052173138Srwatson	source = SLOT(sc_label);
2053173138Srwatson	dest = SLOT(mlabel);
2054173138Srwatson
2055173138Srwatson	mls_copy_effective(source, dest);
2056173138Srwatson}
2057173138Srwatson
2058101099Srwatsonstatic int
2059173138Srwatsonmls_system_check_acct(struct ucred *cred, struct vnode *vp,
2060173138Srwatson    struct label *vplabel)
2061101099Srwatson{
2062173138Srwatson	struct mac_mls *subj, *obj;
2063101099Srwatson
2064173138Srwatson	if (!mls_enabled)
2065173138Srwatson		return (0);
2066173138Srwatson
2067234957Sbrueffer	if (vplabel == NULL)
2068234957Sbrueffer		return (0);
2069234957Sbrueffer
2070122524Srwatson	subj = SLOT(cred->cr_label);
2071173138Srwatson	obj = SLOT(vplabel);
2072101099Srwatson
2073173138Srwatson	if (!mls_dominate_effective(obj, subj) ||
2074173138Srwatson	    !mls_dominate_effective(subj, obj))
2075173138Srwatson		return (EACCES);
2076101099Srwatson
2077105634Srwatson	return (0);
2078101099Srwatson}
2079101099Srwatson
2080101099Srwatsonstatic int
2081173138Srwatsonmls_system_check_auditctl(struct ucred *cred, struct vnode *vp,
2082173138Srwatson    struct label *vplabel)
2083101099Srwatson{
2084173138Srwatson	struct mac_mls *subj, *obj;
2085101099Srwatson
2086172955Srwatson	if (!mls_enabled)
2087101099Srwatson		return (0);
2088101099Srwatson
2089173138Srwatson	subj = SLOT(cred->cr_label);
2090173138Srwatson	obj = SLOT(vplabel);
2091101099Srwatson
2092173138Srwatson	if (!mls_dominate_effective(obj, subj) ||
2093173138Srwatson	    !mls_dominate_effective(subj, obj))
2094173138Srwatson		return (EACCES);
2095173138Srwatson
2096173138Srwatson	return (0);
2097101099Srwatson}
2098101099Srwatson
2099101099Srwatsonstatic int
2100173138Srwatsonmls_system_check_swapon(struct ucred *cred, struct vnode *vp,
2101173138Srwatson    struct label *vplabel)
2102122875Srwatson{
2103173138Srwatson	struct mac_mls *subj, *obj;
2104122875Srwatson
2105172955Srwatson	if (!mls_enabled)
2106122875Srwatson		return (0);
2107122875Srwatson
2108173138Srwatson	subj = SLOT(cred->cr_label);
2109173138Srwatson	obj = SLOT(vplabel);
2110122875Srwatson
2111173138Srwatson	if (!mls_dominate_effective(obj, subj) ||
2112173138Srwatson	    !mls_dominate_effective(subj, obj))
2113173138Srwatson		return (EACCES);
2114173138Srwatson
2115173138Srwatson	return (0);
2116122875Srwatson}
2117122875Srwatson
2118173138Srwatsonstatic void
2119173138Srwatsonmls_sysvmsg_cleanup(struct label *msglabel)
2120173138Srwatson{
2121173138Srwatson
2122173138Srwatson	bzero(SLOT(msglabel), sizeof(struct mac_mls));
2123173138Srwatson}
2124173138Srwatson
2125173138Srwatsonstatic void
2126173138Srwatsonmls_sysvmsg_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2127173138Srwatson    struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
2128173138Srwatson{
2129173138Srwatson	struct mac_mls *source, *dest;
2130173138Srwatson
2131173138Srwatson	/* Ignore the msgq label. */
2132173138Srwatson	source = SLOT(cred->cr_label);
2133173138Srwatson	dest = SLOT(msglabel);
2134173138Srwatson
2135173138Srwatson	mls_copy_effective(source, dest);
2136173138Srwatson}
2137173138Srwatson
2138122875Srwatsonstatic int
2139172955Srwatsonmls_sysvmsq_check_msgrcv(struct ucred *cred, struct msg *msgptr,
2140140629Srwatson    struct label *msglabel)
2141140629Srwatson{
2142140629Srwatson	struct mac_mls *subj, *obj;
2143140629Srwatson
2144172955Srwatson	if (!mls_enabled)
2145140629Srwatson		return (0);
2146140629Srwatson
2147140629Srwatson	subj = SLOT(cred->cr_label);
2148140629Srwatson	obj = SLOT(msglabel);
2149140629Srwatson
2150172955Srwatson	if (!mls_dominate_effective(subj, obj))
2151140629Srwatson		return (EACCES);
2152140629Srwatson
2153140629Srwatson	return (0);
2154140629Srwatson}
2155140629Srwatson
2156140629Srwatsonstatic int
2157172955Srwatsonmls_sysvmsq_check_msgrmid(struct ucred *cred, struct msg *msgptr,
2158140629Srwatson    struct label *msglabel)
2159140629Srwatson{
2160140629Srwatson	struct mac_mls *subj, *obj;
2161140629Srwatson
2162172955Srwatson	if (!mls_enabled)
2163140629Srwatson		return (0);
2164140629Srwatson
2165140629Srwatson	subj = SLOT(cred->cr_label);
2166140629Srwatson	obj = SLOT(msglabel);
2167140629Srwatson
2168172955Srwatson	if (!mls_dominate_effective(obj, subj))
2169140629Srwatson		return (EACCES);
2170140629Srwatson
2171140629Srwatson	return (0);
2172140629Srwatson}
2173140629Srwatson
2174140629Srwatsonstatic int
2175172955Srwatsonmls_sysvmsq_check_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
2176172955Srwatson    struct label *msqklabel)
2177140629Srwatson{
2178140629Srwatson	struct mac_mls *subj, *obj;
2179140629Srwatson
2180172955Srwatson	if (!mls_enabled)
2181140629Srwatson		return (0);
2182140629Srwatson
2183140629Srwatson	subj = SLOT(cred->cr_label);
2184140629Srwatson	obj = SLOT(msqklabel);
2185140629Srwatson
2186172955Srwatson	if (!mls_dominate_effective(subj, obj))
2187140629Srwatson		return (EACCES);
2188140629Srwatson
2189140629Srwatson	return (0);
2190140629Srwatson}
2191140629Srwatson
2192140629Srwatsonstatic int
2193172955Srwatsonmls_sysvmsq_check_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
2194172955Srwatson    struct label *msqklabel)
2195140629Srwatson{
2196140629Srwatson	struct mac_mls *subj, *obj;
2197140629Srwatson
2198172955Srwatson	if (!mls_enabled)
2199140629Srwatson		return (0);
2200140629Srwatson
2201140629Srwatson	subj = SLOT(cred->cr_label);
2202140629Srwatson	obj = SLOT(msqklabel);
2203140629Srwatson
2204172955Srwatson	if (!mls_dominate_effective(obj, subj))
2205140629Srwatson		return (EACCES);
2206140629Srwatson
2207140629Srwatson	return (0);
2208140629Srwatson}
2209140629Srwatson
2210140629Srwatsonstatic int
2211172955Srwatsonmls_sysvmsq_check_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
2212172955Srwatson    struct label *msqklabel)
2213140629Srwatson{
2214140629Srwatson	struct mac_mls *subj, *obj;
2215140629Srwatson
2216172955Srwatson	if (!mls_enabled)
2217140629Srwatson		return (0);
2218140629Srwatson
2219140629Srwatson	subj = SLOT(cred->cr_label);
2220140629Srwatson	obj = SLOT(msqklabel);
2221140629Srwatson
2222172955Srwatson	if (!mls_dominate_effective(subj, obj))
2223140629Srwatson		return (EACCES);
2224140629Srwatson
2225140629Srwatson	return (0);
2226140629Srwatson}
2227140629Srwatson
2228140629Srwatsonstatic int
2229172955Srwatsonmls_sysvmsq_check_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
2230172955Srwatson    struct label *msqklabel, int cmd)
2231140629Srwatson{
2232140629Srwatson	struct mac_mls *subj, *obj;
2233140629Srwatson
2234172955Srwatson	if (!mls_enabled)
2235140629Srwatson		return (0);
2236140629Srwatson
2237140629Srwatson	subj = SLOT(cred->cr_label);
2238140629Srwatson	obj = SLOT(msqklabel);
2239140629Srwatson
2240140629Srwatson	switch(cmd) {
2241140629Srwatson	case IPC_RMID:
2242140629Srwatson	case IPC_SET:
2243172955Srwatson		if (!mls_dominate_effective(obj, subj))
2244140629Srwatson			return (EACCES);
2245140629Srwatson		break;
2246140629Srwatson
2247140629Srwatson	case IPC_STAT:
2248172955Srwatson		if (!mls_dominate_effective(subj, obj))
2249140629Srwatson			return (EACCES);
2250140629Srwatson		break;
2251140629Srwatson
2252140629Srwatson	default:
2253140629Srwatson		return (EACCES);
2254140629Srwatson	}
2255140629Srwatson
2256140629Srwatson	return (0);
2257140629Srwatson}
2258140629Srwatson
2259173138Srwatsonstatic void
2260173138Srwatsonmls_sysvmsq_cleanup(struct label *msqlabel)
2261173138Srwatson{
2262173138Srwatson
2263173138Srwatson	bzero(SLOT(msqlabel), sizeof(struct mac_mls));
2264173138Srwatson}
2265173138Srwatson
2266173138Srwatsonstatic void
2267173138Srwatsonmls_sysvmsq_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2268173138Srwatson    struct label *msqlabel)
2269173138Srwatson{
2270173138Srwatson	struct mac_mls *source, *dest;
2271173138Srwatson
2272173138Srwatson	source = SLOT(cred->cr_label);
2273173138Srwatson	dest = SLOT(msqlabel);
2274173138Srwatson
2275173138Srwatson	mls_copy_effective(source, dest);
2276173138Srwatson}
2277173138Srwatson
2278140629Srwatsonstatic int
2279172955Srwatsonmls_sysvsem_check_semctl(struct ucred *cred, struct semid_kernel *semakptr,
2280172955Srwatson    struct label *semaklabel, int cmd)
2281140629Srwatson{
2282140629Srwatson	struct mac_mls *subj, *obj;
2283140629Srwatson
2284172955Srwatson	if (!mls_enabled)
2285140629Srwatson		return (0);
2286140629Srwatson
2287140629Srwatson	subj = SLOT(cred->cr_label);
2288140629Srwatson	obj = SLOT(semaklabel);
2289140629Srwatson
2290140629Srwatson	switch(cmd) {
2291140629Srwatson	case IPC_RMID:
2292140629Srwatson	case IPC_SET:
2293140629Srwatson	case SETVAL:
2294140629Srwatson	case SETALL:
2295172955Srwatson		if (!mls_dominate_effective(obj, subj))
2296140629Srwatson			return (EACCES);
2297140629Srwatson		break;
2298140629Srwatson
2299140629Srwatson	case IPC_STAT:
2300140629Srwatson	case GETVAL:
2301140629Srwatson	case GETPID:
2302140629Srwatson	case GETNCNT:
2303140629Srwatson	case GETZCNT:
2304140629Srwatson	case GETALL:
2305172955Srwatson		if (!mls_dominate_effective(subj, obj))
2306140629Srwatson			return (EACCES);
2307140629Srwatson		break;
2308140629Srwatson
2309140629Srwatson	default:
2310140629Srwatson		return (EACCES);
2311140629Srwatson	}
2312140629Srwatson
2313140629Srwatson	return (0);
2314140629Srwatson}
2315140629Srwatson
2316140629Srwatsonstatic int
2317172955Srwatsonmls_sysvsem_check_semget(struct ucred *cred, struct semid_kernel *semakptr,
2318172955Srwatson    struct label *semaklabel)
2319140629Srwatson{
2320140629Srwatson	struct mac_mls *subj, *obj;
2321140629Srwatson
2322172955Srwatson	if (!mls_enabled)
2323140629Srwatson		return (0);
2324140629Srwatson
2325140629Srwatson	subj = SLOT(cred->cr_label);
2326140629Srwatson	obj = SLOT(semaklabel);
2327140629Srwatson
2328172955Srwatson	if (!mls_dominate_effective(subj, obj))
2329140629Srwatson		return (EACCES);
2330140629Srwatson
2331140629Srwatson	return (0);
2332140629Srwatson}
2333140629Srwatson
2334140629Srwatsonstatic int
2335172955Srwatsonmls_sysvsem_check_semop(struct ucred *cred, struct semid_kernel *semakptr,
2336172955Srwatson    struct label *semaklabel, size_t accesstype)
2337140629Srwatson{
2338140629Srwatson	struct mac_mls *subj, *obj;
2339140629Srwatson
2340172955Srwatson	if (!mls_enabled)
2341140629Srwatson		return (0);
2342140629Srwatson
2343140629Srwatson	subj = SLOT(cred->cr_label);
2344140629Srwatson	obj = SLOT(semaklabel);
2345140629Srwatson
2346140629Srwatson	if( accesstype & SEM_R )
2347172955Srwatson		if (!mls_dominate_effective(subj, obj))
2348140629Srwatson			return (EACCES);
2349140629Srwatson
2350140629Srwatson	if( accesstype & SEM_A )
2351172955Srwatson		if (!mls_dominate_effective(obj, subj))
2352140629Srwatson			return (EACCES);
2353140629Srwatson
2354140629Srwatson	return (0);
2355140629Srwatson}
2356140629Srwatson
2357173138Srwatsonstatic void
2358173138Srwatsonmls_sysvsem_cleanup(struct label *semalabel)
2359173138Srwatson{
2360173138Srwatson
2361173138Srwatson	bzero(SLOT(semalabel), sizeof(struct mac_mls));
2362173138Srwatson}
2363173138Srwatson
2364173138Srwatsonstatic void
2365173138Srwatsonmls_sysvsem_create(struct ucred *cred, struct semid_kernel *semakptr,
2366173138Srwatson    struct label *semalabel)
2367173138Srwatson{
2368173138Srwatson	struct mac_mls *source, *dest;
2369173138Srwatson
2370173138Srwatson	source = SLOT(cred->cr_label);
2371173138Srwatson	dest = SLOT(semalabel);
2372173138Srwatson
2373173138Srwatson	mls_copy_effective(source, dest);
2374173138Srwatson}
2375173138Srwatson
2376140629Srwatsonstatic int
2377172955Srwatsonmls_sysvshm_check_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
2378172955Srwatson    struct label *shmseglabel, int shmflg)
2379140629Srwatson{
2380140629Srwatson	struct mac_mls *subj, *obj;
2381140629Srwatson
2382172955Srwatson	if (!mls_enabled)
2383140629Srwatson		return (0);
2384140629Srwatson
2385140629Srwatson	subj = SLOT(cred->cr_label);
2386140629Srwatson	obj = SLOT(shmseglabel);
2387140629Srwatson
2388172955Srwatson	if (!mls_dominate_effective(subj, obj))
2389172955Srwatson		return (EACCES);
2390172955Srwatson	if ((shmflg & SHM_RDONLY) == 0) {
2391172955Srwatson		if (!mls_dominate_effective(obj, subj))
2392140629Srwatson			return (EACCES);
2393172955Srwatson	}
2394140629Srwatson
2395140629Srwatson	return (0);
2396140629Srwatson}
2397140629Srwatson
2398140629Srwatsonstatic int
2399172955Srwatsonmls_sysvshm_check_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
2400172955Srwatson    struct label *shmseglabel, int cmd)
2401140629Srwatson{
2402140629Srwatson	struct mac_mls *subj, *obj;
2403140629Srwatson
2404172955Srwatson	if (!mls_enabled)
2405140629Srwatson		return (0);
2406140629Srwatson
2407140629Srwatson	subj = SLOT(cred->cr_label);
2408140629Srwatson	obj = SLOT(shmseglabel);
2409140629Srwatson
2410140629Srwatson	switch(cmd) {
2411140629Srwatson	case IPC_RMID:
2412140629Srwatson	case IPC_SET:
2413172955Srwatson		if (!mls_dominate_effective(obj, subj))
2414140629Srwatson			return (EACCES);
2415140629Srwatson		break;
2416140629Srwatson
2417140629Srwatson	case IPC_STAT:
2418140629Srwatson	case SHM_STAT:
2419172955Srwatson		if (!mls_dominate_effective(subj, obj))
2420140629Srwatson			return (EACCES);
2421140629Srwatson		break;
2422140629Srwatson
2423140629Srwatson	default:
2424140629Srwatson		return (EACCES);
2425140629Srwatson	}
2426140629Srwatson
2427140629Srwatson	return (0);
2428140629Srwatson}
2429140629Srwatson
2430140629Srwatsonstatic int
2431172955Srwatsonmls_sysvshm_check_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
2432172955Srwatson    struct label *shmseglabel, int shmflg)
2433140629Srwatson{
2434140629Srwatson	struct mac_mls *subj, *obj;
2435140629Srwatson
2436172955Srwatson	if (!mls_enabled)
2437140629Srwatson		return (0);
2438140629Srwatson
2439140629Srwatson	subj = SLOT(cred->cr_label);
2440140629Srwatson	obj = SLOT(shmseglabel);
2441140629Srwatson
2442172955Srwatson	if (!mls_dominate_effective(obj, subj))
2443140629Srwatson		return (EACCES);
2444140629Srwatson
2445140629Srwatson	return (0);
2446140629Srwatson}
2447140629Srwatson
2448173138Srwatsonstatic void
2449173138Srwatsonmls_sysvshm_cleanup(struct label *shmlabel)
2450101099Srwatson{
2451101099Srwatson
2452173138Srwatson	bzero(SLOT(shmlabel), sizeof(struct mac_mls));
2453101099Srwatson}
2454101099Srwatson
2455173138Srwatsonstatic void
2456173138Srwatsonmls_sysvshm_create(struct ucred *cred, struct shmid_kernel *shmsegptr,
2457173138Srwatson    struct label *shmlabel)
2458101099Srwatson{
2459173138Srwatson	struct mac_mls *source, *dest;
2460103759Srwatson
2461173138Srwatson	source = SLOT(cred->cr_label);
2462173138Srwatson	dest = SLOT(shmlabel);
2463101099Srwatson
2464173138Srwatson	mls_copy_effective(source, dest);
2465101099Srwatson}
2466101099Srwatson
2467101099Srwatsonstatic int
2468173138Srwatsonmls_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2469173138Srwatson    struct vnode *vp, struct label *vplabel)
2470101099Srwatson{
2471173138Srwatson	struct mac_mls mm_temp, *source, *dest;
2472173138Srwatson	int buflen, error;
2473101099Srwatson
2474173138Srwatson	source = SLOT(mplabel);
2475173138Srwatson	dest = SLOT(vplabel);
2476101099Srwatson
2477173138Srwatson	buflen = sizeof(mm_temp);
2478173138Srwatson	bzero(&mm_temp, buflen);
2479101099Srwatson
2480173138Srwatson	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2481173138Srwatson	    MAC_MLS_EXTATTR_NAME, &buflen, (char *) &mm_temp, curthread);
2482173138Srwatson	if (error == ENOATTR || error == EOPNOTSUPP) {
2483173138Srwatson		/* Fall back to the mntlabel. */
2484173138Srwatson		mls_copy_effective(source, dest);
2485102115Srwatson		return (0);
2486173138Srwatson	} else if (error)
2487105634Srwatson		return (error);
2488101099Srwatson
2489173138Srwatson	if (buflen != sizeof(mm_temp)) {
2490173138Srwatson		printf("mls_vnode_associate_extattr: bad size %d\n", buflen);
2491101099Srwatson		return (EPERM);
2492105634Srwatson	}
2493173138Srwatson	if (mls_valid(&mm_temp) != 0) {
2494173138Srwatson		printf("mls_vnode_associate_extattr: invalid\n");
2495101099Srwatson		return (EPERM);
2496105634Srwatson	}
2497173138Srwatson	if ((mm_temp.mm_flags & MAC_MLS_FLAGS_BOTH) !=
2498173138Srwatson	    MAC_MLS_FLAG_EFFECTIVE) {
2499173138Srwatson		printf("mls_associated_vnode_extattr: not effective\n");
2500173138Srwatson		return (EPERM);
2501173138Srwatson	}
2502105634Srwatson
2503173138Srwatson	mls_copy_effective(&mm_temp, dest);
2504101099Srwatson	return (0);
2505101099Srwatson}
2506101099Srwatson
2507173138Srwatsonstatic void
2508173138Srwatsonmls_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2509173138Srwatson    struct vnode *vp, struct label *vplabel)
2510101099Srwatson{
2511173138Srwatson	struct mac_mls *source, *dest;
2512101099Srwatson
2513173138Srwatson	source = SLOT(mplabel);
2514173138Srwatson	dest = SLOT(vplabel);
2515101099Srwatson
2516173138Srwatson	mls_copy_effective(source, dest);
2517101099Srwatson}
2518101099Srwatson
2519101099Srwatsonstatic int
2520172955Srwatsonmls_vnode_check_chdir(struct ucred *cred, struct vnode *dvp,
2521168976Srwatson    struct label *dvplabel)
2522101099Srwatson{
2523101099Srwatson	struct mac_mls *subj, *obj;
2524101099Srwatson
2525172955Srwatson	if (!mls_enabled)
2526101099Srwatson		return (0);
2527101099Srwatson
2528122524Srwatson	subj = SLOT(cred->cr_label);
2529168976Srwatson	obj = SLOT(dvplabel);
2530101099Srwatson
2531172955Srwatson	if (!mls_dominate_effective(subj, obj))
2532101099Srwatson		return (EACCES);
2533101099Srwatson
2534101099Srwatson	return (0);
2535101099Srwatson}
2536101099Srwatson
2537101099Srwatsonstatic int
2538172955Srwatsonmls_vnode_check_chroot(struct ucred *cred, struct vnode *dvp,
2539168976Srwatson    struct label *dvplabel)
2540101099Srwatson{
2541101099Srwatson	struct mac_mls *subj, *obj;
2542101099Srwatson
2543172955Srwatson	if (!mls_enabled)
2544101099Srwatson		return (0);
2545101099Srwatson
2546122524Srwatson	subj = SLOT(cred->cr_label);
2547168976Srwatson	obj = SLOT(dvplabel);
2548101099Srwatson
2549172955Srwatson	if (!mls_dominate_effective(subj, obj))
2550101099Srwatson		return (EACCES);
2551101099Srwatson
2552101099Srwatson	return (0);
2553101099Srwatson}
2554101099Srwatson
2555101099Srwatsonstatic int
2556172955Srwatsonmls_vnode_check_create(struct ucred *cred, struct vnode *dvp,
2557168976Srwatson    struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2558101099Srwatson{
2559101099Srwatson	struct mac_mls *subj, *obj;
2560101099Srwatson
2561172955Srwatson	if (!mls_enabled)
2562101099Srwatson		return (0);
2563101099Srwatson
2564122524Srwatson	subj = SLOT(cred->cr_label);
2565168976Srwatson	obj = SLOT(dvplabel);
2566101099Srwatson
2567172955Srwatson	if (!mls_dominate_effective(obj, subj))
2568101099Srwatson		return (EACCES);
2569101099Srwatson
2570101099Srwatson	return (0);
2571101099Srwatson}
2572101099Srwatson
2573101099Srwatsonstatic int
2574172955Srwatsonmls_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
2575168976Srwatson    struct label *vplabel, acl_type_t type)
2576101099Srwatson{
2577101099Srwatson	struct mac_mls *subj, *obj;
2578101099Srwatson
2579172955Srwatson	if (!mls_enabled)
2580101099Srwatson		return (0);
2581101099Srwatson
2582122524Srwatson	subj = SLOT(cred->cr_label);
2583168976Srwatson	obj = SLOT(vplabel);
2584101099Srwatson
2585172955Srwatson	if (!mls_dominate_effective(obj, subj))
2586101099Srwatson		return (EACCES);
2587101099Srwatson
2588101099Srwatson	return (0);
2589101099Srwatson}
2590101099Srwatson
2591101099Srwatsonstatic int
2592172955Srwatsonmls_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
2593168976Srwatson    struct label *vplabel, int attrnamespace, const char *name)
2594119202Srwatson{
2595119202Srwatson	struct mac_mls *subj, *obj;
2596119202Srwatson
2597172955Srwatson	if (!mls_enabled)
2598119202Srwatson		return (0);
2599119202Srwatson
2600122524Srwatson	subj = SLOT(cred->cr_label);
2601168976Srwatson	obj = SLOT(vplabel);
2602119202Srwatson
2603172955Srwatson	if (!mls_dominate_effective(obj, subj))
2604119202Srwatson		return (EACCES);
2605119202Srwatson
2606119202Srwatson	return (0);
2607119202Srwatson}
2608119202Srwatson
2609119202Srwatsonstatic int
2610172955Srwatsonmls_vnode_check_exec(struct ucred *cred, struct vnode *vp,
2611168976Srwatson    struct label *vplabel, struct image_params *imgp,
2612106648Srwatson    struct label *execlabel)
2613101099Srwatson{
2614106648Srwatson	struct mac_mls *subj, *obj, *exec;
2615106648Srwatson	int error;
2616101099Srwatson
2617106648Srwatson	if (execlabel != NULL) {
2618106648Srwatson		/*
2619106648Srwatson		 * We currently don't permit labels to be changed at
2620172955Srwatson		 * exec-time as part of MLS, so disallow non-NULL MLS label
2621172955Srwatson		 * elements in the execlabel.
2622106648Srwatson		 */
2623106648Srwatson		exec = SLOT(execlabel);
2624106648Srwatson		error = mls_atmostflags(exec, 0);
2625106648Srwatson		if (error)
2626106648Srwatson			return (error);
2627106648Srwatson	}
2628106648Srwatson
2629172955Srwatson	if (!mls_enabled)
2630101099Srwatson		return (0);
2631101099Srwatson
2632122524Srwatson	subj = SLOT(cred->cr_label);
2633168976Srwatson	obj = SLOT(vplabel);
2634101099Srwatson
2635172955Srwatson	if (!mls_dominate_effective(subj, obj))
2636101099Srwatson		return (EACCES);
2637101099Srwatson
2638101099Srwatson	return (0);
2639101099Srwatson}
2640101099Srwatson
2641101099Srwatsonstatic int
2642172955Srwatsonmls_vnode_check_getacl(struct ucred *cred, struct vnode *vp,
2643168976Srwatson    struct label *vplabel, acl_type_t type)
2644101099Srwatson{
2645101099Srwatson	struct mac_mls *subj, *obj;
2646101099Srwatson
2647172955Srwatson	if (!mls_enabled)
2648101099Srwatson		return (0);
2649101099Srwatson
2650122524Srwatson	subj = SLOT(cred->cr_label);
2651168976Srwatson	obj = SLOT(vplabel);
2652101099Srwatson
2653172955Srwatson	if (!mls_dominate_effective(subj, obj))
2654101099Srwatson		return (EACCES);
2655101099Srwatson
2656101099Srwatson	return (0);
2657101099Srwatson}
2658101099Srwatson
2659101099Srwatsonstatic int
2660172955Srwatsonmls_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
2661189533Srwatson    struct label *vplabel, int attrnamespace, const char *name)
2662101099Srwatson{
2663101099Srwatson	struct mac_mls *subj, *obj;
2664101099Srwatson
2665172955Srwatson	if (!mls_enabled)
2666101099Srwatson		return (0);
2667101099Srwatson
2668122524Srwatson	subj = SLOT(cred->cr_label);
2669168976Srwatson	obj = SLOT(vplabel);
2670101099Srwatson
2671172955Srwatson	if (!mls_dominate_effective(subj, obj))
2672101099Srwatson		return (EACCES);
2673101099Srwatson
2674101099Srwatson	return (0);
2675101099Srwatson}
2676101099Srwatson
2677105634Srwatsonstatic int
2678172955Srwatsonmls_vnode_check_link(struct ucred *cred, struct vnode *dvp,
2679168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2680104530Srwatson    struct componentname *cnp)
2681104530Srwatson{
2682104530Srwatson	struct mac_mls *subj, *obj;
2683104530Srwatson
2684172955Srwatson	if (!mls_enabled)
2685104530Srwatson		return (0);
2686104530Srwatson
2687122524Srwatson	subj = SLOT(cred->cr_label);
2688168976Srwatson	obj = SLOT(dvplabel);
2689104530Srwatson
2690172955Srwatson	if (!mls_dominate_effective(obj, subj))
2691104530Srwatson		return (EACCES);
2692104530Srwatson
2693171555Srwatson	obj = SLOT(vplabel);
2694172955Srwatson	if (!mls_dominate_effective(obj, subj))
2695104530Srwatson		return (EACCES);
2696104530Srwatson
2697104530Srwatson	return (0);
2698104530Srwatson}
2699104530Srwatson
2700101099Srwatsonstatic int
2701172955Srwatsonmls_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
2702168976Srwatson    struct label *vplabel, int attrnamespace)
2703119202Srwatson{
2704119202Srwatson
2705119202Srwatson	struct mac_mls *subj, *obj;
2706119202Srwatson
2707172955Srwatson	if (!mls_enabled)
2708119202Srwatson		return (0);
2709119202Srwatson
2710122524Srwatson	subj = SLOT(cred->cr_label);
2711168976Srwatson	obj = SLOT(vplabel);
2712119202Srwatson
2713172955Srwatson	if (!mls_dominate_effective(subj, obj))
2714119202Srwatson		return (EACCES);
2715119202Srwatson
2716119202Srwatson	return (0);
2717119202Srwatson}
2718119202Srwatson
2719119202Srwatsonstatic int
2720172955Srwatsonmls_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
2721168976Srwatson    struct label *dvplabel, struct componentname *cnp)
2722101099Srwatson{
2723101099Srwatson	struct mac_mls *subj, *obj;
2724103759Srwatson
2725172955Srwatson	if (!mls_enabled)
2726101099Srwatson		return (0);
2727103759Srwatson
2728122524Srwatson	subj = SLOT(cred->cr_label);
2729168976Srwatson	obj = SLOT(dvplabel);
2730103759Srwatson
2731172955Srwatson	if (!mls_dominate_effective(subj, obj))
2732101099Srwatson		return (EACCES);
2733101099Srwatson
2734103759Srwatson	return (0);
2735101099Srwatson}
2736101099Srwatson
2737101099Srwatsonstatic int
2738172955Srwatsonmls_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
2739168976Srwatson    struct label *vplabel, int prot, int flags)
2740104546Srwatson{
2741104546Srwatson	struct mac_mls *subj, *obj;
2742104546Srwatson
2743104546Srwatson	/*
2744104546Srwatson	 * Rely on the use of open()-time protections to handle
2745104546Srwatson	 * non-revocation cases.
2746104546Srwatson	 */
2747172955Srwatson	if (!mls_enabled || !revocation_enabled)
2748104546Srwatson		return (0);
2749104546Srwatson
2750122524Srwatson	subj = SLOT(cred->cr_label);
2751168976Srwatson	obj = SLOT(vplabel);
2752104546Srwatson
2753104546Srwatson	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2754172955Srwatson		if (!mls_dominate_effective(subj, obj))
2755104546Srwatson			return (EACCES);
2756104546Srwatson	}
2757145076Scsjp	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2758172955Srwatson		if (!mls_dominate_effective(obj, subj))
2759104546Srwatson			return (EACCES);
2760104546Srwatson	}
2761104546Srwatson
2762105634Srwatson	return (0);
2763104546Srwatson}
2764104546Srwatson
2765104546Srwatsonstatic int
2766172955Srwatsonmls_vnode_check_open(struct ucred *cred, struct vnode *vp,
2767184413Strasz    struct label *vplabel, accmode_t accmode)
2768101099Srwatson{
2769101099Srwatson	struct mac_mls *subj, *obj;
2770101099Srwatson
2771172955Srwatson	if (!mls_enabled)
2772101099Srwatson		return (0);
2773101099Srwatson
2774122524Srwatson	subj = SLOT(cred->cr_label);
2775168976Srwatson	obj = SLOT(vplabel);
2776101099Srwatson
2777101099Srwatson	/* XXX privilege override for admin? */
2778190524Strasz	if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
2779172955Srwatson		if (!mls_dominate_effective(subj, obj))
2780101099Srwatson			return (EACCES);
2781101099Srwatson	}
2782190524Strasz	if (accmode & VMODIFY_PERMS) {
2783172955Srwatson		if (!mls_dominate_effective(obj, subj))
2784101099Srwatson			return (EACCES);
2785101099Srwatson	}
2786101099Srwatson
2787101099Srwatson	return (0);
2788101099Srwatson}
2789101099Srwatson
2790101099Srwatsonstatic int
2791172955Srwatsonmls_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
2792168976Srwatson    struct vnode *vp, struct label *vplabel)
2793102112Srwatson{
2794102112Srwatson	struct mac_mls *subj, *obj;
2795102112Srwatson
2796172955Srwatson	if (!mls_enabled || !revocation_enabled)
2797102112Srwatson		return (0);
2798102112Srwatson
2799122524Srwatson	subj = SLOT(active_cred->cr_label);
2800168976Srwatson	obj = SLOT(vplabel);
2801102112Srwatson
2802172955Srwatson	if (!mls_dominate_effective(subj, obj))
2803102112Srwatson		return (EACCES);
2804102112Srwatson
2805102112Srwatson	return (0);
2806102112Srwatson}
2807102112Srwatson
2808102112Srwatsonstatic int
2809172955Srwatsonmls_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
2810168976Srwatson    struct vnode *vp, struct label *vplabel)
2811102112Srwatson{
2812102112Srwatson	struct mac_mls *subj, *obj;
2813102112Srwatson
2814172955Srwatson	if (!mls_enabled || !revocation_enabled)
2815102112Srwatson		return (0);
2816102112Srwatson
2817122524Srwatson	subj = SLOT(active_cred->cr_label);
2818168976Srwatson	obj = SLOT(vplabel);
2819102112Srwatson
2820172955Srwatson	if (!mls_dominate_effective(subj, obj))
2821102112Srwatson		return (EACCES);
2822102112Srwatson
2823102112Srwatson	return (0);
2824102112Srwatson}
2825102112Srwatson
2826102112Srwatsonstatic int
2827172955Srwatsonmls_vnode_check_readdir(struct ucred *cred, struct vnode *dvp,
2828168976Srwatson    struct label *dvplabel)
2829101099Srwatson{
2830101099Srwatson	struct mac_mls *subj, *obj;
2831101099Srwatson
2832172955Srwatson	if (!mls_enabled)
2833101099Srwatson		return (0);
2834101099Srwatson
2835122524Srwatson	subj = SLOT(cred->cr_label);
2836168976Srwatson	obj = SLOT(dvplabel);
2837101099Srwatson
2838172955Srwatson	if (!mls_dominate_effective(subj, obj))
2839101099Srwatson		return (EACCES);
2840101099Srwatson
2841101099Srwatson	return (0);
2842101099Srwatson}
2843101099Srwatson
2844101099Srwatsonstatic int
2845172955Srwatsonmls_vnode_check_readlink(struct ucred *cred, struct vnode *vp,
2846168976Srwatson    struct label *vplabel)
2847101099Srwatson{
2848101099Srwatson	struct mac_mls *subj, *obj;
2849101099Srwatson
2850172955Srwatson	if (!mls_enabled)
2851101099Srwatson		return (0);
2852101099Srwatson
2853122524Srwatson	subj = SLOT(cred->cr_label);
2854168976Srwatson	obj = SLOT(vplabel);
2855101099Srwatson
2856172955Srwatson	if (!mls_dominate_effective(subj, obj))
2857101099Srwatson		return (EACCES);
2858101099Srwatson
2859101099Srwatson	return (0);
2860101099Srwatson}
2861101099Srwatson
2862101099Srwatsonstatic int
2863172955Srwatsonmls_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
2864168976Srwatson    struct label *vplabel, struct label *newlabel)
2865101099Srwatson{
2866101099Srwatson	struct mac_mls *old, *new, *subj;
2867105634Srwatson	int error;
2868101099Srwatson
2869168976Srwatson	old = SLOT(vplabel);
2870101099Srwatson	new = SLOT(newlabel);
2871122524Srwatson	subj = SLOT(cred->cr_label);
2872101099Srwatson
2873101099Srwatson	/*
2874105634Srwatson	 * If there is an MLS label update for the vnode, it must be a
2875132232Srwatson	 * effective label.
2876101099Srwatson	 */
2877132232Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2878105634Srwatson	if (error)
2879105634Srwatson		return (error);
2880101099Srwatson
2881101099Srwatson	/*
2882105634Srwatson	 * To perform a relabel of the vnode (MLS label or not), MLS must
2883105634Srwatson	 * authorize the relabel.
2884101099Srwatson	 */
2885172955Srwatson	if (!mls_effective_in_range(old, subj))
2886101099Srwatson		return (EPERM);
2887101099Srwatson
2888101099Srwatson	/*
2889105634Srwatson	 * If the MLS label is to be changed, authorize as appropriate.
2890101099Srwatson	 */
2891132232Srwatson	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2892105634Srwatson		/*
2893105634Srwatson		 * To change the MLS label on a vnode, the new vnode label
2894105634Srwatson		 * must be in the subject range.
2895105634Srwatson		 */
2896172955Srwatson		if (!mls_effective_in_range(new, subj))
2897105634Srwatson			return (EPERM);
2898101099Srwatson
2899105634Srwatson		/*
2900172955Srwatson		 * To change the MLS label on the vnode to be EQUAL, the
2901172955Srwatson		 * subject must have appropriate privilege.
2902105634Srwatson		 */
2903172955Srwatson		if (mls_contains_equal(new)) {
2904172955Srwatson			error = mls_subject_privileged(subj);
2905105634Srwatson			if (error)
2906105634Srwatson				return (error);
2907105634Srwatson		}
2908105634Srwatson	}
2909105634Srwatson
2910105634Srwatson	return (0);
2911101099Srwatson}
2912101099Srwatson
2913101099Srwatsonstatic int
2914172955Srwatsonmls_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
2915168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2916101099Srwatson    struct componentname *cnp)
2917101099Srwatson{
2918101099Srwatson	struct mac_mls *subj, *obj;
2919101099Srwatson
2920172955Srwatson	if (!mls_enabled)
2921101099Srwatson		return (0);
2922101099Srwatson
2923122524Srwatson	subj = SLOT(cred->cr_label);
2924168976Srwatson	obj = SLOT(dvplabel);
2925101099Srwatson
2926172955Srwatson	if (!mls_dominate_effective(obj, subj))
2927101099Srwatson		return (EACCES);
2928101099Srwatson
2929168976Srwatson	obj = SLOT(vplabel);
2930101099Srwatson
2931172955Srwatson	if (!mls_dominate_effective(obj, subj))
2932101099Srwatson		return (EACCES);
2933101099Srwatson
2934101099Srwatson	return (0);
2935101099Srwatson}
2936101099Srwatson
2937101099Srwatsonstatic int
2938172955Srwatsonmls_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
2939168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2940168976Srwatson    int samedir, struct componentname *cnp)
2941101099Srwatson{
2942101099Srwatson	struct mac_mls *subj, *obj;
2943101099Srwatson
2944172955Srwatson	if (!mls_enabled)
2945101099Srwatson		return (0);
2946101099Srwatson
2947122524Srwatson	subj = SLOT(cred->cr_label);
2948168976Srwatson	obj = SLOT(dvplabel);
2949101099Srwatson
2950172955Srwatson	if (!mls_dominate_effective(obj, subj))
2951101099Srwatson		return (EACCES);
2952101099Srwatson
2953101099Srwatson	if (vp != NULL) {
2954168976Srwatson		obj = SLOT(vplabel);
2955101099Srwatson
2956172955Srwatson		if (!mls_dominate_effective(obj, subj))
2957101099Srwatson			return (EACCES);
2958101099Srwatson	}
2959101099Srwatson
2960101099Srwatson	return (0);
2961101099Srwatson}
2962101099Srwatson
2963101099Srwatsonstatic int
2964172955Srwatsonmls_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
2965168976Srwatson    struct label *vplabel)
2966101099Srwatson{
2967101099Srwatson	struct mac_mls *subj, *obj;
2968101099Srwatson
2969172955Srwatson	if (!mls_enabled)
2970101099Srwatson		return (0);
2971101099Srwatson
2972122524Srwatson	subj = SLOT(cred->cr_label);
2973168976Srwatson	obj = SLOT(vplabel);
2974101099Srwatson
2975172955Srwatson	if (!mls_dominate_effective(obj, subj))
2976101099Srwatson		return (EACCES);
2977101099Srwatson
2978101099Srwatson	return (0);
2979101099Srwatson}
2980101099Srwatson
2981101099Srwatsonstatic int
2982172955Srwatsonmls_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
2983168976Srwatson    struct label *vplabel, acl_type_t type, struct acl *acl)
2984101099Srwatson{
2985101099Srwatson	struct mac_mls *subj, *obj;
2986101099Srwatson
2987172955Srwatson	if (!mls_enabled)
2988101099Srwatson		return (0);
2989101099Srwatson
2990122524Srwatson	subj = SLOT(cred->cr_label);
2991168976Srwatson	obj = SLOT(vplabel);
2992101099Srwatson
2993172955Srwatson	if (!mls_dominate_effective(obj, subj))
2994101099Srwatson		return (EACCES);
2995101099Srwatson
2996101099Srwatson	return (0);
2997101099Srwatson}
2998101099Srwatson
2999101099Srwatsonstatic int
3000172955Srwatsonmls_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
3001189533Srwatson    struct label *vplabel, int attrnamespace, const char *name)
3002101099Srwatson{
3003101099Srwatson	struct mac_mls *subj, *obj;
3004101099Srwatson
3005172955Srwatson	if (!mls_enabled)
3006101099Srwatson		return (0);
3007101099Srwatson
3008122524Srwatson	subj = SLOT(cred->cr_label);
3009168976Srwatson	obj = SLOT(vplabel);
3010101099Srwatson
3011172955Srwatson	if (!mls_dominate_effective(obj, subj))
3012101099Srwatson		return (EACCES);
3013101099Srwatson
3014101099Srwatson	/* XXX: protect the MAC EA in a special way? */
3015101099Srwatson
3016101099Srwatson	return (0);
3017101099Srwatson}
3018101099Srwatson
3019101099Srwatsonstatic int
3020172955Srwatsonmls_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
3021168976Srwatson    struct label *vplabel, u_long flags)
3022101099Srwatson{
3023101099Srwatson	struct mac_mls *subj, *obj;
3024101099Srwatson
3025172955Srwatson	if (!mls_enabled)
3026101099Srwatson		return (0);
3027101099Srwatson
3028122524Srwatson	subj = SLOT(cred->cr_label);
3029168976Srwatson	obj = SLOT(vplabel);
3030101099Srwatson
3031172955Srwatson	if (!mls_dominate_effective(obj, subj))
3032101099Srwatson		return (EACCES);
3033101099Srwatson
3034101099Srwatson	return (0);
3035101099Srwatson}
3036101099Srwatson
3037101099Srwatsonstatic int
3038172955Srwatsonmls_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
3039168976Srwatson    struct label *vplabel, mode_t mode)
3040101099Srwatson{
3041101099Srwatson	struct mac_mls *subj, *obj;
3042101099Srwatson
3043172955Srwatson	if (!mls_enabled)
3044101099Srwatson		return (0);
3045101099Srwatson
3046122524Srwatson	subj = SLOT(cred->cr_label);
3047168976Srwatson	obj = SLOT(vplabel);
3048101099Srwatson
3049172955Srwatson	if (!mls_dominate_effective(obj, subj))
3050101099Srwatson		return (EACCES);
3051101099Srwatson
3052101099Srwatson	return (0);
3053101099Srwatson}
3054101099Srwatson
3055101099Srwatsonstatic int
3056172955Srwatsonmls_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
3057168976Srwatson    struct label *vplabel, uid_t uid, gid_t gid)
3058101099Srwatson{
3059101099Srwatson	struct mac_mls *subj, *obj;
3060101099Srwatson
3061172955Srwatson	if (!mls_enabled)
3062101099Srwatson		return (0);
3063101099Srwatson
3064122524Srwatson	subj = SLOT(cred->cr_label);
3065168976Srwatson	obj = SLOT(vplabel);
3066101099Srwatson
3067172955Srwatson	if (!mls_dominate_effective(obj, subj))
3068101099Srwatson		return (EACCES);
3069101099Srwatson
3070101099Srwatson	return (0);
3071101099Srwatson}
3072101099Srwatson
3073101099Srwatsonstatic int
3074172955Srwatsonmls_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
3075168976Srwatson    struct label *vplabel, struct timespec atime, struct timespec mtime)
3076101099Srwatson{
3077101099Srwatson	struct mac_mls *subj, *obj;
3078101099Srwatson
3079172955Srwatson	if (!mls_enabled)
3080101099Srwatson		return (0);
3081101099Srwatson
3082122524Srwatson	subj = SLOT(cred->cr_label);
3083168976Srwatson	obj = SLOT(vplabel);
3084101099Srwatson
3085172955Srwatson	if (!mls_dominate_effective(obj, subj))
3086101099Srwatson		return (EACCES);
3087101099Srwatson
3088101099Srwatson	return (0);
3089101099Srwatson}
3090101099Srwatson
3091101099Srwatsonstatic int
3092172955Srwatsonmls_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred,
3093168976Srwatson    struct vnode *vp, struct label *vplabel)
3094101099Srwatson{
3095101099Srwatson	struct mac_mls *subj, *obj;
3096101099Srwatson
3097172955Srwatson	if (!mls_enabled)
3098101099Srwatson		return (0);
3099101099Srwatson
3100122524Srwatson	subj = SLOT(active_cred->cr_label);
3101168976Srwatson	obj = SLOT(vplabel);
3102101099Srwatson
3103172955Srwatson	if (!mls_dominate_effective(subj, obj))
3104101099Srwatson		return (EACCES);
3105101099Srwatson
3106101099Srwatson	return (0);
3107101099Srwatson}
3108101099Srwatson
3109102112Srwatsonstatic int
3110172955Srwatsonmls_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
3111172107Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
3112172107Srwatson    struct componentname *cnp)
3113172107Srwatson{
3114172107Srwatson	struct mac_mls *subj, *obj;
3115172107Srwatson
3116172955Srwatson	if (!mls_enabled)
3117172107Srwatson		return (0);
3118172107Srwatson
3119172107Srwatson	subj = SLOT(cred->cr_label);
3120172107Srwatson	obj = SLOT(dvplabel);
3121172107Srwatson
3122172955Srwatson	if (!mls_dominate_effective(obj, subj))
3123172107Srwatson		return (EACCES);
3124172107Srwatson
3125172107Srwatson	obj = SLOT(vplabel);
3126172107Srwatson
3127172955Srwatson	if (!mls_dominate_effective(obj, subj))
3128172107Srwatson		return (EACCES);
3129172107Srwatson
3130172107Srwatson	return (0);
3131172107Srwatson}
3132172107Srwatson
3133172107Srwatsonstatic int
3134172955Srwatsonmls_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred,
3135168976Srwatson    struct vnode *vp, struct label *vplabel)
3136102112Srwatson{
3137102112Srwatson	struct mac_mls *subj, *obj;
3138102112Srwatson
3139172955Srwatson	if (!mls_enabled || !revocation_enabled)
3140102112Srwatson		return (0);
3141102112Srwatson
3142122524Srwatson	subj = SLOT(active_cred->cr_label);
3143168976Srwatson	obj = SLOT(vplabel);
3144102112Srwatson
3145172955Srwatson	if (!mls_dominate_effective(obj, subj))
3146102112Srwatson		return (EACCES);
3147102112Srwatson
3148102112Srwatson	return (0);
3149102112Srwatson}
3150102112Srwatson
3151173138Srwatsonstatic int
3152173138Srwatsonmls_vnode_create_extattr(struct ucred *cred, struct mount *mp,
3153173138Srwatson    struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
3154173138Srwatson    struct vnode *vp, struct label *vplabel, struct componentname *cnp)
3155173138Srwatson{
3156173138Srwatson	struct mac_mls *source, *dest, mm_temp;
3157173138Srwatson	size_t buflen;
3158173138Srwatson	int error;
3159173138Srwatson
3160173138Srwatson	buflen = sizeof(mm_temp);
3161173138Srwatson	bzero(&mm_temp, buflen);
3162173138Srwatson
3163173138Srwatson	source = SLOT(cred->cr_label);
3164173138Srwatson	dest = SLOT(vplabel);
3165173138Srwatson	mls_copy_effective(source, &mm_temp);
3166173138Srwatson
3167173138Srwatson	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
3168173138Srwatson	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
3169173138Srwatson	if (error == 0)
3170173138Srwatson		mls_copy_effective(source, dest);
3171173138Srwatson	return (error);
3172173138Srwatson}
3173173138Srwatson
3174173138Srwatsonstatic void
3175173138Srwatsonmls_vnode_relabel(struct ucred *cred, struct vnode *vp,
3176173138Srwatson    struct label *vplabel, struct label *label)
3177173138Srwatson{
3178173138Srwatson	struct mac_mls *source, *dest;
3179173138Srwatson
3180173138Srwatson	source = SLOT(label);
3181173138Srwatson	dest = SLOT(vplabel);
3182173138Srwatson
3183173138Srwatson	mls_copy(source, dest);
3184173138Srwatson}
3185173138Srwatson
3186173138Srwatsonstatic int
3187173138Srwatsonmls_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
3188173138Srwatson    struct label *vplabel, struct label *intlabel)
3189173138Srwatson{
3190173138Srwatson	struct mac_mls *source, mm_temp;
3191173138Srwatson	size_t buflen;
3192173138Srwatson	int error;
3193173138Srwatson
3194173138Srwatson	buflen = sizeof(mm_temp);
3195173138Srwatson	bzero(&mm_temp, buflen);
3196173138Srwatson
3197173138Srwatson	source = SLOT(intlabel);
3198173138Srwatson	if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0)
3199173138Srwatson		return (0);
3200173138Srwatson
3201173138Srwatson	mls_copy_effective(source, &mm_temp);
3202173138Srwatson
3203173138Srwatson	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
3204173138Srwatson	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
3205173138Srwatson	return (error);
3206173138Srwatson}
3207173138Srwatson
3208172955Srwatsonstatic struct mac_policy_ops mls_ops =
3209101099Srwatson{
3210172955Srwatson	.mpo_init = mls_init,
3211173138Srwatson
3212173138Srwatson	.mpo_bpfdesc_check_receive = mls_bpfdesc_check_receive,
3213173138Srwatson	.mpo_bpfdesc_create = mls_bpfdesc_create,
3214173138Srwatson	.mpo_bpfdesc_create_mbuf = mls_bpfdesc_create_mbuf,
3215173138Srwatson	.mpo_bpfdesc_destroy_label = mls_destroy_label,
3216172955Srwatson	.mpo_bpfdesc_init_label = mls_init_label,
3217173138Srwatson
3218184407Srwatson	.mpo_cred_associate_nfsd = mls_cred_associate_nfsd,
3219173138Srwatson	.mpo_cred_check_relabel = mls_cred_check_relabel,
3220173138Srwatson	.mpo_cred_check_visible = mls_cred_check_visible,
3221173138Srwatson	.mpo_cred_copy_label = mls_copy_label,
3222184407Srwatson	.mpo_cred_create_init = mls_cred_create_init,
3223184407Srwatson	.mpo_cred_create_swapper = mls_cred_create_swapper,
3224172955Srwatson	.mpo_cred_destroy_label = mls_destroy_label,
3225172955Srwatson	.mpo_cred_externalize_label = mls_externalize_label,
3226173138Srwatson	.mpo_cred_init_label = mls_init_label,
3227172955Srwatson	.mpo_cred_internalize_label = mls_internalize_label,
3228173138Srwatson	.mpo_cred_relabel = mls_cred_relabel,
3229173138Srwatson
3230172955Srwatson	.mpo_devfs_create_device = mls_devfs_create_device,
3231172955Srwatson	.mpo_devfs_create_directory = mls_devfs_create_directory,
3232172955Srwatson	.mpo_devfs_create_symlink = mls_devfs_create_symlink,
3233173138Srwatson	.mpo_devfs_destroy_label = mls_destroy_label,
3234173138Srwatson	.mpo_devfs_init_label = mls_init_label,
3235172955Srwatson	.mpo_devfs_update = mls_devfs_update,
3236172955Srwatson	.mpo_devfs_vnode_associate = mls_devfs_vnode_associate,
3237173138Srwatson
3238173138Srwatson	.mpo_ifnet_check_relabel = mls_ifnet_check_relabel,
3239173138Srwatson	.mpo_ifnet_check_transmit = mls_ifnet_check_transmit,
3240173138Srwatson	.mpo_ifnet_copy_label = mls_copy_label,
3241172955Srwatson	.mpo_ifnet_create = mls_ifnet_create,
3242173138Srwatson	.mpo_ifnet_create_mbuf = mls_ifnet_create_mbuf,
3243173138Srwatson	.mpo_ifnet_destroy_label = mls_destroy_label,
3244173138Srwatson	.mpo_ifnet_externalize_label = mls_externalize_label,
3245173138Srwatson	.mpo_ifnet_init_label = mls_init_label,
3246173138Srwatson	.mpo_ifnet_internalize_label = mls_internalize_label,
3247173138Srwatson	.mpo_ifnet_relabel = mls_ifnet_relabel,
3248173138Srwatson
3249173138Srwatson	.mpo_inpcb_check_deliver = mls_inpcb_check_deliver,
3250183980Sbz	.mpo_inpcb_check_visible = mls_inpcb_check_visible,
3251172955Srwatson	.mpo_inpcb_create = mls_inpcb_create,
3252173138Srwatson	.mpo_inpcb_create_mbuf = mls_inpcb_create_mbuf,
3253173138Srwatson	.mpo_inpcb_destroy_label = mls_destroy_label,
3254173138Srwatson	.mpo_inpcb_init_label = mls_init_label_waitcheck,
3255173138Srwatson	.mpo_inpcb_sosetlabel = mls_inpcb_sosetlabel,
3256173138Srwatson
3257184308Srwatson	.mpo_ip6q_create = mls_ip6q_create,
3258184308Srwatson	.mpo_ip6q_destroy_label = mls_destroy_label,
3259184308Srwatson	.mpo_ip6q_init_label = mls_init_label_waitcheck,
3260184308Srwatson	.mpo_ip6q_match = mls_ip6q_match,
3261184308Srwatson	.mpo_ip6q_reassemble = mls_ip6q_reassemble,
3262184308Srwatson	.mpo_ip6q_update = mls_ip6q_update,
3263184308Srwatson
3264172955Srwatson	.mpo_ipq_create = mls_ipq_create,
3265173138Srwatson	.mpo_ipq_destroy_label = mls_destroy_label,
3266173138Srwatson	.mpo_ipq_init_label = mls_init_label_waitcheck,
3267172955Srwatson	.mpo_ipq_match = mls_ipq_match,
3268173138Srwatson	.mpo_ipq_reassemble = mls_ipq_reassemble,
3269172955Srwatson	.mpo_ipq_update = mls_ipq_update,
3270173138Srwatson
3271173138Srwatson	.mpo_mbuf_copy_label = mls_copy_label,
3272173138Srwatson	.mpo_mbuf_destroy_label = mls_destroy_label,
3273173138Srwatson	.mpo_mbuf_init_label = mls_init_label_waitcheck,
3274173138Srwatson
3275172955Srwatson	.mpo_mount_check_stat = mls_mount_check_stat,
3276173138Srwatson	.mpo_mount_create = mls_mount_create,
3277173138Srwatson	.mpo_mount_destroy_label = mls_destroy_label,
3278173138Srwatson	.mpo_mount_init_label = mls_init_label,
3279173138Srwatson
3280173138Srwatson	.mpo_netatalk_aarp_send = mls_netatalk_aarp_send,
3281173138Srwatson
3282173138Srwatson	.mpo_netinet_arp_send = mls_netinet_arp_send,
3283173138Srwatson	.mpo_netinet_firewall_reply = mls_netinet_firewall_reply,
3284173138Srwatson	.mpo_netinet_firewall_send = mls_netinet_firewall_send,
3285173138Srwatson	.mpo_netinet_fragment = mls_netinet_fragment,
3286173138Srwatson	.mpo_netinet_icmp_reply = mls_netinet_icmp_reply,
3287173138Srwatson	.mpo_netinet_igmp_send = mls_netinet_igmp_send,
3288173138Srwatson
3289173138Srwatson	.mpo_netinet6_nd6_send = mls_netinet6_nd6_send,
3290173138Srwatson
3291172955Srwatson	.mpo_pipe_check_ioctl = mls_pipe_check_ioctl,
3292172955Srwatson	.mpo_pipe_check_poll = mls_pipe_check_poll,
3293172955Srwatson	.mpo_pipe_check_read = mls_pipe_check_read,
3294172955Srwatson	.mpo_pipe_check_relabel = mls_pipe_check_relabel,
3295172955Srwatson	.mpo_pipe_check_stat = mls_pipe_check_stat,
3296172955Srwatson	.mpo_pipe_check_write = mls_pipe_check_write,
3297173138Srwatson	.mpo_pipe_copy_label = mls_copy_label,
3298173138Srwatson	.mpo_pipe_create = mls_pipe_create,
3299173138Srwatson	.mpo_pipe_destroy_label = mls_destroy_label,
3300173138Srwatson	.mpo_pipe_externalize_label = mls_externalize_label,
3301173138Srwatson	.mpo_pipe_init_label = mls_init_label,
3302173138Srwatson	.mpo_pipe_internalize_label = mls_internalize_label,
3303173138Srwatson	.mpo_pipe_relabel = mls_pipe_relabel,
3304173138Srwatson
3305172955Srwatson	.mpo_posixsem_check_getvalue = mls_posixsem_check_rdonly,
3306180059Sjhb	.mpo_posixsem_check_open = mls_posixsem_check_openunlink,
3307172955Srwatson	.mpo_posixsem_check_post = mls_posixsem_check_write,
3308225344Srwatson	.mpo_posixsem_check_setmode = mls_posixsem_check_setmode,
3309225344Srwatson	.mpo_posixsem_check_setowner = mls_posixsem_check_setowner,
3310180059Sjhb	.mpo_posixsem_check_stat = mls_posixsem_check_rdonly,
3311180059Sjhb	.mpo_posixsem_check_unlink = mls_posixsem_check_openunlink,
3312172955Srwatson	.mpo_posixsem_check_wait = mls_posixsem_check_write,
3313173138Srwatson	.mpo_posixsem_create = mls_posixsem_create,
3314173138Srwatson	.mpo_posixsem_destroy_label = mls_destroy_label,
3315173138Srwatson	.mpo_posixsem_init_label = mls_init_label,
3316173138Srwatson
3317225344Srwatson	.mpo_posixshm_check_mmap = mls_posixshm_check_mmap,
3318225344Srwatson	.mpo_posixshm_check_open = mls_posixshm_check_open,
3319254603Skib	.mpo_posixshm_check_read = mls_posixshm_check_read,
3320225344Srwatson	.mpo_posixshm_check_setmode = mls_posixshm_check_setmode,
3321225344Srwatson	.mpo_posixshm_check_setowner = mls_posixshm_check_setowner,
3322225344Srwatson	.mpo_posixshm_check_stat = mls_posixshm_check_stat,
3323225344Srwatson	.mpo_posixshm_check_truncate = mls_posixshm_check_truncate,
3324225344Srwatson	.mpo_posixshm_check_unlink = mls_posixshm_check_unlink,
3325254603Skib	.mpo_posixshm_check_write = mls_posixshm_check_write,
3326225344Srwatson	.mpo_posixshm_create = mls_posixshm_create,
3327225344Srwatson	.mpo_posixshm_destroy_label = mls_destroy_label,
3328225344Srwatson	.mpo_posixshm_init_label = mls_init_label,
3329225344Srwatson
3330172955Srwatson	.mpo_proc_check_debug = mls_proc_check_debug,
3331172955Srwatson	.mpo_proc_check_sched = mls_proc_check_sched,
3332172955Srwatson	.mpo_proc_check_signal = mls_proc_check_signal,
3333173138Srwatson
3334172955Srwatson	.mpo_socket_check_deliver = mls_socket_check_deliver,
3335172955Srwatson	.mpo_socket_check_relabel = mls_socket_check_relabel,
3336172955Srwatson	.mpo_socket_check_visible = mls_socket_check_visible,
3337173138Srwatson	.mpo_socket_copy_label = mls_copy_label,
3338173138Srwatson	.mpo_socket_create = mls_socket_create,
3339173138Srwatson	.mpo_socket_create_mbuf = mls_socket_create_mbuf,
3340173138Srwatson	.mpo_socket_destroy_label = mls_destroy_label,
3341173138Srwatson	.mpo_socket_externalize_label = mls_externalize_label,
3342173138Srwatson	.mpo_socket_init_label = mls_init_label_waitcheck,
3343173138Srwatson	.mpo_socket_internalize_label = mls_internalize_label,
3344173138Srwatson	.mpo_socket_newconn = mls_socket_newconn,
3345173138Srwatson	.mpo_socket_relabel = mls_socket_relabel,
3346173138Srwatson
3347173138Srwatson	.mpo_socketpeer_destroy_label = mls_destroy_label,
3348173138Srwatson	.mpo_socketpeer_externalize_label = mls_externalize_label,
3349173138Srwatson	.mpo_socketpeer_init_label = mls_init_label_waitcheck,
3350173138Srwatson	.mpo_socketpeer_set_from_mbuf = mls_socketpeer_set_from_mbuf,
3351173138Srwatson	.mpo_socketpeer_set_from_socket = mls_socketpeer_set_from_socket,
3352173138Srwatson
3353173138Srwatson	.mpo_syncache_create = mls_syncache_create,
3354173138Srwatson	.mpo_syncache_create_mbuf = mls_syncache_create_mbuf,
3355173138Srwatson	.mpo_syncache_destroy_label = mls_destroy_label,
3356173138Srwatson	.mpo_syncache_init_label = mls_init_label_waitcheck,
3357173138Srwatson
3358173138Srwatson	.mpo_sysvmsg_cleanup = mls_sysvmsg_cleanup,
3359173138Srwatson	.mpo_sysvmsg_create = mls_sysvmsg_create,
3360173138Srwatson	.mpo_sysvmsg_destroy_label = mls_destroy_label,
3361173138Srwatson	.mpo_sysvmsg_init_label = mls_init_label,
3362173138Srwatson
3363173138Srwatson	.mpo_sysvmsq_check_msgrcv = mls_sysvmsq_check_msgrcv,
3364173138Srwatson	.mpo_sysvmsq_check_msgrmid = mls_sysvmsq_check_msgrmid,
3365173138Srwatson	.mpo_sysvmsq_check_msqget = mls_sysvmsq_check_msqget,
3366173138Srwatson	.mpo_sysvmsq_check_msqsnd = mls_sysvmsq_check_msqsnd,
3367173138Srwatson	.mpo_sysvmsq_check_msqrcv = mls_sysvmsq_check_msqrcv,
3368173138Srwatson	.mpo_sysvmsq_check_msqctl = mls_sysvmsq_check_msqctl,
3369173138Srwatson	.mpo_sysvmsq_cleanup = mls_sysvmsq_cleanup,
3370173138Srwatson	.mpo_sysvmsq_destroy_label = mls_destroy_label,
3371173138Srwatson	.mpo_sysvmsq_init_label = mls_init_label,
3372173138Srwatson	.mpo_sysvmsq_create = mls_sysvmsq_create,
3373173138Srwatson
3374173138Srwatson	.mpo_sysvsem_check_semctl = mls_sysvsem_check_semctl,
3375173138Srwatson	.mpo_sysvsem_check_semget = mls_sysvsem_check_semget,
3376173138Srwatson	.mpo_sysvsem_check_semop = mls_sysvsem_check_semop,
3377173138Srwatson	.mpo_sysvsem_cleanup = mls_sysvsem_cleanup,
3378173138Srwatson	.mpo_sysvsem_create = mls_sysvsem_create,
3379173138Srwatson	.mpo_sysvsem_destroy_label = mls_destroy_label,
3380173138Srwatson	.mpo_sysvsem_init_label = mls_init_label,
3381173138Srwatson
3382173138Srwatson	.mpo_sysvshm_check_shmat = mls_sysvshm_check_shmat,
3383173138Srwatson	.mpo_sysvshm_check_shmctl = mls_sysvshm_check_shmctl,
3384173138Srwatson	.mpo_sysvshm_check_shmget = mls_sysvshm_check_shmget,
3385173138Srwatson	.mpo_sysvshm_cleanup = mls_sysvshm_cleanup,
3386173138Srwatson	.mpo_sysvshm_create = mls_sysvshm_create,
3387173138Srwatson	.mpo_sysvshm_destroy_label = mls_destroy_label,
3388173138Srwatson	.mpo_sysvshm_init_label = mls_init_label,
3389173138Srwatson
3390173138Srwatson
3391172955Srwatson	.mpo_system_check_acct = mls_system_check_acct,
3392172955Srwatson	.mpo_system_check_auditctl = mls_system_check_auditctl,
3393172955Srwatson	.mpo_system_check_swapon = mls_system_check_swapon,
3394173138Srwatson
3395173138Srwatson	.mpo_vnode_associate_extattr = mls_vnode_associate_extattr,
3396173138Srwatson	.mpo_vnode_associate_singlelabel = mls_vnode_associate_singlelabel,
3397172955Srwatson	.mpo_vnode_check_access = mls_vnode_check_open,
3398172955Srwatson	.mpo_vnode_check_chdir = mls_vnode_check_chdir,
3399172955Srwatson	.mpo_vnode_check_chroot = mls_vnode_check_chroot,
3400172955Srwatson	.mpo_vnode_check_create = mls_vnode_check_create,
3401172955Srwatson	.mpo_vnode_check_deleteacl = mls_vnode_check_deleteacl,
3402172955Srwatson	.mpo_vnode_check_deleteextattr = mls_vnode_check_deleteextattr,
3403172955Srwatson	.mpo_vnode_check_exec = mls_vnode_check_exec,
3404172955Srwatson	.mpo_vnode_check_getacl = mls_vnode_check_getacl,
3405172955Srwatson	.mpo_vnode_check_getextattr = mls_vnode_check_getextattr,
3406172955Srwatson	.mpo_vnode_check_link = mls_vnode_check_link,
3407172955Srwatson	.mpo_vnode_check_listextattr = mls_vnode_check_listextattr,
3408172955Srwatson	.mpo_vnode_check_lookup = mls_vnode_check_lookup,
3409172955Srwatson	.mpo_vnode_check_mmap = mls_vnode_check_mmap,
3410172955Srwatson	.mpo_vnode_check_open = mls_vnode_check_open,
3411172955Srwatson	.mpo_vnode_check_poll = mls_vnode_check_poll,
3412172955Srwatson	.mpo_vnode_check_read = mls_vnode_check_read,
3413172955Srwatson	.mpo_vnode_check_readdir = mls_vnode_check_readdir,
3414172955Srwatson	.mpo_vnode_check_readlink = mls_vnode_check_readlink,
3415172955Srwatson	.mpo_vnode_check_relabel = mls_vnode_check_relabel,
3416172955Srwatson	.mpo_vnode_check_rename_from = mls_vnode_check_rename_from,
3417172955Srwatson	.mpo_vnode_check_rename_to = mls_vnode_check_rename_to,
3418172955Srwatson	.mpo_vnode_check_revoke = mls_vnode_check_revoke,
3419172955Srwatson	.mpo_vnode_check_setacl = mls_vnode_check_setacl,
3420172955Srwatson	.mpo_vnode_check_setextattr = mls_vnode_check_setextattr,
3421172955Srwatson	.mpo_vnode_check_setflags = mls_vnode_check_setflags,
3422172955Srwatson	.mpo_vnode_check_setmode = mls_vnode_check_setmode,
3423172955Srwatson	.mpo_vnode_check_setowner = mls_vnode_check_setowner,
3424172955Srwatson	.mpo_vnode_check_setutimes = mls_vnode_check_setutimes,
3425172955Srwatson	.mpo_vnode_check_stat = mls_vnode_check_stat,
3426172955Srwatson	.mpo_vnode_check_unlink = mls_vnode_check_unlink,
3427172955Srwatson	.mpo_vnode_check_write = mls_vnode_check_write,
3428173138Srwatson	.mpo_vnode_copy_label = mls_copy_label,
3429173138Srwatson	.mpo_vnode_create_extattr = mls_vnode_create_extattr,
3430173138Srwatson	.mpo_vnode_destroy_label = mls_destroy_label,
3431173138Srwatson	.mpo_vnode_externalize_label = mls_externalize_label,
3432173138Srwatson	.mpo_vnode_init_label = mls_init_label,
3433173138Srwatson	.mpo_vnode_internalize_label = mls_internalize_label,
3434173138Srwatson	.mpo_vnode_relabel = mls_vnode_relabel,
3435173138Srwatson	.mpo_vnode_setlabel_extattr = mls_vnode_setlabel_extattr,
3436101099Srwatson};
3437101099Srwatson
3438172955SrwatsonMAC_POLICY_SET(&mls_ops, mac_mls, "TrustedBSD MAC/MLS",
3439187016Srwatson    MPC_LOADTIME_FLAG_NOTLATE, &mls_slot);
3440