mac_mls.c revision 179781
1101099Srwatson/*-
2166533Srwatson * Copyright (c) 1999-2002, 2007 Robert N. M. Watson
3140628Srwatson * 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 *
9140628Srwatson * This software was developed for the FreeBSD Project in part by McAfee
10140628Srwatson * Research, the Security Research Division of McAfee, Inc. under
11140628Srwatson * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
12140628Srwatson * CHATS research program.
13101099Srwatson *
14172930Srwatson * This software was enhanced by SPARTA ISSO under SPAWAR contract
15172930Srwatson * N66001-04-C-6019 ("SEFOS").
16172930Srwatson *
17101099Srwatson * Redistribution and use in source and binary forms, with or without
18101099Srwatson * modification, are permitted provided that the following conditions
19101099Srwatson * are met:
20101099Srwatson * 1. Redistributions of source code must retain the above copyright
21101099Srwatson *    notice, this list of conditions and the following disclaimer.
22101099Srwatson * 2. Redistributions in binary form must reproduce the above copyright
23101099Srwatson *    notice, this list of conditions and the following disclaimer in the
24101099Srwatson *    documentation and/or other materials provided with the distribution.
25101099Srwatson *
26101099Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27101099Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28101099Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29101099Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30101099Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31101099Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32101099Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33101099Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34101099Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35101099Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36101099Srwatson * SUCH DAMAGE.
37101099Srwatson *
38101099Srwatson * $FreeBSD: head/sys/security/mac_mls/mac_mls.c 179781 2008-06-13 22:14:15Z rwatson $
39101099Srwatson */
40101099Srwatson
41101099Srwatson/*
42101099Srwatson * Developed by the TrustedBSD Project.
43168951Srwatson *
44101099Srwatson * MLS fixed label mandatory confidentiality policy.
45101099Srwatson */
46101099Srwatson
47101099Srwatson#include <sys/types.h>
48101099Srwatson#include <sys/param.h>
49105988Srwatson#include <sys/acl.h>
50101099Srwatson#include <sys/conf.h>
51164184Strhodes#include <sys/extattr.h>
52103183Sbde#include <sys/kernel.h>
53145076Scsjp#include <sys/ksem.h>
54101099Srwatson#include <sys/mman.h>
55168951Srwatson#include <sys/malloc.h>
56101099Srwatson#include <sys/mount.h>
57115497Srwatson#include <sys/proc.h>
58101099Srwatson#include <sys/sbuf.h>
59101099Srwatson#include <sys/systm.h>
60101099Srwatson#include <sys/sysproto.h>
61105696Srwatson#include <sys/sysent.h>
62101099Srwatson#include <sys/systm.h>
63101099Srwatson#include <sys/vnode.h>
64101099Srwatson#include <sys/file.h>
65101099Srwatson#include <sys/socket.h>
66101099Srwatson#include <sys/socketvar.h>
67150340Sphk#include <sys/pipe.h>
68101099Srwatson#include <sys/sx.h>
69140628Srwatson#include <sys/sysctl.h>
70140628Srwatson#include <sys/msg.h>
71140628Srwatson#include <sys/sem.h>
72101099Srwatson#include <sys/shm.h>
73101099Srwatson
74101099Srwatson#include <fs/devfs/devfs.h>
75101099Srwatson
76101099Srwatson#include <net/bpfdesc.h>
77101099Srwatson#include <net/if.h>
78101099Srwatson#include <net/if_types.h>
79101099Srwatson#include <net/if_var.h>
80101099Srwatson
81122875Srwatson#include <netinet/in.h>
82101099Srwatson#include <netinet/in_pcb.h>
83101099Srwatson#include <netinet/ip_var.h>
84122879Srwatson
85101099Srwatson#include <vm/uma.h>
86101099Srwatson#include <vm/vm.h>
87165469Srwatson
88101099Srwatson#include <security/mac/mac_policy.h>
89101099Srwatson#include <security/mac_mls/mac_mls.h>
90101099Srwatson
91101099SrwatsonSYSCTL_DECL(_security_mac);
92101099Srwatson
93101099SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
94101099Srwatson    "TrustedBSD mac_mls policy controls");
95172955Srwatson
96105988Srwatsonstatic int	mls_label_size = sizeof(struct mac_mls);
97172955SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
98105988Srwatson    &mls_label_size, 0, "Size of struct mac_mls");
99172955Srwatson
100172955Srwatsonstatic int	mls_enabled = 1;
101172955SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW, &mls_enabled, 0,
102172955Srwatson    "Enforce MAC/MLS policy");
103101099SrwatsonTUNABLE_INT("security.mac.mls.enabled", &mls_enabled);
104101099Srwatson
105101099Srwatsonstatic int	destroyed_not_inited;
106101099SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
107101099Srwatson    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
108101099Srwatson
109101099Srwatsonstatic int	ptys_equal = 0;
110101099SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
111101099Srwatson    &ptys_equal, 0, "Label pty devices as mls/equal on create");
112101099SrwatsonTUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
113101099Srwatson
114101099Srwatsonstatic int	revocation_enabled = 0;
115101099SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
116101099Srwatson    &revocation_enabled, 0, "Revoke access to objects on relabel");
117101099SrwatsonTUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled);
118101099Srwatson
119105643Srwatsonstatic int	max_compartments = MAC_MLS_MAX_COMPARTMENTS;
120105643SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
121105643Srwatson    &max_compartments, 0, "Maximum compartments the policy supports");
122105643Srwatson
123105606Srwatsonstatic int	mls_slot;
124105606Srwatson#define	SLOT(l)	((struct mac_mls *)mac_label_get((l), mls_slot))
125105606Srwatson#define	SLOT_SET(l, val) mac_label_set((l), mls_slot, (uintptr_t)(val))
126105606Srwatson
127105606Srwatsonstatic uma_zone_t	zone_mls;
128153927Scsjp
129153927Scsjpstatic __inline int
130153927Scsjpmls_bit_set_empty(u_char *set) {
131153927Scsjp	int i;
132153927Scsjp
133105637Srwatson	for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++)
134101099Srwatson		if (set[i] != 0)
135105637Srwatson			return (0);
136105637Srwatson	return (1);
137101099Srwatson}
138172955Srwatson
139172955Srwatsonstatic struct mac_mls *
140172955Srwatsonmls_alloc(int flag)
141101099Srwatson{
142122879Srwatson
143101099Srwatson	return (uma_zalloc(zone_mls, flag | M_ZERO));
144105643Srwatson}
145105643Srwatson
146105643Srwatsonstatic void
147105643Srwatsonmls_free(struct mac_mls *mm)
148105643Srwatson{
149105643Srwatson
150105643Srwatson	if (mm != NULL)
151105643Srwatson		uma_zfree(zone_mls, mm);
152105643Srwatson	else
153105643Srwatson		atomic_add_int(&destroyed_not_inited, 1);
154101099Srwatson}
155104514Srwatson
156101099Srwatsonstatic int
157101099Srwatsonmls_atmostflags(struct mac_mls *mm, int flags)
158122879Srwatson{
159101099Srwatson
160101099Srwatson	if ((mm->mm_flags & flags) != mm->mm_flags)
161101099Srwatson		return (EINVAL);
162172955Srwatson	return (0);
163101099Srwatson}
164101099Srwatson
165172955Srwatsonstatic int
166172955Srwatsonmls_dominate_element(struct mac_mls_element *a, struct mac_mls_element *b)
167101099Srwatson{
168101099Srwatson	int bit;
169101099Srwatson
170101099Srwatson	switch (a->mme_type) {
171101099Srwatson	case MAC_MLS_TYPE_EQUAL:
172172955Srwatson	case MAC_MLS_TYPE_HIGH:
173105634Srwatson		return (1);
174105634Srwatson
175172955Srwatson	case MAC_MLS_TYPE_LOW:
176105634Srwatson		switch (b->mme_type) {
177105634Srwatson		case MAC_MLS_TYPE_LEVEL:
178105634Srwatson		case MAC_MLS_TYPE_HIGH:
179105634Srwatson			return (0);
180105634Srwatson
181172955Srwatson		case MAC_MLS_TYPE_EQUAL:
182101099Srwatson		case MAC_MLS_TYPE_LOW:
183105643Srwatson			return (1);
184101099Srwatson
185105736Srwatson		default:
186101099Srwatson			panic("mls_dominate_element: b->mme_type invalid");
187101099Srwatson		}
188101099Srwatson
189101099Srwatson	case MAC_MLS_TYPE_LEVEL:
190101099Srwatson		switch (b->mme_type) {
191101099Srwatson		case MAC_MLS_TYPE_EQUAL:
192101099Srwatson		case MAC_MLS_TYPE_LOW:
193101099Srwatson			return (1);
194101099Srwatson
195101099Srwatson		case MAC_MLS_TYPE_HIGH:
196101099Srwatson			return (0);
197101099Srwatson
198101099Srwatson		case MAC_MLS_TYPE_LEVEL:
199101099Srwatson			for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++)
200101099Srwatson				if (!MAC_MLS_BIT_TEST(bit,
201172955Srwatson				    a->mme_compartments) &&
202101099Srwatson				    MAC_MLS_BIT_TEST(bit, b->mme_compartments))
203101099Srwatson					return (0);
204101099Srwatson			return (a->mme_level >= b->mme_level);
205101099Srwatson
206101099Srwatson		default:
207101099Srwatson			panic("mls_dominate_element: b->mme_type invalid");
208101099Srwatson		}
209101099Srwatson
210101099Srwatson	default:
211101099Srwatson		panic("mls_dominate_element: a->mme_type invalid");
212101099Srwatson	}
213101099Srwatson
214105643Srwatson	return (0);
215105643Srwatson}
216105643Srwatson
217105643Srwatsonstatic int
218105643Srwatsonmls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
219101099Srwatson{
220101099Srwatson
221101099Srwatson	return (mls_dominate_element(&rangeb->mm_rangehigh,
222172955Srwatson	    &rangea->mm_rangehigh) &&
223101099Srwatson	    mls_dominate_element(&rangea->mm_rangelow,
224101099Srwatson	    &rangeb->mm_rangelow));
225101099Srwatson}
226172955Srwatson
227101099Srwatsonstatic int
228101099Srwatsonmls_effective_in_range(struct mac_mls *effective, struct mac_mls *range)
229101099Srwatson{
230101099Srwatson
231101099Srwatson	KASSERT((effective->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
232101099Srwatson	    ("mls_effective_in_range: a not effective"));
233172955Srwatson	KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
234105988Srwatson	    ("mls_effective_in_range: b not range"));
235105988Srwatson
236105988Srwatson	return (mls_dominate_element(&range->mm_rangehigh,
237172955Srwatson	    &effective->mm_effective) &&
238172955Srwatson	    mls_dominate_element(&effective->mm_effective,
239172955Srwatson	    &range->mm_rangelow));
240105988Srwatson
241105988Srwatson	return (1);
242105988Srwatson}
243105988Srwatson
244105988Srwatsonstatic int
245105988Srwatsonmls_dominate_effective(struct mac_mls *a, struct mac_mls *b)
246172955Srwatson{
247101099Srwatson	KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
248101099Srwatson	    ("mls_dominate_effective: a not effective"));
249172955Srwatson	KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
250101099Srwatson	    ("mls_dominate_effective: b not effective"));
251172955Srwatson
252101099Srwatson	return (mls_dominate_element(&a->mm_effective, &b->mm_effective));
253101099Srwatson}
254101099Srwatson
255101099Srwatsonstatic int
256172955Srwatsonmls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
257101099Srwatson{
258101099Srwatson
259132232Srwatson	if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
260172955Srwatson	    b->mme_type == MAC_MLS_TYPE_EQUAL)
261103750Srwatson		return (1);
262172955Srwatson
263101099Srwatson	return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
264172955Srwatson}
265132232Srwatson
266172955Srwatsonstatic int
267101099Srwatsonmls_equal_effective(struct mac_mls *a, struct mac_mls *b)
268101099Srwatson{
269101099Srwatson
270101099Srwatson	KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
271101099Srwatson	    ("mls_equal_effective: a not effective"));
272101099Srwatson	KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
273172955Srwatson	    ("mls_equal_effective: b not effective"));
274101099Srwatson
275132232Srwatson	return (mls_equal_element(&a->mm_effective, &b->mm_effective));
276172955Srwatson}
277132232Srwatson
278172955Srwatsonstatic int
279101099Srwatsonmls_contains_equal(struct mac_mls *mm)
280172955Srwatson{
281101099Srwatson
282101099Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
283101099Srwatson		if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
284172955Srwatson			return (1);
285101099Srwatson
286101099Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
287101099Srwatson		if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL)
288101099Srwatson			return (1);
289101099Srwatson		if (mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
290101099Srwatson			return (1);
291101099Srwatson	}
292101099Srwatson
293101099Srwatson	return (0);
294101099Srwatson}
295172955Srwatson
296101099Srwatsonstatic int
297101099Srwatsonmls_subject_privileged(struct mac_mls *mm)
298132232Srwatson{
299172955Srwatson
300132232Srwatson	KASSERT((mm->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH,
301172955Srwatson	    ("mls_subject_privileged: subject doesn't have both labels"));
302101099Srwatson
303172955Srwatson	/* If the effective is EQUAL, it's ok. */
304101099Srwatson	if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
305101099Srwatson		return (0);
306101099Srwatson
307172955Srwatson	/* If either range endpoint is EQUAL, it's ok. */
308105634Srwatson	if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL ||
309105634Srwatson	    mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
310172955Srwatson		return (0);
311172955Srwatson
312105634Srwatson	/* If the range is low-high, it's ok. */
313172955Srwatson	if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW &&
314105634Srwatson	    mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH)
315172955Srwatson		return (0);
316172955Srwatson
317105634Srwatson	/* It's not ok. */
318172955Srwatson	return (EPERM);
319105637Srwatson}
320105634Srwatson
321105634Srwatsonstatic int
322105634Srwatsonmls_valid(struct mac_mls *mm)
323105634Srwatson{
324105634Srwatson
325105634Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
326172955Srwatson		switch (mm->mm_effective.mme_type) {
327105634Srwatson		case MAC_MLS_TYPE_LEVEL:
328105634Srwatson			break;
329172955Srwatson
330172955Srwatson		case MAC_MLS_TYPE_EQUAL:
331105634Srwatson		case MAC_MLS_TYPE_HIGH:
332132232Srwatson		case MAC_MLS_TYPE_LOW:
333172955Srwatson			if (mm->mm_effective.mme_level != 0 ||
334105634Srwatson			    !MAC_MLS_BIT_SET_EMPTY(
335105634Srwatson			    mm->mm_effective.mme_compartments))
336105634Srwatson				return (EINVAL);
337172955Srwatson			break;
338172955Srwatson
339105634Srwatson		default:
340105634Srwatson			return (EINVAL);
341105634Srwatson		}
342172955Srwatson	} else {
343172955Srwatson		if (mm->mm_effective.mme_type != MAC_MLS_TYPE_UNDEF)
344105634Srwatson			return (EINVAL);
345105634Srwatson	}
346105634Srwatson
347105634Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
348105634Srwatson		switch (mm->mm_rangelow.mme_type) {
349105634Srwatson		case MAC_MLS_TYPE_LEVEL:
350106091Srwatson			break;
351172955Srwatson
352105988Srwatson		case MAC_MLS_TYPE_EQUAL:
353105988Srwatson		case MAC_MLS_TYPE_HIGH:
354172955Srwatson		case MAC_MLS_TYPE_LOW:
355172955Srwatson			if (mm->mm_rangelow.mme_level != 0 ||
356105988Srwatson			    !MAC_MLS_BIT_SET_EMPTY(
357172955Srwatson			    mm->mm_rangelow.mme_compartments))
358105988Srwatson				return (EINVAL);
359105988Srwatson			break;
360105634Srwatson
361172955Srwatson		default:
362101099Srwatson			return (EINVAL);
363101099Srwatson		}
364172955Srwatson
365172955Srwatson		switch (mm->mm_rangehigh.mme_type) {
366101099Srwatson		case MAC_MLS_TYPE_LEVEL:
367101099Srwatson			break;
368101099Srwatson
369101099Srwatson		case MAC_MLS_TYPE_EQUAL:
370101099Srwatson		case MAC_MLS_TYPE_HIGH:
371101099Srwatson		case MAC_MLS_TYPE_LOW:
372172955Srwatson			if (mm->mm_rangehigh.mme_level != 0 ||
373105643Srwatson			    !MAC_MLS_BIT_SET_EMPTY(
374172955Srwatson			    mm->mm_rangehigh.mme_compartments))
375101099Srwatson				return (EINVAL);
376101099Srwatson			break;
377101099Srwatson
378101099Srwatson		default:
379101099Srwatson			return (EINVAL);
380101099Srwatson		}
381101099Srwatson		if (!mls_dominate_element(&mm->mm_rangehigh,
382172955Srwatson		    &mm->mm_rangelow))
383101099Srwatson			return (EINVAL);
384101099Srwatson	} else {
385101099Srwatson		if (mm->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
386172955Srwatson		    mm->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
387172955Srwatson			return (EINVAL);
388101099Srwatson	}
389101099Srwatson
390101099Srwatson	return (0);
391101099Srwatson}
392101099Srwatson
393101099Srwatsonstatic void
394172955Srwatsonmls_set_range(struct mac_mls *mm, u_short typelow, u_short levellow,
395105643Srwatson    u_char *compartmentslow, u_short typehigh, u_short levelhigh,
396172955Srwatson    u_char *compartmentshigh)
397101099Srwatson{
398101099Srwatson
399101099Srwatson	mm->mm_rangelow.mme_type = typelow;
400101099Srwatson	mm->mm_rangelow.mme_level = levellow;
401101099Srwatson	if (compartmentslow != NULL)
402101099Srwatson		memcpy(mm->mm_rangelow.mme_compartments,
403101099Srwatson		    compartmentslow,
404172955Srwatson		    sizeof(mm->mm_rangelow.mme_compartments));
405101099Srwatson	mm->mm_rangehigh.mme_type = typehigh;
406101099Srwatson	mm->mm_rangehigh.mme_level = levelhigh;
407101099Srwatson	if (compartmentshigh != NULL)
408101099Srwatson		memcpy(mm->mm_rangehigh.mme_compartments,
409101099Srwatson		    compartmentshigh,
410101099Srwatson		    sizeof(mm->mm_rangehigh.mme_compartments));
411172955Srwatson	mm->mm_flags |= MAC_MLS_FLAG_RANGE;
412105643Srwatson}
413172955Srwatson
414101099Srwatsonstatic void
415101099Srwatsonmls_set_effective(struct mac_mls *mm, u_short type, u_short level,
416101099Srwatson    u_char *compartments)
417101099Srwatson{
418101099Srwatson
419101099Srwatson	mm->mm_effective.mme_type = type;
420172955Srwatson	mm->mm_effective.mme_level = level;
421172955Srwatson	if (compartments != NULL)
422101099Srwatson		memcpy(mm->mm_effective.mme_compartments, compartments,
423101099Srwatson		    sizeof(mm->mm_effective.mme_compartments));
424172955Srwatson	mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
425172955Srwatson}
426101099Srwatson
427101099Srwatsonstatic void
428101099Srwatsonmls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
429101099Srwatson{
430101099Srwatson
431101099Srwatson	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
432101099Srwatson	    ("mls_copy_range: labelfrom not range"));
433172955Srwatson
434172955Srwatson	labelto->mm_rangelow = labelfrom->mm_rangelow;
435172955Srwatson	labelto->mm_rangehigh = labelfrom->mm_rangehigh;
436101099Srwatson	labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
437101099Srwatson}
438172955Srwatson
439172955Srwatsonstatic void
440105643Srwatsonmls_copy_effective(struct mac_mls *labelfrom, struct mac_mls *labelto)
441172955Srwatson{
442172955Srwatson
443172955Srwatson	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
444172955Srwatson	    ("mls_copy_effective: labelfrom not effective"));
445105643Srwatson
446172955Srwatson	labelto->mm_effective = labelfrom->mm_effective;
447172955Srwatson	labelto->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
448172955Srwatson}
449101099Srwatson
450101099Srwatsonstatic void
451101099Srwatsonmls_copy(struct mac_mls *source, struct mac_mls *dest)
452172955Srwatson{
453105643Srwatson
454101099Srwatson	if (source->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
455101099Srwatson		mls_copy_effective(source, dest);
456172955Srwatson	if (source->mm_flags & MAC_MLS_FLAG_RANGE)
457172955Srwatson		mls_copy_range(source, dest);
458105643Srwatson}
459172955Srwatson
460172955Srwatson/*
461172955Srwatson * Policy module operations.
462101099Srwatson */
463101099Srwatsonstatic void
464101099Srwatsonmls_init(struct mac_policy_conf *conf)
465172955Srwatson{
466101099Srwatson
467105643Srwatson	zone_mls = uma_zcreate("mac_mls", sizeof(struct mac_mls), NULL,
468101099Srwatson	    NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
469172955Srwatson}
470101099Srwatson
471101099Srwatson/*
472101099Srwatson * Label operations.
473101099Srwatson */
474101099Srwatsonstatic void
475101099Srwatsonmls_init_label(struct label *label)
476101099Srwatson{
477172955Srwatson
478101099Srwatson	SLOT_SET(label, mls_alloc(M_WAITOK));
479101099Srwatson}
480132232Srwatson
481172955Srwatsonstatic int
482101099Srwatsonmls_init_label_waitcheck(struct label *label, int flag)
483132232Srwatson{
484132232Srwatson
485101099Srwatson	SLOT_SET(label, mls_alloc(flag));
486101099Srwatson	if (SLOT(label) == NULL)
487105656Srwatson		return (ENOMEM);
488172955Srwatson
489105656Srwatson	return (0);
490105656Srwatson}
491132232Srwatson
492172955Srwatsonstatic void
493105656Srwatsonmls_destroy_label(struct label *label)
494172955Srwatson{
495105656Srwatson
496105656Srwatson	mls_free(SLOT(label));
497101099Srwatson	SLOT_SET(label, NULL);
498101099Srwatson}
499101099Srwatson
500101099Srwatson/*
501172955Srwatson * mls_element_to_string() accepts an sbuf and MLS element.  It converts the
502101099Srwatson * MLS element to a string and stores the result in the sbuf; if there isn't
503101099Srwatson * space in the sbuf, -1 is returned.
504122879Srwatson */
505122879Srwatsonstatic int
506101099Srwatsonmls_element_to_string(struct sbuf *sb, struct mac_mls_element *element)
507101099Srwatson{
508101099Srwatson	int i, first;
509101099Srwatson
510101099Srwatson	switch (element->mme_type) {
511101099Srwatson	case MAC_MLS_TYPE_HIGH:
512172955Srwatson		return (sbuf_printf(sb, "high"));
513101099Srwatson
514101099Srwatson	case MAC_MLS_TYPE_LOW:
515132781Skan		return (sbuf_printf(sb, "low"));
516101099Srwatson
517101099Srwatson	case MAC_MLS_TYPE_EQUAL:
518101099Srwatson		return (sbuf_printf(sb, "equal"));
519172955Srwatson
520101099Srwatson	case MAC_MLS_TYPE_LEVEL:
521101099Srwatson		if (sbuf_printf(sb, "%d", element->mme_level) == -1)
522132781Skan			return (-1);
523101099Srwatson
524101099Srwatson		first = 1;
525101099Srwatson		for (i = 1; i <= MAC_MLS_MAX_COMPARTMENTS; i++) {
526101099Srwatson			if (MAC_MLS_BIT_TEST(i, element->mme_compartments)) {
527101099Srwatson				if (first) {
528101099Srwatson					if (sbuf_putc(sb, ':') == -1)
529101099Srwatson						return (-1);
530172955Srwatson					if (sbuf_printf(sb, "%d", i) == -1)
531101099Srwatson						return (-1);
532101099Srwatson					first = 0;
533101099Srwatson				} else {
534132781Skan					if (sbuf_printf(sb, "+%d", i) == -1)
535101099Srwatson						return (-1);
536101099Srwatson				}
537105696Srwatson			}
538172955Srwatson		}
539172955Srwatson		return (0);
540172955Srwatson
541105696Srwatson	default:
542115497Srwatson		panic("mls_element_to_string: invalid type (%d)",
543172955Srwatson		    element->mme_type);
544105696Srwatson	}
545115497Srwatson}
546105696Srwatson
547105696Srwatson/*
548105696Srwatson * mls_to_string() converts an MLS label to a string, and places the results
549115497Srwatson * in the passed sbuf.  It returns 0 on success, or EINVAL if there isn't
550105696Srwatson * room in the sbuf.  Note: the sbuf will be modified even in a failure case,
551105696Srwatson * so the caller may need to revert the sbuf by restoring the offset if
552115497Srwatson * that's undesired.
553105696Srwatson */
554105696Srwatsonstatic int
555115497Srwatsonmls_to_string(struct sbuf *sb, struct mac_mls *mm)
556105696Srwatson{
557105696Srwatson
558115497Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
559115497Srwatson		if (mls_element_to_string(sb, &mm->mm_effective) == -1)
560115497Srwatson			return (EINVAL);
561115497Srwatson	}
562115497Srwatson
563115497Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
564115497Srwatson		if (sbuf_putc(sb, '(') == -1)
565115497Srwatson			return (EINVAL);
566115497Srwatson
567115497Srwatson		if (mls_element_to_string(sb, &mm->mm_rangelow) == -1)
568115497Srwatson			return (EINVAL);
569115497Srwatson
570115497Srwatson		if (sbuf_putc(sb, '-') == -1)
571115497Srwatson			return (EINVAL);
572115497Srwatson
573115497Srwatson		if (mls_element_to_string(sb, &mm->mm_rangehigh) == -1)
574115497Srwatson			return (EINVAL);
575105696Srwatson
576115497Srwatson		if (sbuf_putc(sb, ')') == -1)
577105696Srwatson			return (EINVAL);
578105696Srwatson	}
579172955Srwatson
580105696Srwatson	return (0);
581105696Srwatson}
582105696Srwatson
583105696Srwatsonstatic int
584115497Srwatsonmls_externalize_label(struct label *label, char *element_name,
585172955Srwatson    struct sbuf *sb, int *claimed)
586172955Srwatson{
587172955Srwatson	struct mac_mls *mm;
588172955Srwatson
589172955Srwatson	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
590115497Srwatson		return (0);
591101099Srwatson
592172955Srwatson	(*claimed)++;
593101099Srwatson
594105696Srwatson	mm = SLOT(label);
595172955Srwatson
596172955Srwatson	return (mls_to_string(sb, mm));
597105696Srwatson}
598105696Srwatson
599105696Srwatsonstatic int
600172955Srwatsonmls_parse_element(struct mac_mls_element *element, char *string)
601116701Srwatson{
602105696Srwatson	char *compartment, *end, *level;
603105696Srwatson	int value;
604172955Srwatson
605105696Srwatson	if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) {
606105696Srwatson		element->mme_type = MAC_MLS_TYPE_HIGH;
607116701Srwatson		element->mme_level = MAC_MLS_TYPE_UNDEF;
608105696Srwatson	} else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) {
609105696Srwatson		element->mme_type = MAC_MLS_TYPE_LOW;
610172955Srwatson		element->mme_level = MAC_MLS_TYPE_UNDEF;
611105696Srwatson	} else if (strcmp(string, "equal") == 0 ||
612105696Srwatson	    strcmp(string, "eq") == 0) {
613116701Srwatson		element->mme_type = MAC_MLS_TYPE_EQUAL;
614105696Srwatson		element->mme_level = MAC_MLS_TYPE_UNDEF;
615105696Srwatson	} else {
616105696Srwatson		element->mme_type = MAC_MLS_TYPE_LEVEL;
617105696Srwatson
618105696Srwatson		/*
619105696Srwatson		 * Numeric level piece of the element.
620105696Srwatson		 */
621172955Srwatson		level = strsep(&string, ":");
622116701Srwatson		value = strtol(level, &end, 10);
623105696Srwatson		if (end == level || *end != '\0')
624172955Srwatson			return (EINVAL);
625101099Srwatson		if (value < 0 || value > 65535)
626105696Srwatson			return (EINVAL);
627105696Srwatson		element->mme_level = value;
628105696Srwatson
629105696Srwatson		/*
630105696Srwatson		 * Optional compartment piece of the element.  If none are
631172955Srwatson		 * included, we assume that the label has no compartments.
632172955Srwatson		 */
633105696Srwatson		if (string == NULL)
634105696Srwatson			return (0);
635105696Srwatson		if (*string == '\0')
636172955Srwatson			return (0);
637101099Srwatson
638115395Srwatson		while ((compartment = strsep(&string, "+")) != NULL) {
639115395Srwatson			value = strtol(compartment, &end, 10);
640105696Srwatson			if (compartment == end || *end != '\0')
641105696Srwatson				return (EINVAL);
642105696Srwatson			if (value < 1 || value > MAC_MLS_MAX_COMPARTMENTS)
643105696Srwatson				return (EINVAL);
644105696Srwatson			MAC_MLS_BIT_SET(value, element->mme_compartments);
645105696Srwatson		}
646105696Srwatson	}
647105696Srwatson
648105696Srwatson	return (0);
649105696Srwatson}
650105696Srwatson
651105696Srwatson/*
652105696Srwatson * Note: destructively consumes the string, make a local copy before calling
653105696Srwatson * if that's a problem.
654115395Srwatson */
655105696Srwatsonstatic int
656115395Srwatsonmls_parse(struct mac_mls *mm, char *string)
657115395Srwatson{
658115395Srwatson	char *rangehigh, *rangelow, *effective;
659115395Srwatson	int error;
660115395Srwatson
661115395Srwatson	effective = strsep(&string, "(");
662105696Srwatson	if (*effective == '\0')
663115395Srwatson		effective = NULL;
664115395Srwatson
665115395Srwatson	if (string != NULL) {
666105696Srwatson		rangelow = strsep(&string, "-");
667115395Srwatson		if (string == NULL)
668115395Srwatson			return (EINVAL);
669115395Srwatson		rangehigh = strsep(&string, ")");
670115395Srwatson		if (string == NULL)
671115395Srwatson			return (EINVAL);
672115395Srwatson		if (*string != '\0')
673115395Srwatson			return (EINVAL);
674115395Srwatson	} else {
675115395Srwatson		rangelow = NULL;
676105696Srwatson		rangehigh = NULL;
677115395Srwatson	}
678115395Srwatson
679115395Srwatson	KASSERT((rangelow != NULL && rangehigh != NULL) ||
680105696Srwatson	    (rangelow == NULL && rangehigh == NULL),
681115395Srwatson	    ("mls_parse: range mismatch"));
682105696Srwatson
683115395Srwatson	bzero(mm, sizeof(*mm));
684105696Srwatson	if (effective != NULL) {
685105696Srwatson		error = mls_parse_element(&mm->mm_effective, effective);
686105696Srwatson		if (error)
687105696Srwatson			return (error);
688105696Srwatson		mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
689105696Srwatson	}
690105696Srwatson
691105696Srwatson	if (rangelow != NULL) {
692105696Srwatson		error = mls_parse_element(&mm->mm_rangelow,
693105696Srwatson		    rangelow);
694105696Srwatson		if (error)
695172955Srwatson			return (error);
696105696Srwatson		error = mls_parse_element(&mm->mm_rangehigh,
697132232Srwatson		    rangehigh);
698101099Srwatson		if (error)
699101099Srwatson			return (error);
700132232Srwatson		mm->mm_flags |= MAC_MLS_FLAG_RANGE;
701132232Srwatson	}
702132232Srwatson
703115395Srwatson	error = mls_valid(mm);
704115395Srwatson	if (error)
705115395Srwatson		return (error);
706115395Srwatson
707105696Srwatson	return (0);
708115395Srwatson}
709115395Srwatson
710105696Srwatsonstatic int
711115395Srwatsonmls_internalize_label(struct label *label, char *element_name,
712105696Srwatson    char *element_data, int *claimed)
713115395Srwatson{
714115395Srwatson	struct mac_mls *mm, mm_temp;
715115395Srwatson	int error;
716105696Srwatson
717115395Srwatson	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
718105696Srwatson		return (0);
719105696Srwatson
720172955Srwatson	(*claimed)++;
721101099Srwatson
722172955Srwatson	error = mls_parse(&mm_temp, element_data);
723132232Srwatson	if (error)
724172955Srwatson		return (error);
725105696Srwatson
726105696Srwatson	mm = SLOT(label);
727172955Srwatson	*mm = mm_temp;
728105696Srwatson
729105696Srwatson	return (0);
730105696Srwatson}
731172955Srwatson
732105696Srwatsonstatic void
733105696Srwatsonmls_copy_label(struct label *src, struct label *dest)
734172955Srwatson{
735105696Srwatson
736105696Srwatson	*SLOT(dest) = *SLOT(src);
737172955Srwatson}
738105696Srwatson
739105696Srwatson
740172955Srwatson/*
741101099Srwatson * Object-specific entry point implementations are sorted alphabetically by
742101099Srwatson * object type name and then by operation.
743101099Srwatson */
744105696Srwatsonstatic int
745105696Srwatsonmls_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel,
746101099Srwatson     struct ifnet *ifp, struct label *ifplabel)
747105696Srwatson{
748172955Srwatson	struct mac_mls *a, *b;
749105696Srwatson
750105696Srwatson	if (!mls_enabled)
751172955Srwatson		return (0);
752105696Srwatson
753105696Srwatson	a = SLOT(dlabel);
754105696Srwatson	b = SLOT(ifplabel);
755105696Srwatson
756105696Srwatson	if (mls_equal_effective(a, b))
757105696Srwatson		return (0);
758105696Srwatson	return (EACCES);
759172955Srwatson}
760105696Srwatson
761105696Srwatsonstatic void
762105696Srwatsonmls_bpfdesc_create(struct ucred *cred, struct bpf_d *d, struct label *dlabel)
763172955Srwatson{
764172955Srwatson	struct mac_mls *source, *dest;
765105696Srwatson
766101099Srwatson	source = SLOT(cred->cr_label);
767101099Srwatson	dest = SLOT(dlabel);
768101099Srwatson
769105696Srwatson	mls_copy_effective(source, dest);
770172955Srwatson}
771105696Srwatson
772105696Srwatsonstatic void
773105696Srwatsonmls_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel,
774105696Srwatson    struct mbuf *m, struct label *mlabel)
775105696Srwatson{
776101099Srwatson	struct mac_mls *source, *dest;
777172955Srwatson
778172955Srwatson	source = SLOT(dlabel);
779101099Srwatson	dest = SLOT(mlabel);
780101099Srwatson
781172955Srwatson	mls_copy_effective(source, dest);
782168976Srwatson}
783101099Srwatson
784172955Srwatsonstatic int
785101099Srwatsonmls_cred_check_relabel(struct ucred *cred, struct label *newlabel)
786101099Srwatson{
787172955Srwatson	struct mac_mls *subj, *new;
788101099Srwatson	int error;
789101099Srwatson
790101099Srwatson	subj = SLOT(cred->cr_label);
791101099Srwatson	new = SLOT(newlabel);
792101099Srwatson
793105606Srwatson	/*
794105606Srwatson	 * If there is an MLS label update for the credential, it may be an
795105606Srwatson	 * update of effective, range, or both.
796105606Srwatson	 */
797101099Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
798101099Srwatson	if (error)
799172955Srwatson		return (error);
800101099Srwatson
801101099Srwatson	/*
802101099Srwatson	 * If the MLS label is to be changed, authorize as appropriate.
803172955Srwatson	 */
804172955Srwatson	if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
805101099Srwatson		/*
806172955Srwatson		 * If the change request modifies both the MLS label
807101099Srwatson		 * effective and range, check that the new effective will be
808172955Srwatson		 * in the new range.
809172955Srwatson		 */
810172955Srwatson		if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) ==
811101099Srwatson		    MAC_MLS_FLAGS_BOTH && !mls_effective_in_range(new, new))
812101099Srwatson			return (EINVAL);
813101099Srwatson
814172955Srwatson		/*
815107698Srwatson		 * To change the MLS effective label on a credential, the new
816122563Srwatson		 * effective label must be in the current range.
817104535Srwatson		 */
818104535Srwatson		if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE &&
819104535Srwatson		    !mls_effective_in_range(new, subj))
820122524Srwatson			return (EPERM);
821104535Srwatson
822104535Srwatson		/*
823172955Srwatson		 * To change the MLS range label on a credential, the new
824104535Srwatson		 * range must be in the current range.
825104535Srwatson		 */
826104535Srwatson		if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
827172955Srwatson		    !mls_range_in_range(new, subj))
828168976Srwatson			return (EPERM);
829101099Srwatson
830101099Srwatson		/*
831101099Srwatson		 * To have EQUAL in any component of the new credential MLS
832122524Srwatson		 * label, the subject must already have EQUAL in their label.
833168976Srwatson		 */
834172955Srwatson		if (mls_contains_equal(new)) {
835172955Srwatson			error = mls_subject_privileged(subj);
836101099Srwatson			if (error)
837101099Srwatson				return (error);
838101099Srwatson		}
839172955Srwatson	}
840168976Srwatson
841101099Srwatson	return (0);
842101099Srwatson}
843101099Srwatson
844168976Srwatsonstatic int
845168976Srwatsonmls_cred_check_visible(struct ucred *cr1, struct ucred *cr2)
846101099Srwatson{
847172955Srwatson	struct mac_mls *subj, *obj;
848101099Srwatson
849101099Srwatson	if (!mls_enabled)
850101099Srwatson		return (0);
851172955Srwatson
852168976Srwatson	subj = SLOT(cr1->cr_label);
853101099Srwatson	obj = SLOT(cr2->cr_label);
854101099Srwatson
855101099Srwatson	/* XXX: range */
856168976Srwatson	if (!mls_dominate_effective(subj, obj))
857168976Srwatson		return (ESRCH);
858101099Srwatson
859172955Srwatson	return (0);
860101099Srwatson}
861101099Srwatson
862101099Srwatsonstatic void
863172955Srwatsonmls_cred_relabel(struct ucred *cred, struct label *newlabel)
864105988Srwatson{
865168976Srwatson	struct mac_mls *source, *dest;
866101099Srwatson
867101099Srwatson	source = SLOT(newlabel);
868101099Srwatson	dest = SLOT(cred->cr_label);
869105988Srwatson
870168976Srwatson	mls_copy(source, dest);
871101099Srwatson}
872172955Srwatson
873101099Srwatsonstatic void
874101099Srwatsonmls_devfs_create_device(struct ucred *cred, struct mount *mp,
875101099Srwatson    struct cdev *dev, struct devfs_dirent *de, struct label *delabel)
876172955Srwatson{
877168976Srwatson	struct mac_mls *mm;
878101099Srwatson	int mls_type;
879172955Srwatson
880106354Smux	mm = SLOT(delabel);
881101099Srwatson	if (strcmp(dev->si_name, "null") == 0 ||
882168976Srwatson	    strcmp(dev->si_name, "zero") == 0 ||
883168976Srwatson	    strcmp(dev->si_name, "random") == 0 ||
884101099Srwatson	    strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
885172955Srwatson		mls_type = MAC_MLS_TYPE_EQUAL;
886172955Srwatson	else if (strcmp(dev->si_name, "kmem") == 0 ||
887105988Srwatson	    strcmp(dev->si_name, "mem") == 0)
888105988Srwatson		mls_type = MAC_MLS_TYPE_HIGH;
889172955Srwatson	else if (ptys_equal &&
890105988Srwatson	    (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
891168954Srwatson	    strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
892172955Srwatson		mls_type = MAC_MLS_TYPE_EQUAL;
893105988Srwatson	else
894105988Srwatson		mls_type = MAC_MLS_TYPE_LOW;
895101099Srwatson	mls_set_effective(mm, mls_type, 0, NULL);
896101099Srwatson}
897172955Srwatson
898172955Srwatsonstatic void
899105988Srwatsonmls_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
900105988Srwatson    struct devfs_dirent *de, struct label *delabel)
901105988Srwatson{
902172955Srwatson	struct mac_mls *mm;
903172955Srwatson
904105988Srwatson	mm = SLOT(delabel);
905105988Srwatson	mls_set_effective(mm, MAC_MLS_TYPE_LOW, 0, NULL);
906172955Srwatson}
907172955Srwatson
908172955Srwatsonstatic void
909105988Srwatsonmls_devfs_create_symlink(struct ucred *cred, struct mount *mp,
910105988Srwatson    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
911101099Srwatson    struct label *delabel)
912172955Srwatson{
913101099Srwatson	struct mac_mls *source, *dest;
914101099Srwatson
915101099Srwatson	source = SLOT(cred->cr_label);
916101099Srwatson	dest = SLOT(delabel);
917172955Srwatson
918172955Srwatson	mls_copy_effective(source, dest);
919101099Srwatson}
920101099Srwatson
921101099Srwatsonstatic void
922168976Srwatsonmls_devfs_update(struct mount *mp, struct devfs_dirent *de,
923168976Srwatson    struct label *delabel, struct vnode *vp, struct label *vplabel)
924101099Srwatson{
925172955Srwatson	struct mac_mls *source, *dest;
926101099Srwatson
927101099Srwatson	source = SLOT(vplabel);
928105988Srwatson	dest = SLOT(delabel);
929172955Srwatson
930168976Srwatson	mls_copy_effective(source, dest);
931168976Srwatson}
932105988Srwatson
933172955Srwatsonstatic void
934105988Srwatsonmls_devfs_vnode_associate(struct mount *mp, struct label *mplabel,
935105988Srwatson    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
936105988Srwatson    struct label *vplabel)
937172955Srwatson{
938172955Srwatson	struct mac_mls *source, *dest;
939105988Srwatson
940122524Srwatson	source = SLOT(delabel);
941168976Srwatson	dest = SLOT(vplabel);
942172955Srwatson
943105988Srwatson	mls_copy_effective(source, dest);
944105988Srwatson}
945172955Srwatson
946105988Srwatsonstatic int
947172955Srwatsonmls_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp,
948105988Srwatson    struct label *ifplabel, struct label *newlabel)
949105988Srwatson{
950105988Srwatson	struct mac_mls *subj, *new;
951105988Srwatson	int error;
952172955Srwatson
953168976Srwatson	subj = SLOT(cred->cr_label);
954105988Srwatson	new = SLOT(newlabel);
955172955Srwatson
956105988Srwatson	/*
957105988Srwatson	 * If there is an MLS label update for the interface, it may be an
958105988Srwatson	 * update of effective, range, or both.
959172955Srwatson	 */
960172955Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
961105988Srwatson	if (error)
962105988Srwatson		return (error);
963132232Srwatson
964105988Srwatson	/*
965105988Srwatson	 * Relabeling network interfaces requires MLS privilege.
966172955Srwatson	 */
967105988Srwatson	return (mls_subject_privileged(subj));
968105988Srwatson}
969172955Srwatson
970105988Srwatsonstatic int
971105988Srwatsonmls_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel,
972105988Srwatson    struct mbuf *m, struct label *mlabel)
973101099Srwatson{
974101099Srwatson	struct mac_mls *p, *i;
975101099Srwatson
976101099Srwatson	if (!mls_enabled)
977172955Srwatson		return (0);
978122875Srwatson
979122875Srwatson	p = SLOT(mlabel);
980122875Srwatson	i = SLOT(ifplabel);
981122875Srwatson
982122875Srwatson	return (mls_effective_in_range(p, i) ? 0 : EACCES);
983122875Srwatson}
984122875Srwatson
985172955Srwatsonstatic void
986122875Srwatsonmls_ifnet_create(struct ifnet *ifp, struct label *ifplabel)
987122875Srwatson{
988122875Srwatson	struct mac_mls *dest;
989172955Srwatson	int type;
990168976Srwatson
991101099Srwatson	dest = SLOT(ifplabel);
992101099Srwatson
993101099Srwatson	if (ifp->if_type == IFT_LOOP)
994168976Srwatson		type = MAC_MLS_TYPE_EQUAL;
995168976Srwatson	else
996101099Srwatson		type = MAC_MLS_TYPE_LOW;
997172955Srwatson
998101099Srwatson	mls_set_effective(dest, type, 0, NULL);
999101099Srwatson	mls_set_range(dest, type, 0, NULL, type, 0, NULL);
1000101099Srwatson}
1001172955Srwatson
1002168976Srwatsonstatic void
1003101099Srwatsonmls_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel,
1004101099Srwatson    struct mbuf *m, struct label *mlabel)
1005101099Srwatson{
1006122524Srwatson	struct mac_mls *source, *dest;
1007168976Srwatson
1008101099Srwatson	source = SLOT(ifplabel);
1009172955Srwatson	dest = SLOT(mlabel);
1010101099Srwatson
1011101099Srwatson	mls_copy_effective(source, dest);
1012101099Srwatson}
1013172955Srwatson
1014168976Srwatsonstatic void
1015101099Srwatsonmls_ifnet_relabel(struct ucred *cred, struct ifnet *ifp,
1016101099Srwatson    struct label *ifplabel, struct label *newlabel)
1017101099Srwatson{
1018122524Srwatson	struct mac_mls *source, *dest;
1019168976Srwatson
1020101099Srwatson	source = SLOT(newlabel);
1021172955Srwatson	dest = SLOT(ifplabel);
1022101099Srwatson
1023101099Srwatson	mls_copy(source, dest);
1024101099Srwatson}
1025172955Srwatson
1026172850Srwatsonstatic int
1027145855Srwatsonmls_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel,
1028145855Srwatson    struct mbuf *m, struct label *mlabel)
1029145855Srwatson{
1030145855Srwatson	struct mac_mls *p, *i;
1031172850Srwatson
1032145855Srwatson	if (!mls_enabled)
1033172955Srwatson		return (0);
1034145855Srwatson
1035145855Srwatson	p = SLOT(mlabel);
1036145855Srwatson	i = SLOT(inplabel);
1037172955Srwatson
1038172930Srwatson	return (mls_equal_effective(p, i) ? 0 : EACCES);
1039101099Srwatson}
1040101099Srwatson
1041101099Srwatsonstatic void
1042168976Srwatsonmls_inpcb_create(struct socket *so, struct label *solabel, struct inpcb *inp,
1043168976Srwatson    struct label *inplabel)
1044101099Srwatson{
1045172955Srwatson	struct mac_mls *source, *dest;
1046101099Srwatson
1047101099Srwatson	source = SLOT(solabel);
1048101099Srwatson	dest = SLOT(inplabel);
1049172955Srwatson
1050168976Srwatson	mls_copy_effective(source, dest);
1051101099Srwatson}
1052101099Srwatson
1053101099Srwatsonstatic void
1054101099Srwatsonmls_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel,
1055168976Srwatson    struct mbuf *m, struct label *mlabel)
1056101099Srwatson{
1057172955Srwatson	struct mac_mls *source, *dest;
1058101099Srwatson
1059101099Srwatson	source = SLOT(inplabel);
1060101099Srwatson	dest = SLOT(mlabel);
1061172955Srwatson
1062168976Srwatson	mls_copy_effective(source, dest);
1063101099Srwatson}
1064101099Srwatson
1065101099Srwatsonstatic void
1066101099Srwatsonmls_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1067168976Srwatson    struct inpcb *inp, struct label *inplabel)
1068101099Srwatson{
1069172955Srwatson	struct mac_mls *source, *dest;
1070101099Srwatson
1071101099Srwatson	source = SLOT(solabel);
1072101099Srwatson	dest = SLOT(inplabel);
1073172955Srwatson
1074168976Srwatson	mls_copy(source, dest);
1075101099Srwatson}
1076101099Srwatson
1077101099Srwatsonstatic void
1078168976Srwatsonmls_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q,
1079168976Srwatson    struct label *qlabel)
1080101099Srwatson{
1081172955Srwatson	struct mac_mls *source, *dest;
1082101099Srwatson
1083101099Srwatson	source = SLOT(mlabel);
1084101099Srwatson	dest = SLOT(qlabel);
1085140628Srwatson
1086140628Srwatson	mls_copy_effective(source, dest);
1087140628Srwatson}
1088172955Srwatson
1089140628Srwatsonstatic int
1090140628Srwatsonmls_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
1091140628Srwatson    struct label *qlabel)
1092140628Srwatson{
1093140628Srwatson	struct mac_mls *a, *b;
1094140628Srwatson
1095140628Srwatson	a = SLOT(qlabel);
1096140628Srwatson	b = SLOT(mlabel);
1097172955Srwatson
1098140628Srwatson	return (mls_equal_effective(a, b));
1099140628Srwatson}
1100140628Srwatson
1101172955Srwatsonstatic void
1102172955Srwatsonmls_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m,
1103140628Srwatson    struct label *mlabel)
1104140628Srwatson{
1105140628Srwatson	struct mac_mls *source, *dest;
1106140628Srwatson
1107140628Srwatson	source = SLOT(qlabel);
1108140628Srwatson	dest = SLOT(mlabel);
1109172955Srwatson
1110140628Srwatson	/* Just use the head, since we require them all to match. */
1111140628Srwatson	mls_copy_effective(source, dest);
1112140628Srwatson}
1113172955Srwatson
1114140628Srwatsonstatic void
1115140628Srwatsonmls_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
1116140628Srwatson    struct label *qlabel)
1117140628Srwatson{
1118140628Srwatson
1119140628Srwatson	/* NOOP: we only accept matching labels, so no need to update */
1120140628Srwatson}
1121172955Srwatson
1122140628Srwatsonstatic int
1123140628Srwatsonmls_mount_check_stat(struct ucred *cred, struct mount *mp,
1124140628Srwatson    struct label *mntlabel)
1125172955Srwatson{
1126140628Srwatson	struct mac_mls *subj, *obj;
1127140628Srwatson
1128140628Srwatson	if (!mls_enabled)
1129140628Srwatson		return (0);
1130140628Srwatson
1131140628Srwatson	subj = SLOT(cred->cr_label);
1132140628Srwatson	obj = SLOT(mntlabel);
1133172955Srwatson
1134140628Srwatson	if (!mls_dominate_effective(subj, obj))
1135140628Srwatson		return (EACCES);
1136140628Srwatson
1137101099Srwatson	return (0);
1138101099Srwatson}
1139101099Srwatson
1140172955Srwatsonstatic void
1141168976Srwatsonmls_mount_create(struct ucred *cred, struct mount *mp, struct label *mplabel)
1142168976Srwatson{
1143101099Srwatson	struct mac_mls *source, *dest;
1144101099Srwatson
1145101099Srwatson	source = SLOT(cred->cr_label);
1146168976Srwatson	dest = SLOT(mplabel);
1147168976Srwatson
1148101099Srwatson	mls_copy_effective(source, dest);
1149172955Srwatson}
1150101099Srwatson
1151101099Srwatsonstatic void
1152101099Srwatsonmls_netatalk_aarp_send(struct ifnet *ifp, struct label *ifplabel,
1153172955Srwatson    struct mbuf *m, struct label *mlabel)
1154168976Srwatson{
1155101099Srwatson	struct mac_mls *dest;
1156101099Srwatson
1157101099Srwatson	dest = SLOT(mlabel);
1158122524Srwatson
1159168976Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1160101099Srwatson}
1161172955Srwatson
1162101099Srwatsonstatic void
1163101099Srwatsonmls_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel,
1164101099Srwatson    struct mbuf *m, struct label *mlabel)
1165172955Srwatson{
1166101099Srwatson	struct mac_mls *dest;
1167121816Sbrooks
1168101099Srwatson	dest = SLOT(mlabel);
1169101099Srwatson
1170110350Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1171101099Srwatson}
1172168976Srwatson
1173101099Srwatsonstatic void
1174168976Srwatsonmls_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1175110350Srwatson    struct mbuf *msend, struct label *msendlabel)
1176101099Srwatson{
1177101099Srwatson	struct mac_mls *source, *dest;
1178101099Srwatson
1179101099Srwatson	source = SLOT(mrecvlabel);
1180110350Srwatson	dest = SLOT(msendlabel);
1181101099Srwatson
1182101099Srwatson	mls_copy_effective(source, dest);
1183101099Srwatson}
1184110350Srwatson
1185101099Srwatsonstatic void
1186101099Srwatsonmls_netinet_firewall_send(struct mbuf *m, struct label *mlabel)
1187101099Srwatson{
1188101099Srwatson	struct mac_mls *dest;
1189101099Srwatson
1190106089Srwatson	dest = SLOT(mlabel);
1191101099Srwatson
1192101099Srwatson	/* XXX: where is the label for the firewall really comming from? */
1193101099Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1194101099Srwatson}
1195101099Srwatson
1196101099Srwatsonstatic void
1197101099Srwatsonmls_netinet_fragment(struct mbuf *m, struct label *mlabel, struct mbuf *frag,
1198101099Srwatson    struct label *fraglabel)
1199101099Srwatson{
1200101099Srwatson	struct mac_mls *source, *dest;
1201168976Srwatson
1202110350Srwatson	source = SLOT(mlabel);
1203101099Srwatson	dest = SLOT(fraglabel);
1204101099Srwatson
1205106089Srwatson	mls_copy_effective(source, dest);
1206106089Srwatson}
1207106089Srwatson
1208106089Srwatsonstatic void
1209106089Srwatsonmls_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1210101099Srwatson    struct mbuf *msend, struct label *msendlabel)
1211101099Srwatson{
1212101099Srwatson	struct mac_mls *source, *dest;
1213101099Srwatson
1214101099Srwatson	source = SLOT(mrecvlabel);
1215101099Srwatson	dest = SLOT(msendlabel);
1216101099Srwatson
1217172955Srwatson	mls_copy_effective(source, dest);
1218172955Srwatson}
1219101099Srwatson
1220101099Srwatsonstatic void
1221101099Srwatsonmls_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel,
1222172955Srwatson    struct mbuf *m, struct label *mlabel)
1223168976Srwatson{
1224101099Srwatson	struct mac_mls *dest;
1225101099Srwatson
1226101099Srwatson	dest = SLOT(mlabel);
1227168976Srwatson
1228101099Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1229101099Srwatson}
1230172955Srwatson
1231101099Srwatsonstatic void
1232101099Srwatsonmls_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel,
1233101099Srwatson    struct mbuf *m, struct label *mlabel)
1234172955Srwatson{
1235172955Srwatson	struct mac_mls *dest;
1236101099Srwatson
1237101099Srwatson	dest = SLOT(mlabel);
1238101099Srwatson
1239101099Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1240168976Srwatson}
1241101099Srwatson
1242101099Srwatsonstatic int
1243172955Srwatsonmls_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
1244101099Srwatson    struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1245101099Srwatson{
1246101099Srwatson
1247172955Srwatson	if (!mls_enabled)
1248168976Srwatson		return (0);
1249101099Srwatson
1250101099Srwatson	/* XXX: This will be implemented soon... */
1251101099Srwatson
1252168976Srwatson	return (0);
1253168976Srwatson}
1254101099Srwatson
1255172955Srwatsonstatic int
1256101099Srwatsonmls_pipe_check_poll(struct ucred *cred, struct pipepair *pp,
1257101099Srwatson    struct label *pplabel)
1258101099Srwatson{
1259172955Srwatson	struct mac_mls *subj, *obj;
1260123607Srwatson
1261123607Srwatson	if (!mls_enabled)
1262123607Srwatson		return (0);
1263123607Srwatson
1264123607Srwatson	subj = SLOT(cred->cr_label);
1265123607Srwatson	obj = SLOT(pplabel);
1266123607Srwatson
1267172955Srwatson	if (!mls_dominate_effective(subj, obj))
1268123607Srwatson		return (EACCES);
1269123607Srwatson
1270123607Srwatson	return (0);
1271172955Srwatson}
1272168976Srwatson
1273101099Srwatsonstatic int
1274101099Srwatsonmls_pipe_check_read(struct ucred *cred, struct pipepair *pp,
1275101099Srwatson    struct label *pplabel)
1276168976Srwatson{
1277101099Srwatson	struct mac_mls *subj, *obj;
1278172955Srwatson
1279101099Srwatson	if (!mls_enabled)
1280101099Srwatson		return (0);
1281101099Srwatson
1282172955Srwatson	subj = SLOT(cred->cr_label);
1283168976Srwatson	obj = SLOT(pplabel);
1284101099Srwatson
1285101099Srwatson	if (!mls_dominate_effective(subj, obj))
1286101099Srwatson		return (EACCES);
1287168976Srwatson
1288168976Srwatson	return (0);
1289101099Srwatson}
1290172955Srwatson
1291101099Srwatsonstatic int
1292101099Srwatsonmls_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
1293101099Srwatson    struct label *pplabel, struct label *newlabel)
1294172955Srwatson{
1295168976Srwatson	struct mac_mls *subj, *obj, *new;
1296101099Srwatson	int error;
1297101099Srwatson
1298101099Srwatson	new = SLOT(newlabel);
1299168976Srwatson	subj = SLOT(cred->cr_label);
1300168976Srwatson	obj = SLOT(pplabel);
1301101099Srwatson
1302172955Srwatson	/*
1303101099Srwatson	 * If there is an MLS label update for a pipe, it must be a effective
1304101099Srwatson	 * update.
1305101099Srwatson	 */
1306172955Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1307168976Srwatson	if (error)
1308168976Srwatson		return (error);
1309101099Srwatson
1310101099Srwatson	/*
1311101099Srwatson	 * To perform a relabel of a pipe (MLS label or not), MLS must
1312168976Srwatson	 * authorize the relabel.
1313168976Srwatson	 */
1314101099Srwatson	if (!mls_effective_in_range(obj, subj))
1315172955Srwatson		return (EPERM);
1316101099Srwatson
1317101099Srwatson	/*
1318101099Srwatson	 * If the MLS label is to be changed, authorize as appropriate.
1319172955Srwatson	 */
1320168976Srwatson	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1321101099Srwatson		/*
1322101099Srwatson		 * To change the MLS label on a pipe, the new pipe label must
1323101099Srwatson		 * be in the subject range.
1324168976Srwatson		 */
1325168976Srwatson		if (!mls_effective_in_range(new, subj))
1326101099Srwatson			return (EPERM);
1327172955Srwatson
1328101099Srwatson		/*
1329101099Srwatson		 * To change the MLS label on a pipe to be EQUAL, the subject
1330101099Srwatson		 * must have appropriate privilege.
1331172955Srwatson		 */
1332172930Srwatson		if (mls_contains_equal(new)) {
1333101099Srwatson			error = mls_subject_privileged(subj);
1334101099Srwatson			if (error)
1335101099Srwatson				return (error);
1336101099Srwatson		}
1337168976Srwatson	}
1338101099Srwatson
1339172955Srwatson	return (0);
1340101099Srwatson}
1341101099Srwatson
1342101099Srwatsonstatic int
1343172955Srwatsonmls_pipe_check_stat(struct ucred *cred, struct pipepair *pp,
1344168976Srwatson    struct label *pplabel)
1345101099Srwatson{
1346101099Srwatson	struct mac_mls *subj, *obj;
1347101099Srwatson
1348101099Srwatson	if (!mls_enabled)
1349168976Srwatson		return (0);
1350101099Srwatson
1351172955Srwatson	subj = SLOT(cred->cr_label);
1352101099Srwatson	obj = SLOT(pplabel);
1353101099Srwatson
1354101099Srwatson	if (!mls_dominate_effective(subj, obj))
1355172955Srwatson		return (EACCES);
1356168976Srwatson
1357101099Srwatson	return (0);
1358101099Srwatson}
1359101099Srwatson
1360101099Srwatsonstatic int
1361101099Srwatsonmls_pipe_check_write(struct ucred *cred, struct pipepair *pp,
1362122875Srwatson    struct label *pplabel)
1363172955Srwatson{
1364122875Srwatson	struct mac_mls *subj, *obj;
1365122875Srwatson
1366122875Srwatson	if (!mls_enabled)
1367122875Srwatson		return (0);
1368122875Srwatson
1369122875Srwatson	subj = SLOT(cred->cr_label);
1370122875Srwatson	obj = SLOT(pplabel);
1371172955Srwatson
1372122875Srwatson	if (!mls_dominate_effective(obj, subj))
1373122875Srwatson		return (EACCES);
1374162238Scsjp
1375172955Srwatson	return (0);
1376162238Scsjp}
1377162238Scsjp
1378162238Scsjpstatic void
1379162238Scsjpmls_pipe_create(struct ucred *cred, struct pipepair *pp,
1380162238Scsjp    struct label *pplabel)
1381162238Scsjp{
1382172955Srwatson	struct mac_mls *source, *dest;
1383162238Scsjp
1384162238Scsjp	source = SLOT(cred->cr_label);
1385101099Srwatson	dest = SLOT(pplabel);
1386101099Srwatson
1387101099Srwatson	mls_copy_effective(source, dest);
1388101099Srwatson}
1389172955Srwatson
1390101099Srwatsonstatic void
1391101099Srwatsonmls_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1392101099Srwatson    struct label *pplabel, struct label *newlabel)
1393122524Srwatson{
1394101099Srwatson	struct mac_mls *source, *dest;
1395172955Srwatson
1396172955Srwatson	source = SLOT(newlabel);
1397172955Srwatson	dest = SLOT(pplabel);
1398101099Srwatson
1399101099Srwatson	mls_copy(source, dest);
1400101099Srwatson}
1401172955Srwatson
1402101099Srwatsonstatic int
1403101099Srwatsonmls_posixsem_check_rdonly(struct ucred *cred, struct ksem *ks,
1404101099Srwatson    struct label *kslabel)
1405122524Srwatson{
1406101099Srwatson	struct mac_mls *subj, *obj;
1407172955Srwatson
1408172955Srwatson	if (!mls_enabled)
1409172955Srwatson		return (0);
1410101099Srwatson
1411101099Srwatson	subj = SLOT(cred->cr_label);
1412101099Srwatson	obj = SLOT(kslabel);
1413172955Srwatson
1414101099Srwatson	if (!mls_dominate_effective(subj, obj))
1415101099Srwatson		return (EACCES);
1416101099Srwatson
1417101099Srwatson	return (0);
1418122524Srwatson}
1419101099Srwatson
1420172955Srwatsonstatic int
1421101099Srwatsonmls_posixsem_check_write(struct ucred *cred, struct ksem *ks,
1422101099Srwatson    struct label *kslabel)
1423101099Srwatson{
1424140628Srwatson	struct mac_mls *subj, *obj;
1425140628Srwatson
1426140628Srwatson	if (!mls_enabled)
1427172955Srwatson		return (0);
1428140628Srwatson
1429140628Srwatson	subj = SLOT(cred->cr_label);
1430140628Srwatson	obj = SLOT(kslabel);
1431140628Srwatson
1432140628Srwatson	if (!mls_dominate_effective(obj, subj))
1433140628Srwatson		return (EACCES);
1434172955Srwatson
1435140628Srwatson	return (0);
1436140628Srwatson}
1437140628Srwatson
1438140628Srwatsonstatic void
1439140628Srwatsonmls_posixsem_create(struct ucred *cred, struct ksem *ks,
1440140628Srwatson    struct label *kslabel)
1441172955Srwatson{
1442140628Srwatson	struct mac_mls *source, *dest;
1443140628Srwatson
1444140628Srwatson	source = SLOT(cred->cr_label);
1445140628Srwatson	dest = SLOT(kslabel);
1446140628Srwatson
1447140628Srwatson	mls_copy_effective(source, dest);
1448172955Srwatson}
1449140628Srwatson
1450140628Srwatsonstatic void
1451140628Srwatsonmls_proc_associate_nfsd(struct ucred *cred)
1452140628Srwatson{
1453140628Srwatson	struct mac_mls *label;
1454101099Srwatson
1455101099Srwatson	label = SLOT(cred->cr_label);
1456101099Srwatson	mls_set_effective(label, MAC_MLS_TYPE_LOW, 0, NULL);
1457172955Srwatson	mls_set_range(label, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
1458168976Srwatson	    NULL);
1459101099Srwatson}
1460101099Srwatson
1461101099Srwatsonstatic int
1462172955Srwatsonmls_proc_check_debug(struct ucred *cred, struct proc *p)
1463101099Srwatson{
1464101099Srwatson	struct mac_mls *subj, *obj;
1465168976Srwatson
1466168976Srwatson	if (!mls_enabled)
1467101099Srwatson		return (0);
1468172955Srwatson
1469101099Srwatson	subj = SLOT(cred->cr_label);
1470101099Srwatson	obj = SLOT(p->p_ucred->cr_label);
1471101099Srwatson
1472101099Srwatson	/* XXX: range checks */
1473101099Srwatson	if (!mls_dominate_effective(subj, obj))
1474172955Srwatson		return (ESRCH);
1475101099Srwatson	if (!mls_dominate_effective(obj, subj))
1476101099Srwatson		return (EACCES);
1477105634Srwatson
1478101099Srwatson	return (0);
1479122524Srwatson}
1480101099Srwatson
1481101099Srwatsonstatic int
1482101099Srwatsonmls_proc_check_sched(struct ucred *cred, struct proc *p)
1483105634Srwatson{
1484132232Srwatson	struct mac_mls *subj, *obj;
1485101099Srwatson
1486105634Srwatson	if (!mls_enabled)
1487105634Srwatson		return (0);
1488105634Srwatson
1489101099Srwatson	subj = SLOT(cred->cr_label);
1490101099Srwatson	obj = SLOT(p->p_ucred->cr_label);
1491105634Srwatson
1492101099Srwatson	/* XXX: range checks */
1493105634Srwatson	if (!mls_dominate_effective(subj, obj))
1494105634Srwatson		return (ESRCH);
1495110351Srwatson	if (!mls_dominate_effective(obj, subj))
1496132232Srwatson		return (EACCES);
1497110351Srwatson
1498110351Srwatson	return (0);
1499110351Srwatson}
1500110351Srwatson
1501172955Srwatsonstatic int
1502110351Srwatsonmls_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
1503110351Srwatson{
1504110351Srwatson	struct mac_mls *subj, *obj;
1505132232Srwatson
1506132232Srwatson	if (!mls_enabled)
1507105634Srwatson		return (0);
1508132232Srwatson
1509172955Srwatson	subj = SLOT(cred->cr_label);
1510105634Srwatson	obj = SLOT(p->p_ucred->cr_label);
1511101099Srwatson
1512105634Srwatson	/* XXX: range checks */
1513172955Srwatson	if (!mls_dominate_effective(subj, obj))
1514172955Srwatson		return (ESRCH);
1515105634Srwatson	if (!mls_dominate_effective(obj, subj))
1516105634Srwatson		return (EACCES);
1517172955Srwatson
1518105634Srwatson	return (0);
1519101099Srwatson}
1520105634Srwatson
1521172955Srwatsonstatic void
1522172955Srwatsonmls_proc_create_init(struct ucred *cred)
1523105634Srwatson{
1524172955Srwatson	struct mac_mls *dest;
1525172955Srwatson
1526105634Srwatson	dest = SLOT(cred->cr_label);
1527105634Srwatson
1528105634Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_LOW, 0, NULL);
1529105634Srwatson	mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
1530105634Srwatson	    NULL);
1531101099Srwatson}
1532101099Srwatson
1533101099Srwatsonstatic void
1534101099Srwatsonmls_proc_create_swapper(struct ucred *cred)
1535172955Srwatson{
1536101099Srwatson	struct mac_mls *dest;
1537101099Srwatson
1538101099Srwatson	dest = SLOT(cred->cr_label);
1539172955Srwatson
1540101099Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1541101099Srwatson	mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
1542122524Srwatson	    NULL);
1543122524Srwatson}
1544101099Srwatson
1545101099Srwatsonstatic int
1546172955Srwatsonmls_socket_check_deliver(struct socket *so, struct label *solabel,
1547101099Srwatson    struct mbuf *m, struct label *mlabel)
1548101099Srwatson{
1549101099Srwatson	struct mac_mls *p, *s;
1550101099Srwatson
1551101099Srwatson	if (!mls_enabled)
1552101099Srwatson		return (0);
1553172955Srwatson
1554168976Srwatson	p = SLOT(mlabel);
1555101099Srwatson	s = SLOT(solabel);
1556101099Srwatson
1557105634Srwatson	return (mls_equal_effective(p, s) ? 0 : EACCES);
1558101099Srwatson}
1559122524Srwatson
1560101099Srwatsonstatic int
1561101099Srwatsonmls_socket_check_relabel(struct ucred *cred, struct socket *so,
1562105634Srwatson    struct label *solabel, struct label *newlabel)
1563172955Srwatson{
1564172955Srwatson	struct mac_mls *subj, *obj, *new;
1565105634Srwatson	int error;
1566105634Srwatson
1567105634Srwatson	new = SLOT(newlabel);
1568105634Srwatson	subj = SLOT(cred->cr_label);
1569101099Srwatson	obj = SLOT(solabel);
1570105634Srwatson
1571106160Srwatson	/*
1572106160Srwatson	 * If there is an MLS label update for the socket, it may be an
1573172955Srwatson	 * update of effective.
1574106160Srwatson	 */
1575106160Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1576106160Srwatson	if (error)
1577105634Srwatson		return (error);
1578101099Srwatson
1579101099Srwatson	/*
1580103759Srwatson	 * To relabel a socket, the old socket effective must be in the
1581172955Srwatson	 * subject range.
1582168976Srwatson	 */
1583101099Srwatson	if (!mls_effective_in_range(obj, subj))
1584101099Srwatson		return (EPERM);
1585103761Srwatson
1586172955Srwatson	/*
1587101099Srwatson	 * If the MLS label is to be changed, authorize as appropriate.
1588101099Srwatson	 */
1589168976Srwatson	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1590168976Srwatson		/*
1591103759Srwatson		 * To relabel a socket, the new socket effective must be in
1592172955Srwatson		 * the subject range.
1593101099Srwatson		 */
1594101099Srwatson		if (!mls_effective_in_range(new, subj))
1595101099Srwatson			return (EPERM);
1596172955Srwatson
1597122875Srwatson		/*
1598122875Srwatson		 * To change the MLS label on the socket to contain EQUAL,
1599122875Srwatson		 * the subject must have appropriate privilege.
1600122875Srwatson		 */
1601172955Srwatson		if (mls_contains_equal(new)) {
1602122875Srwatson			error = mls_subject_privileged(subj);
1603122875Srwatson			if (error)
1604122875Srwatson				return (error);
1605122875Srwatson		}
1606122875Srwatson	}
1607172955Srwatson
1608122875Srwatson	return (0);
1609122875Srwatson}
1610122875Srwatson
1611172955Srwatsonstatic int
1612140628Srwatsonmls_socket_check_visible(struct ucred *cred, struct socket *so,
1613140628Srwatson    struct label *solabel)
1614140628Srwatson{
1615140628Srwatson	struct mac_mls *subj, *obj;
1616172955Srwatson
1617140628Srwatson	if (!mls_enabled)
1618140628Srwatson		return (0);
1619140628Srwatson
1620140628Srwatson	subj = SLOT(cred->cr_label);
1621140628Srwatson	obj = SLOT(solabel);
1622172955Srwatson
1623140628Srwatson	if (!mls_dominate_effective(subj, obj))
1624140628Srwatson		return (ENOENT);
1625140628Srwatson
1626140628Srwatson	return (0);
1627140628Srwatson}
1628140628Srwatson
1629172955Srwatsonstatic void
1630140628Srwatsonmls_socket_create(struct ucred *cred, struct socket *so,
1631140628Srwatson    struct label *solabel)
1632140628Srwatson{
1633140628Srwatson	struct mac_mls *source, *dest;
1634172955Srwatson
1635140628Srwatson	source = SLOT(cred->cr_label);
1636140628Srwatson	dest = SLOT(solabel);
1637140628Srwatson
1638140628Srwatson	mls_copy_effective(source, dest);
1639140628Srwatson}
1640172955Srwatson
1641140628Srwatsonstatic void
1642140628Srwatsonmls_socket_create_mbuf(struct socket *so, struct label *solabel,
1643140628Srwatson    struct mbuf *m, struct label *mlabel)
1644140628Srwatson{
1645140628Srwatson	struct mac_mls *source, *dest;
1646140628Srwatson
1647172955Srwatson	source = SLOT(solabel);
1648172955Srwatson	dest = SLOT(mlabel);
1649140628Srwatson
1650140628Srwatson	mls_copy_effective(source, dest);
1651140628Srwatson}
1652172955Srwatson
1653140628Srwatsonstatic void
1654140628Srwatsonmls_socket_newconn(struct socket *oldso, struct label *oldsolabel,
1655140628Srwatson    struct socket *newso, struct label *newsolabel)
1656140628Srwatson{
1657140628Srwatson	struct mac_mls *source, *dest;
1658172955Srwatson
1659140628Srwatson	source = SLOT(oldsolabel);
1660140628Srwatson	dest = SLOT(newsolabel);
1661140628Srwatson
1662140628Srwatson	mls_copy_effective(source, dest);
1663140628Srwatson}
1664140628Srwatson
1665172955Srwatsonstatic void
1666172955Srwatsonmls_socket_relabel(struct ucred *cred, struct socket *so,
1667140628Srwatson    struct label *solabel, struct label *newlabel)
1668140628Srwatson{
1669140628Srwatson	struct mac_mls *source, *dest;
1670172955Srwatson
1671140628Srwatson	source = SLOT(newlabel);
1672140628Srwatson	dest = SLOT(solabel);
1673140628Srwatson
1674140628Srwatson	mls_copy(source, dest);
1675140628Srwatson}
1676172955Srwatson
1677140628Srwatsonstatic void
1678140628Srwatsonmls_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel,
1679140628Srwatson    struct socket *so, struct label *sopeerlabel)
1680140628Srwatson{
1681140628Srwatson	struct mac_mls *source, *dest;
1682140628Srwatson
1683172955Srwatson	source = SLOT(mlabel);
1684172955Srwatson	dest = SLOT(sopeerlabel);
1685140628Srwatson
1686140628Srwatson	mls_copy_effective(source, dest);
1687140628Srwatson}
1688172955Srwatson
1689140628Srwatsonstatic void
1690140628Srwatsonmls_socketpeer_set_from_socket(struct socket *oldso,
1691140628Srwatson    struct label *oldsolabel, struct socket *newso,
1692140628Srwatson    struct label *newsopeerlabel)
1693140628Srwatson{
1694172955Srwatson	struct mac_mls *source, *dest;
1695140628Srwatson
1696140628Srwatson	source = SLOT(oldsolabel);
1697140628Srwatson	dest = SLOT(newsopeerlabel);
1698140628Srwatson
1699140628Srwatson	mls_copy_effective(source, dest);
1700140628Srwatson}
1701172955Srwatson
1702172955Srwatsonstatic void
1703140628Srwatsonmls_syncache_create(struct label *label, struct inpcb *inp)
1704140628Srwatson{
1705140628Srwatson	struct mac_mls *source, *dest;
1706172955Srwatson
1707140628Srwatson	source = SLOT(inp->inp_label);
1708140628Srwatson	dest = SLOT(label);
1709140628Srwatson
1710140628Srwatson	mls_copy_effective(source, dest);
1711140628Srwatson}
1712140628Srwatson
1713140628Srwatsonstatic void
1714140628Srwatsonmls_syncache_create_mbuf(struct label *sc_label, struct mbuf *m,
1715172955Srwatson    struct label *mlabel)
1716140628Srwatson{
1717140628Srwatson	struct mac_mls *source, *dest;
1718140628Srwatson
1719140628Srwatson	source = SLOT(sc_label);
1720172955Srwatson	dest = SLOT(mlabel);
1721140628Srwatson
1722140628Srwatson	mls_copy_effective(source, dest);
1723140628Srwatson}
1724140628Srwatson
1725140628Srwatsonstatic int
1726140628Srwatsonmls_system_check_acct(struct ucred *cred, struct vnode *vp,
1727140628Srwatson    struct label *vplabel)
1728140628Srwatson{
1729140628Srwatson	struct mac_mls *subj, *obj;
1730140628Srwatson
1731140628Srwatson	if (!mls_enabled)
1732172955Srwatson		return (0);
1733172955Srwatson
1734140628Srwatson	subj = SLOT(cred->cr_label);
1735140628Srwatson	obj = SLOT(vplabel);
1736140628Srwatson
1737172955Srwatson	if (!mls_dominate_effective(obj, subj) ||
1738140628Srwatson	    !mls_dominate_effective(subj, obj))
1739140628Srwatson		return (EACCES);
1740140628Srwatson
1741140628Srwatson	return (0);
1742140628Srwatson}
1743140628Srwatson
1744140628Srwatsonstatic int
1745140628Srwatsonmls_system_check_auditctl(struct ucred *cred, struct vnode *vp,
1746140628Srwatson    struct label *vplabel)
1747140628Srwatson{
1748172955Srwatson	struct mac_mls *subj, *obj;
1749140628Srwatson
1750140628Srwatson	if (!mls_enabled)
1751140628Srwatson		return (0);
1752140628Srwatson
1753140628Srwatson	subj = SLOT(cred->cr_label);
1754140628Srwatson	obj = SLOT(vplabel);
1755140628Srwatson
1756140628Srwatson	if (!mls_dominate_effective(obj, subj) ||
1757140628Srwatson	    !mls_dominate_effective(subj, obj))
1758172955Srwatson		return (EACCES);
1759140628Srwatson
1760140628Srwatson	return (0);
1761140628Srwatson}
1762140628Srwatson
1763140628Srwatsonstatic int
1764140628Srwatsonmls_system_check_swapon(struct ucred *cred, struct vnode *vp,
1765140628Srwatson    struct label *vplabel)
1766140628Srwatson{
1767140628Srwatson	struct mac_mls *subj, *obj;
1768140628Srwatson
1769140628Srwatson	if (!mls_enabled)
1770172955Srwatson		return (0);
1771172955Srwatson
1772140628Srwatson	subj = SLOT(cred->cr_label);
1773140628Srwatson	obj = SLOT(vplabel);
1774140628Srwatson
1775172955Srwatson	if (!mls_dominate_effective(obj, subj) ||
1776140628Srwatson	    !mls_dominate_effective(subj, obj))
1777140628Srwatson		return (EACCES);
1778140628Srwatson
1779140628Srwatson	return (0);
1780140628Srwatson}
1781172955Srwatson
1782140628Srwatsonstatic void
1783140628Srwatsonmls_sysvmsg_cleanup(struct label *msglabel)
1784140628Srwatson{
1785140628Srwatson
1786140628Srwatson	bzero(SLOT(msglabel), sizeof(struct mac_mls));
1787140628Srwatson}
1788172955Srwatson
1789172955Srwatsonstatic void
1790140628Srwatsonmls_sysvmsg_create(struct ucred *cred, struct msqid_kernel *msqkptr,
1791140628Srwatson    struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
1792140628Srwatson{
1793172955Srwatson	struct mac_mls *source, *dest;
1794140628Srwatson
1795140628Srwatson	/* Ignore the msgq label. */
1796140628Srwatson	source = SLOT(cred->cr_label);
1797140628Srwatson	dest = SLOT(msglabel);
1798140628Srwatson
1799140628Srwatson	mls_copy_effective(source, dest);
1800172955Srwatson}
1801140628Srwatson
1802140628Srwatsonstatic int
1803140628Srwatsonmls_sysvmsq_check_msgrcv(struct ucred *cred, struct msg *msgptr,
1804172955Srwatson    struct label *msglabel)
1805140628Srwatson{
1806140628Srwatson	struct mac_mls *subj, *obj;
1807140628Srwatson
1808140628Srwatson	if (!mls_enabled)
1809140628Srwatson		return (0);
1810140628Srwatson
1811172955Srwatson	subj = SLOT(cred->cr_label);
1812172955Srwatson	obj = SLOT(msglabel);
1813140628Srwatson
1814140628Srwatson	if (!mls_dominate_effective(subj, obj))
1815140628Srwatson		return (EACCES);
1816172955Srwatson
1817140628Srwatson	return (0);
1818140628Srwatson}
1819140628Srwatson
1820140628Srwatsonstatic int
1821140628Srwatsonmls_sysvmsq_check_msgrmid(struct ucred *cred, struct msg *msgptr,
1822172955Srwatson    struct label *msglabel)
1823140628Srwatson{
1824140628Srwatson	struct mac_mls *subj, *obj;
1825172955Srwatson
1826140628Srwatson	if (!mls_enabled)
1827140628Srwatson		return (0);
1828140628Srwatson
1829140628Srwatson	subj = SLOT(cred->cr_label);
1830140628Srwatson	obj = SLOT(msglabel);
1831140628Srwatson
1832140628Srwatson	if (!mls_dominate_effective(obj, subj))
1833172955Srwatson		return (EACCES);
1834172955Srwatson
1835140628Srwatson	return (0);
1836140628Srwatson}
1837140628Srwatson
1838172955Srwatsonstatic int
1839140628Srwatsonmls_sysvmsq_check_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
1840140628Srwatson    struct label *msqklabel)
1841140628Srwatson{
1842140628Srwatson	struct mac_mls *subj, *obj;
1843140628Srwatson
1844140628Srwatson	if (!mls_enabled)
1845140628Srwatson		return (0);
1846140628Srwatson
1847172955Srwatson	subj = SLOT(cred->cr_label);
1848140628Srwatson	obj = SLOT(msqklabel);
1849140628Srwatson
1850140628Srwatson	if (!mls_dominate_effective(subj, obj))
1851140628Srwatson		return (EACCES);
1852140628Srwatson
1853172955Srwatson	return (0);
1854140628Srwatson}
1855140628Srwatson
1856140628Srwatsonstatic int
1857140628Srwatsonmls_sysvmsq_check_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
1858140628Srwatson    struct label *msqklabel)
1859140628Srwatson{
1860140628Srwatson	struct mac_mls *subj, *obj;
1861140628Srwatson
1862140628Srwatson	if (!mls_enabled)
1863140628Srwatson		return (0);
1864140628Srwatson
1865172955Srwatson	subj = SLOT(cred->cr_label);
1866172955Srwatson	obj = SLOT(msqklabel);
1867140628Srwatson
1868140628Srwatson	if (!mls_dominate_effective(obj, subj))
1869140628Srwatson		return (EACCES);
1870172955Srwatson
1871140628Srwatson	return (0);
1872140628Srwatson}
1873140628Srwatson
1874140628Srwatsonstatic int
1875140628Srwatsonmls_sysvmsq_check_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
1876172955Srwatson    struct label *msqklabel)
1877140628Srwatson{
1878140628Srwatson	struct mac_mls *subj, *obj;
1879140628Srwatson
1880140628Srwatson	if (!mls_enabled)
1881140628Srwatson		return (0);
1882140628Srwatson
1883172955Srwatson	subj = SLOT(cred->cr_label);
1884168976Srwatson	obj = SLOT(msqklabel);
1885110354Srwatson
1886110354Srwatson	if (!mls_dominate_effective(subj, obj))
1887110354Srwatson		return (EACCES);
1888110354Srwatson
1889172955Srwatson	return (0);
1890110354Srwatson}
1891110354Srwatson
1892122524Srwatsonstatic int
1893110354Srwatsonmls_sysvmsq_check_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
1894172955Srwatson    struct label *msqklabel, int cmd)
1895110354Srwatson{
1896110354Srwatson	struct mac_mls *subj, *obj;
1897110354Srwatson
1898168976Srwatson	if (!mls_enabled)
1899172955Srwatson		return (0);
1900110354Srwatson
1901110354Srwatson	subj = SLOT(cred->cr_label);
1902110354Srwatson	obj = SLOT(msqklabel);
1903110354Srwatson
1904110354Srwatson	switch(cmd) {
1905110354Srwatson	case IPC_RMID:
1906172955Srwatson	case IPC_SET:
1907168976Srwatson		if (!mls_dominate_effective(obj, subj))
1908101099Srwatson			return (EACCES);
1909101099Srwatson		break;
1910101099Srwatson
1911172955Srwatson	case IPC_STAT:
1912101099Srwatson		if (!mls_dominate_effective(subj, obj))
1913101099Srwatson			return (EACCES);
1914122524Srwatson		break;
1915168976Srwatson
1916101099Srwatson	default:
1917172955Srwatson		return (EACCES);
1918101099Srwatson	}
1919101099Srwatson
1920101099Srwatson	return (0);
1921101099Srwatson}
1922101099Srwatson
1923101099Srwatsonstatic void
1924172955Srwatsonmls_sysvmsq_cleanup(struct label *msqlabel)
1925168976Srwatson{
1926101099Srwatson
1927103759Srwatson	bzero(SLOT(msqlabel), sizeof(struct mac_mls));
1928172955Srwatson}
1929101099Srwatson
1930101099Srwatsonstatic void
1931101099Srwatsonmls_sysvmsq_create(struct ucred *cred, struct msqid_kernel *msqkptr,
1932101099Srwatson    struct label *msqlabel)
1933101099Srwatson{
1934101099Srwatson	struct mac_mls *source, *dest;
1935101099Srwatson
1936101099Srwatson	source = SLOT(cred->cr_label);
1937172955Srwatson	dest = SLOT(msqlabel);
1938168976Srwatson
1939101099Srwatson	mls_copy_effective(source, dest);
1940101099Srwatson}
1941101099Srwatson
1942172955Srwatsonstatic int
1943101099Srwatsonmls_sysvsem_check_semctl(struct ucred *cred, struct semid_kernel *semakptr,
1944101099Srwatson    struct label *semaklabel, int cmd)
1945122524Srwatson{
1946168976Srwatson	struct mac_mls *subj, *obj;
1947101099Srwatson
1948172955Srwatson	if (!mls_enabled)
1949102115Srwatson		return (0);
1950101099Srwatson
1951101099Srwatson	subj = SLOT(cred->cr_label);
1952101099Srwatson	obj = SLOT(semaklabel);
1953101099Srwatson
1954101099Srwatson	switch(cmd) {
1955172955Srwatson	case IPC_RMID:
1956168976Srwatson	case IPC_SET:
1957102115Srwatson	case SETVAL:
1958102115Srwatson	case SETALL:
1959102115Srwatson		if (!mls_dominate_effective(obj, subj))
1960172955Srwatson			return (EACCES);
1961102115Srwatson		break;
1962102115Srwatson
1963122524Srwatson	case IPC_STAT:
1964168976Srwatson	case GETVAL:
1965102115Srwatson	case GETPID:
1966172955Srwatson	case GETNCNT:
1967102115Srwatson	case GETZCNT:
1968102115Srwatson	case GETALL:
1969102115Srwatson		if (!mls_dominate_effective(subj, obj))
1970102115Srwatson			return (EACCES);
1971102115Srwatson		break;
1972102115Srwatson
1973172955Srwatson	default:
1974168976Srwatson		return (EACCES);
1975101099Srwatson	}
1976101099Srwatson
1977105634Srwatson	return (0);
1978101099Srwatson}
1979101099Srwatson
1980122524Srwatsonstatic int
1981168976Srwatsonmls_sysvsem_check_semget(struct ucred *cred, struct semid_kernel *semakptr,
1982101099Srwatson    struct label *semaklabel)
1983101099Srwatson{
1984172955Srwatson	struct mac_mls *subj, *obj;
1985172955Srwatson
1986101099Srwatson	if (!mls_enabled)
1987132232Srwatson		return (0);
1988105634Srwatson
1989105634Srwatson	subj = SLOT(cred->cr_label);
1990101099Srwatson	obj = SLOT(semaklabel);
1991101099Srwatson
1992105634Srwatson	if (!mls_dominate_effective(subj, obj))
1993105634Srwatson		return (EACCES);
1994101099Srwatson
1995172955Srwatson	return (0);
1996101099Srwatson}
1997101099Srwatson
1998101099Srwatsonstatic int
1999105634Srwatsonmls_sysvsem_check_semop(struct ucred *cred, struct semid_kernel *semakptr,
2000101099Srwatson    struct label *semaklabel, size_t accesstype)
2001132232Srwatson{
2002105634Srwatson	struct mac_mls *subj, *obj;
2003105634Srwatson
2004105634Srwatson	if (!mls_enabled)
2005105634Srwatson		return (0);
2006172955Srwatson
2007105634Srwatson	subj = SLOT(cred->cr_label);
2008101099Srwatson	obj = SLOT(semaklabel);
2009105634Srwatson
2010105634Srwatson	if( accesstype & SEM_R )
2011105634Srwatson		if (!mls_dominate_effective(subj, obj))
2012105634Srwatson			return (EACCES);
2013172955Srwatson
2014172955Srwatson	if( accesstype & SEM_A )
2015105634Srwatson		if (!mls_dominate_effective(obj, subj))
2016105634Srwatson			return (EACCES);
2017105634Srwatson
2018105634Srwatson	return (0);
2019105634Srwatson}
2020101099Srwatson
2021101099Srwatsonstatic void
2022101099Srwatsonmls_sysvsem_cleanup(struct label *semalabel)
2023101099Srwatson{
2024172955Srwatson
2025168976Srwatson	bzero(SLOT(semalabel), sizeof(struct mac_mls));
2026102115Srwatson}
2027102115Srwatson
2028102115Srwatsonstatic void
2029172955Srwatsonmls_sysvsem_create(struct ucred *cred, struct semid_kernel *semakptr,
2030102115Srwatson    struct label *semalabel)
2031102115Srwatson{
2032122524Srwatson	struct mac_mls *source, *dest;
2033168976Srwatson
2034102115Srwatson	source = SLOT(cred->cr_label);
2035172955Srwatson	dest = SLOT(semalabel);
2036102115Srwatson
2037102115Srwatson	mls_copy_effective(source, dest);
2038102115Srwatson}
2039102115Srwatson
2040102115Srwatsonstatic int
2041102115Srwatsonmls_sysvshm_check_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
2042172955Srwatson    struct label *shmseglabel, int shmflg)
2043168976Srwatson{
2044102115Srwatson	struct mac_mls *subj, *obj;
2045102115Srwatson
2046102115Srwatson	if (!mls_enabled)
2047172955Srwatson		return (0);
2048102115Srwatson
2049102115Srwatson	subj = SLOT(cred->cr_label);
2050122524Srwatson	obj = SLOT(shmseglabel);
2051168976Srwatson
2052102115Srwatson	if (!mls_dominate_effective(subj, obj))
2053172955Srwatson		return (EACCES);
2054102115Srwatson	if ((shmflg & SHM_RDONLY) == 0) {
2055102115Srwatson		if (!mls_dominate_effective(obj, subj))
2056102115Srwatson			return (EACCES);
2057102115Srwatson	}
2058102115Srwatson
2059102115Srwatson	return (0);
2060172955Srwatson}
2061172850Srwatson
2062145855Srwatsonstatic int
2063145855Srwatsonmls_sysvshm_check_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
2064145855Srwatson    struct label *shmseglabel, int cmd)
2065172955Srwatson{
2066145855Srwatson	struct mac_mls *subj, *obj;
2067145855Srwatson
2068145855Srwatson	if (!mls_enabled)
2069172850Srwatson		return (0);
2070145855Srwatson
2071172955Srwatson	subj = SLOT(cred->cr_label);
2072145855Srwatson	obj = SLOT(shmseglabel);
2073145855Srwatson
2074145855Srwatson	switch(cmd) {
2075145855Srwatson	case IPC_RMID:
2076145855Srwatson	case IPC_SET:
2077145855Srwatson		if (!mls_dominate_effective(obj, subj))
2078172955Srwatson			return (EACCES);
2079172850Srwatson		break;
2080145855Srwatson
2081145855Srwatson	case IPC_STAT:
2082145855Srwatson	case SHM_STAT:
2083172955Srwatson		if (!mls_dominate_effective(subj, obj))
2084145855Srwatson			return (EACCES);
2085145855Srwatson		break;
2086145855Srwatson
2087172850Srwatson	default:
2088145855Srwatson		return (EACCES);
2089172955Srwatson	}
2090145855Srwatson
2091145855Srwatson	return (0);
2092145855Srwatson}
2093145855Srwatson
2094145855Srwatsonstatic int
2095145855Srwatsonmls_sysvshm_check_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
2096172955Srwatson    struct label *shmseglabel, int shmflg)
2097101099Srwatson{
2098101099Srwatson	struct mac_mls *subj, *obj;
2099101099Srwatson
2100172955Srwatson	if (!mls_enabled)
2101101099Srwatson		return (0);
2102101099Srwatson
2103122524Srwatson	subj = SLOT(cred->cr_label);
2104168976Srwatson	obj = SLOT(shmseglabel);
2105101099Srwatson
2106101099Srwatson	if (!mls_dominate_effective(obj, subj))
2107172955Srwatson		return (EACCES);
2108101099Srwatson
2109172955Srwatson	return (0);
2110101099Srwatson}
2111101099Srwatson
2112101099Srwatsonstatic void
2113101099Srwatsonmls_sysvshm_cleanup(struct label *shmlabel)
2114101099Srwatson{
2115101099Srwatson
2116172955Srwatson	bzero(SLOT(shmlabel), sizeof(struct mac_mls));
2117101099Srwatson}
2118101099Srwatson
2119103759Srwatsonstatic void
2120172955Srwatsonmls_sysvshm_create(struct ucred *cred, struct shmid_kernel *shmsegptr,
2121101099Srwatson    struct label *shmlabel)
2122101099Srwatson{
2123122524Srwatson	struct mac_mls *source, *dest;
2124168976Srwatson
2125103759Srwatson	source = SLOT(cred->cr_label);
2126101099Srwatson	dest = SLOT(shmlabel);
2127172955Srwatson
2128101099Srwatson	mls_copy_effective(source, dest);
2129172955Srwatson}
2130101099Srwatson
2131101099Srwatsonstatic int
2132101099Srwatsonmls_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2133101099Srwatson    struct vnode *vp, struct label *vplabel)
2134101099Srwatson{
2135101099Srwatson	struct mac_mls mm_temp, *source, *dest;
2136172955Srwatson	int buflen, error;
2137101099Srwatson
2138101099Srwatson	source = SLOT(mplabel);
2139103759Srwatson	dest = SLOT(vplabel);
2140172955Srwatson
2141101099Srwatson	buflen = sizeof(mm_temp);
2142101099Srwatson	bzero(&mm_temp, buflen);
2143122524Srwatson
2144168976Srwatson	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2145103759Srwatson	    MAC_MLS_EXTATTR_NAME, &buflen, (char *) &mm_temp, curthread);
2146101099Srwatson	if (error == ENOATTR || error == EOPNOTSUPP) {
2147172955Srwatson		/* Fall back to the mntlabel. */
2148101099Srwatson		mls_copy_effective(source, dest);
2149172955Srwatson		return (0);
2150101099Srwatson	} else if (error)
2151101099Srwatson		return (error);
2152101099Srwatson
2153101099Srwatson	if (buflen != sizeof(mm_temp)) {
2154101099Srwatson		printf("mls_vnode_associate_extattr: bad size %d\n", buflen);
2155101099Srwatson		return (EPERM);
2156172955Srwatson	}
2157168976Srwatson	if (mls_valid(&mm_temp) != 0) {
2158101099Srwatson		printf("mls_vnode_associate_extattr: invalid\n");
2159101099Srwatson		return (EPERM);
2160101099Srwatson	}
2161172955Srwatson	if ((mm_temp.mm_flags & MAC_MLS_FLAGS_BOTH) !=
2162101099Srwatson	    MAC_MLS_FLAG_EFFECTIVE) {
2163101099Srwatson		printf("mls_associated_vnode_extattr: not effective\n");
2164168976Srwatson		return (EPERM);
2165168976Srwatson	}
2166101099Srwatson
2167172955Srwatson	mls_copy_effective(&mm_temp, dest);
2168101099Srwatson	return (0);
2169101099Srwatson}
2170101099Srwatson
2171172955Srwatsonstatic void
2172168976Srwatsonmls_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2173101099Srwatson    struct vnode *vp, struct label *vplabel)
2174101099Srwatson{
2175105634Srwatson	struct mac_mls *source, *dest;
2176101099Srwatson
2177101099Srwatson	source = SLOT(mplabel);
2178122524Srwatson	dest = SLOT(vplabel);
2179168976Srwatson
2180101099Srwatson	mls_copy_effective(source, dest);
2181101099Srwatson}
2182172955Srwatson
2183172955Srwatsonstatic int
2184101099Srwatsonmls_vnode_check_chdir(struct ucred *cred, struct vnode *dvp,
2185132232Srwatson    struct label *dvplabel)
2186105634Srwatson{
2187105634Srwatson	struct mac_mls *subj, *obj;
2188101099Srwatson
2189101099Srwatson	if (!mls_enabled)
2190172955Srwatson		return (0);
2191172955Srwatson
2192101099Srwatson	subj = SLOT(cred->cr_label);
2193172955Srwatson	obj = SLOT(dvplabel);
2194101099Srwatson
2195101099Srwatson	if (!mls_dominate_effective(subj, obj))
2196101099Srwatson		return (EACCES);
2197105634Srwatson
2198101099Srwatson	return (0);
2199132232Srwatson}
2200105634Srwatson
2201132232Srwatsonstatic int
2202105634Srwatsonmls_vnode_check_chroot(struct ucred *cred, struct vnode *dvp,
2203105634Srwatson    struct label *dvplabel)
2204172955Srwatson{
2205105634Srwatson	struct mac_mls *subj, *obj;
2206101099Srwatson
2207105634Srwatson	if (!mls_enabled)
2208105634Srwatson		return (0);
2209105634Srwatson
2210105634Srwatson	subj = SLOT(cred->cr_label);
2211172955Srwatson	obj = SLOT(dvplabel);
2212172955Srwatson
2213105634Srwatson	if (!mls_dominate_effective(subj, obj))
2214105634Srwatson		return (EACCES);
2215105634Srwatson
2216105634Srwatson	return (0);
2217105634Srwatson}
2218101099Srwatson
2219101099Srwatsonstatic int
2220101099Srwatsonmls_vnode_check_create(struct ucred *cred, struct vnode *dvp,
2221101099Srwatson    struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2222172955Srwatson{
2223168976Srwatson	struct mac_mls *subj, *obj;
2224101099Srwatson
2225101099Srwatson	if (!mls_enabled)
2226101099Srwatson		return (0);
2227172955Srwatson
2228105722Srwatson	subj = SLOT(cred->cr_label);
2229105722Srwatson	obj = SLOT(dvplabel);
2230122524Srwatson
2231168976Srwatson	if (!mls_dominate_effective(obj, subj))
2232101099Srwatson		return (EACCES);
2233172955Srwatson
2234101099Srwatson	return (0);
2235101099Srwatson}
2236101099Srwatson
2237101099Srwatsonstatic int
2238101099Srwatsonmls_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
2239168951Srwatson    struct label *vplabel, acl_type_t type)
2240168951Srwatson{
2241168951Srwatson	struct mac_mls *subj, *obj;
2242168951Srwatson
2243168951Srwatson	if (!mls_enabled)
2244101099Srwatson		return (0);
2245172955Srwatson
2246112574Srwatson	subj = SLOT(cred->cr_label);
2247112574Srwatson	obj = SLOT(vplabel);
2248112574Srwatson
2249112574Srwatson	if (!mls_dominate_effective(obj, subj))
2250172955Srwatson		return (EACCES);
2251112574Srwatson
2252112574Srwatson	return (0);
2253168951Srwatson}
2254168951Srwatson
2255168951Srwatsonstatic int
2256168951Srwatsonmls_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
2257168951Srwatson    struct label *vplabel, int attrnamespace, const char *name)
2258168951Srwatson{
2259112574Srwatson	struct mac_mls *subj, *obj;
2260168951Srwatson
2261168951Srwatson	if (!mls_enabled)
2262168951Srwatson		return (0);
2263168951Srwatson
2264168951Srwatson	subj = SLOT(cred->cr_label);
2265168951Srwatson	obj = SLOT(vplabel);
2266168951Srwatson
2267112574Srwatson	if (!mls_dominate_effective(obj, subj))
2268168951Srwatson		return (EACCES);
2269168951Srwatson
2270168951Srwatson	return (0);
2271168951Srwatson}
2272168951Srwatson
2273168951Srwatsonstatic int
2274168951Srwatsonmls_vnode_check_exec(struct ucred *cred, struct vnode *vp,
2275168951Srwatson    struct label *vplabel, struct image_params *imgp,
2276168951Srwatson    struct label *execlabel)
2277168951Srwatson{
2278168951Srwatson	struct mac_mls *subj, *obj, *exec;
2279168951Srwatson	int error;
2280168951Srwatson
2281168951Srwatson	if (execlabel != NULL) {
2282168951Srwatson		/*
2283168951Srwatson		 * We currently don't permit labels to be changed at
2284168951Srwatson		 * exec-time as part of MLS, so disallow non-NULL MLS label
2285168951Srwatson		 * elements in the execlabel.
2286168951Srwatson		 */
2287168951Srwatson		exec = SLOT(execlabel);
2288168951Srwatson		error = mls_atmostflags(exec, 0);
2289168951Srwatson		if (error)
2290168951Srwatson			return (error);
2291168951Srwatson	}
2292168951Srwatson
2293168951Srwatson	if (!mls_enabled)
2294168951Srwatson		return (0);
2295168951Srwatson
2296168951Srwatson	subj = SLOT(cred->cr_label);
2297168951Srwatson	obj = SLOT(vplabel);
2298168951Srwatson
2299168951Srwatson	if (!mls_dominate_effective(subj, obj))
2300168951Srwatson		return (EACCES);
2301168951Srwatson
2302168951Srwatson	return (0);
2303168951Srwatson}
2304168951Srwatson
2305168951Srwatsonstatic int
2306168951Srwatsonmls_vnode_check_getacl(struct ucred *cred, struct vnode *vp,
2307168951Srwatson    struct label *vplabel, acl_type_t type)
2308168951Srwatson{
2309168951Srwatson	struct mac_mls *subj, *obj;
2310168951Srwatson
2311168951Srwatson	if (!mls_enabled)
2312168951Srwatson		return (0);
2313168951Srwatson
2314168951Srwatson	subj = SLOT(cred->cr_label);
2315168951Srwatson	obj = SLOT(vplabel);
2316168951Srwatson
2317168951Srwatson	if (!mls_dominate_effective(subj, obj))
2318168951Srwatson		return (EACCES);
2319168951Srwatson
2320168951Srwatson	return (0);
2321168951Srwatson}
2322168951Srwatson
2323168951Srwatsonstatic int
2324168951Srwatsonmls_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
2325168951Srwatson    struct label *vplabel, int attrnamespace, const char *name,
2326168951Srwatson    struct uio *uio)
2327168951Srwatson{
2328168951Srwatson	struct mac_mls *subj, *obj;
2329168951Srwatson
2330168951Srwatson	if (!mls_enabled)
2331168951Srwatson		return (0);
2332168951Srwatson
2333168951Srwatson	subj = SLOT(cred->cr_label);
2334168951Srwatson	obj = SLOT(vplabel);
2335168951Srwatson
2336168951Srwatson	if (!mls_dominate_effective(subj, obj))
2337168951Srwatson		return (EACCES);
2338168951Srwatson
2339168951Srwatson	return (0);
2340168951Srwatson}
2341168951Srwatson
2342168951Srwatsonstatic int
2343168951Srwatsonmls_vnode_check_link(struct ucred *cred, struct vnode *dvp,
2344168951Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2345168951Srwatson    struct componentname *cnp)
2346168951Srwatson{
2347168951Srwatson	struct mac_mls *subj, *obj;
2348168951Srwatson
2349168951Srwatson	if (!mls_enabled)
2350168951Srwatson		return (0);
2351168951Srwatson
2352168951Srwatson	subj = SLOT(cred->cr_label);
2353168951Srwatson	obj = SLOT(dvplabel);
2354168951Srwatson
2355168951Srwatson	if (!mls_dominate_effective(obj, subj))
2356168951Srwatson		return (EACCES);
2357168951Srwatson
2358168951Srwatson	obj = SLOT(vplabel);
2359168951Srwatson	if (!mls_dominate_effective(obj, subj))
2360168951Srwatson		return (EACCES);
2361168951Srwatson
2362168951Srwatson	return (0);
2363168951Srwatson}
2364168951Srwatson
2365168951Srwatsonstatic int
2366168951Srwatsonmls_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
2367168951Srwatson    struct label *vplabel, int attrnamespace)
2368168951Srwatson{
2369168951Srwatson
2370168951Srwatson	struct mac_mls *subj, *obj;
2371168951Srwatson
2372168951Srwatson	if (!mls_enabled)
2373168951Srwatson		return (0);
2374168951Srwatson
2375168951Srwatson	subj = SLOT(cred->cr_label);
2376168951Srwatson	obj = SLOT(vplabel);
2377168951Srwatson
2378168951Srwatson	if (!mls_dominate_effective(subj, obj))
2379168951Srwatson		return (EACCES);
2380168951Srwatson
2381168951Srwatson	return (0);
2382168951Srwatson}
2383168951Srwatson
2384168951Srwatsonstatic int
2385168951Srwatsonmls_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
2386168951Srwatson    struct label *dvplabel, struct componentname *cnp)
2387168951Srwatson{
2388168951Srwatson	struct mac_mls *subj, *obj;
2389168951Srwatson
2390168951Srwatson	if (!mls_enabled)
2391168951Srwatson		return (0);
2392168951Srwatson
2393168951Srwatson	subj = SLOT(cred->cr_label);
2394168951Srwatson	obj = SLOT(dvplabel);
2395168951Srwatson
2396168951Srwatson	if (!mls_dominate_effective(subj, obj))
2397168951Srwatson		return (EACCES);
2398168951Srwatson
2399168951Srwatson	return (0);
2400168951Srwatson}
2401168951Srwatson
2402168951Srwatsonstatic int
2403168951Srwatsonmls_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
2404168951Srwatson    struct label *vplabel, int prot, int flags)
2405168951Srwatson{
2406168951Srwatson	struct mac_mls *subj, *obj;
2407168951Srwatson
2408168951Srwatson	/*
2409168951Srwatson	 * Rely on the use of open()-time protections to handle
2410168951Srwatson	 * non-revocation cases.
2411168951Srwatson	 */
2412168951Srwatson	if (!mls_enabled || !revocation_enabled)
2413168951Srwatson		return (0);
2414168951Srwatson
2415168951Srwatson	subj = SLOT(cred->cr_label);
2416168951Srwatson	obj = SLOT(vplabel);
2417168951Srwatson
2418168951Srwatson	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2419168951Srwatson		if (!mls_dominate_effective(subj, obj))
2420168951Srwatson			return (EACCES);
2421172955Srwatson	}
2422168951Srwatson	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2423168951Srwatson		if (!mls_dominate_effective(obj, subj))
2424168951Srwatson			return (EACCES);
2425112574Srwatson	}
2426112574Srwatson
2427112574Srwatson	return (0);
2428112574Srwatson}
2429172955Srwatson
2430168976Srwatsonstatic int
2431106418Srwatsonmls_vnode_check_open(struct ucred *cred, struct vnode *vp,
2432106418Srwatson    struct label *vplabel, int acc_mode)
2433106418Srwatson{
2434106418Srwatson	struct mac_mls *subj, *obj;
2435172955Srwatson
2436106418Srwatson	if (!mls_enabled)
2437106418Srwatson		return (0);
2438122524Srwatson
2439106418Srwatson	subj = SLOT(cred->cr_label);
2440172955Srwatson	obj = SLOT(vplabel);
2441106418Srwatson
2442106418Srwatson	/* XXX privilege override for admin? */
2443106418Srwatson	if (acc_mode & (VREAD | VEXEC | VSTAT)) {
2444168976Srwatson		if (!mls_dominate_effective(subj, obj))
2445106418Srwatson			return (EACCES);
2446106418Srwatson	}
2447168976Srwatson	if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2448172955Srwatson		if (!mls_dominate_effective(obj, subj))
2449106418Srwatson			return (EACCES);
2450106418Srwatson	}
2451106418Srwatson
2452106418Srwatson	return (0);
2453106418Srwatson}
2454106418Srwatson
2455172955Srwatsonstatic int
2456168933Srwatsonmls_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
2457168933Srwatson    struct vnode *vp, struct label *vplabel)
2458168933Srwatson{
2459168933Srwatson	struct mac_mls *subj, *obj;
2460168933Srwatson
2461172955Srwatson	if (!mls_enabled || !revocation_enabled)
2462168933Srwatson		return (0);
2463168933Srwatson
2464168933Srwatson	subj = SLOT(active_cred->cr_label);
2465168933Srwatson	obj = SLOT(vplabel);
2466172955Srwatson
2467168933Srwatson	if (!mls_dominate_effective(subj, obj))
2468168933Srwatson		return (EACCES);
2469168933Srwatson
2470168933Srwatson	return (0);
2471168933Srwatson}
2472168933Srwatson
2473168933Srwatsonstatic int
2474172955Srwatsonmls_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
2475168933Srwatson    struct vnode *vp, struct label *vplabel)
2476168933Srwatson{
2477168933Srwatson	struct mac_mls *subj, *obj;
2478168933Srwatson
2479168933Srwatson	if (!mls_enabled || !revocation_enabled)
2480168933Srwatson		return (0);
2481172955Srwatson
2482168933Srwatson	subj = SLOT(active_cred->cr_label);
2483168933Srwatson	obj = SLOT(vplabel);
2484168933Srwatson
2485168933Srwatson	if (!mls_dominate_effective(subj, obj))
2486172955Srwatson		return (EACCES);
2487168933Srwatson
2488168933Srwatson	return (0);
2489168933Srwatson}
2490168933Srwatson
2491172955Srwatsonstatic int
2492168933Srwatsonmls_vnode_check_readdir(struct ucred *cred, struct vnode *dvp,
2493168933Srwatson    struct label *dvplabel)
2494168933Srwatson{
2495168933Srwatson	struct mac_mls *subj, *obj;
2496168933Srwatson
2497168933Srwatson	if (!mls_enabled)
2498168933Srwatson		return (0);
2499172955Srwatson
2500168976Srwatson	subj = SLOT(cred->cr_label);
2501106161Srwatson	obj = SLOT(dvplabel);
2502106161Srwatson
2503106416Srwatson	if (!mls_dominate_effective(subj, obj))
2504106161Srwatson		return (EACCES);
2505172955Srwatson
2506106161Srwatson	return (0);
2507106161Srwatson}
2508122524Srwatson
2509168976Srwatsonstatic int
2510106161Srwatsonmls_vnode_check_readlink(struct ucred *cred, struct vnode *vp,
2511172955Srwatson    struct label *vplabel)
2512106416Srwatson{
2513106416Srwatson	struct mac_mls *subj, *obj;
2514106161Srwatson
2515172955Srwatson	if (!mls_enabled)
2516106161Srwatson		return (0);
2517106161Srwatson
2518106161Srwatson	subj = SLOT(cred->cr_label);
2519106161Srwatson	obj = SLOT(vplabel);
2520106161Srwatson
2521106161Srwatson	if (!mls_dominate_effective(subj, obj))
2522172955Srwatson		return (EACCES);
2523112574Srwatson
2524112574Srwatson	return (0);
2525166617Srwatson}
2526112574Srwatson
2527112574Srwatsonstatic int
2528172955Srwatsonmls_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
2529112574Srwatson    struct label *vplabel, struct label *newlabel)
2530112574Srwatson{
2531122524Srwatson	struct mac_mls *old, *new, *subj;
2532112574Srwatson	int error;
2533172955Srwatson
2534112574Srwatson	old = SLOT(vplabel);
2535112574Srwatson	new = SLOT(newlabel);
2536112574Srwatson	subj = SLOT(cred->cr_label);
2537112574Srwatson
2538112574Srwatson	/*
2539112574Srwatson	 * If there is an MLS label update for the vnode, it must be a
2540112574Srwatson	 * effective label.
2541172955Srwatson	 */
2542126121Spjd	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2543106161Srwatson	if (error)
2544106161Srwatson		return (error);
2545106161Srwatson
2546106161Srwatson	/*
2547172955Srwatson	 * To perform a relabel of the vnode (MLS label or not), MLS must
2548106161Srwatson	 * authorize the relabel.
2549106161Srwatson	 */
2550122524Srwatson	if (!mls_effective_in_range(old, subj))
2551106161Srwatson		return (EPERM);
2552106161Srwatson
2553172955Srwatson	/*
2554172955Srwatson	 * If the MLS label is to be changed, authorize as appropriate.
2555106161Srwatson	 */
2556126121Spjd	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2557172955Srwatson		/*
2558106161Srwatson		 * To change the MLS label on a vnode, the new vnode label
2559106161Srwatson		 * must be in the subject range.
2560172955Srwatson		 */
2561106161Srwatson		if (!mls_effective_in_range(new, subj))
2562106161Srwatson			return (EPERM);
2563106161Srwatson
2564106161Srwatson		/*
2565106161Srwatson		 * To change the MLS label on the vnode to be EQUAL, the
2566106161Srwatson		 * subject must have appropriate privilege.
2567106161Srwatson		 */
2568106161Srwatson		if (mls_contains_equal(new)) {
2569172955Srwatson			error = mls_subject_privileged(subj);
2570168976Srwatson			if (error)
2571101099Srwatson				return (error);
2572101099Srwatson		}
2573101099Srwatson	}
2574172955Srwatson
2575101099Srwatson	return (0);
2576101099Srwatson}
2577122524Srwatson
2578168976Srwatsonstatic int
2579101099Srwatsonmls_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
2580172955Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2581101099Srwatson    struct componentname *cnp)
2582101099Srwatson{
2583101099Srwatson	struct mac_mls *subj, *obj;
2584101099Srwatson
2585101099Srwatson	if (!mls_enabled)
2586101099Srwatson		return (0);
2587172955Srwatson
2588168976Srwatson	subj = SLOT(cred->cr_label);
2589101099Srwatson	obj = SLOT(dvplabel);
2590101099Srwatson
2591101099Srwatson	if (!mls_dominate_effective(obj, subj))
2592172955Srwatson		return (EACCES);
2593101099Srwatson
2594101099Srwatson	obj = SLOT(vplabel);
2595122524Srwatson
2596168976Srwatson	if (!mls_dominate_effective(obj, subj))
2597101099Srwatson		return (EACCES);
2598172955Srwatson
2599101099Srwatson	return (0);
2600101099Srwatson}
2601101099Srwatson
2602101099Srwatsonstatic int
2603101099Srwatsonmls_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
2604101099Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2605172955Srwatson    int samedir, struct componentname *cnp)
2606168976Srwatson{
2607101099Srwatson	struct mac_mls *subj, *obj;
2608101099Srwatson
2609101099Srwatson	if (!mls_enabled)
2610172955Srwatson		return (0);
2611101099Srwatson
2612101099Srwatson	subj = SLOT(cred->cr_label);
2613122524Srwatson	obj = SLOT(dvplabel);
2614168976Srwatson
2615101099Srwatson	if (!mls_dominate_effective(obj, subj))
2616172955Srwatson		return (EACCES);
2617101099Srwatson
2618101099Srwatson	if (vp != NULL) {
2619101099Srwatson		obj = SLOT(vplabel);
2620101099Srwatson
2621101099Srwatson		if (!mls_dominate_effective(obj, subj))
2622101099Srwatson			return (EACCES);
2623172955Srwatson	}
2624168976Srwatson
2625101099Srwatson	return (0);
2626101099Srwatson}
2627101099Srwatson
2628172955Srwatsonstatic int
2629101099Srwatsonmls_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
2630101099Srwatson    struct label *vplabel)
2631122524Srwatson{
2632168976Srwatson	struct mac_mls *subj, *obj;
2633101099Srwatson
2634172955Srwatson	if (!mls_enabled)
2635101099Srwatson		return (0);
2636101099Srwatson
2637101099Srwatson	subj = SLOT(cred->cr_label);
2638101099Srwatson	obj = SLOT(vplabel);
2639101099Srwatson
2640101099Srwatson	if (!mls_dominate_effective(obj, subj))
2641172955Srwatson		return (EACCES);
2642168976Srwatson
2643119202Srwatson	return (0);
2644119202Srwatson}
2645119202Srwatson
2646172955Srwatsonstatic int
2647119202Srwatsonmls_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
2648119202Srwatson    struct label *vplabel, acl_type_t type, struct acl *acl)
2649122524Srwatson{
2650168976Srwatson	struct mac_mls *subj, *obj;
2651119202Srwatson
2652172955Srwatson	if (!mls_enabled)
2653119202Srwatson		return (0);
2654119202Srwatson
2655119202Srwatson	subj = SLOT(cred->cr_label);
2656119202Srwatson	obj = SLOT(vplabel);
2657119202Srwatson
2658119202Srwatson	if (!mls_dominate_effective(obj, subj))
2659172955Srwatson		return (EACCES);
2660168976Srwatson
2661106648Srwatson	return (0);
2662101099Srwatson}
2663106648Srwatson
2664106648Srwatsonstatic int
2665101099Srwatsonmls_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
2666106648Srwatson    struct label *vplabel, int attrnamespace, const char *name,
2667106648Srwatson    struct uio *uio)
2668106648Srwatson{
2669172955Srwatson	struct mac_mls *subj, *obj;
2670172955Srwatson
2671106648Srwatson	if (!mls_enabled)
2672106648Srwatson		return (0);
2673106648Srwatson
2674106648Srwatson	subj = SLOT(cred->cr_label);
2675106648Srwatson	obj = SLOT(vplabel);
2676106648Srwatson
2677106648Srwatson	if (!mls_dominate_effective(obj, subj))
2678172955Srwatson		return (EACCES);
2679101099Srwatson
2680101099Srwatson	/* XXX: protect the MAC EA in a special way? */
2681122524Srwatson
2682168976Srwatson	return (0);
2683101099Srwatson}
2684172955Srwatson
2685101099Srwatsonstatic int
2686101099Srwatsonmls_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
2687101099Srwatson    struct label *vplabel, u_long flags)
2688101099Srwatson{
2689101099Srwatson	struct mac_mls *subj, *obj;
2690101099Srwatson
2691172955Srwatson	if (!mls_enabled)
2692168976Srwatson		return (0);
2693101099Srwatson
2694101099Srwatson	subj = SLOT(cred->cr_label);
2695101099Srwatson	obj = SLOT(vplabel);
2696172955Srwatson
2697101099Srwatson	if (!mls_dominate_effective(obj, subj))
2698101099Srwatson		return (EACCES);
2699122524Srwatson
2700168976Srwatson	return (0);
2701101099Srwatson}
2702172955Srwatson
2703101099Srwatsonstatic int
2704101099Srwatsonmls_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
2705101099Srwatson    struct label *vplabel, mode_t mode)
2706101099Srwatson{
2707101099Srwatson	struct mac_mls *subj, *obj;
2708101099Srwatson
2709172955Srwatson	if (!mls_enabled)
2710168976Srwatson		return (0);
2711168976Srwatson
2712101099Srwatson	subj = SLOT(cred->cr_label);
2713101099Srwatson	obj = SLOT(vplabel);
2714101099Srwatson
2715172955Srwatson	if (!mls_dominate_effective(obj, subj))
2716101099Srwatson		return (EACCES);
2717101099Srwatson
2718122524Srwatson	return (0);
2719168976Srwatson}
2720101099Srwatson
2721172955Srwatsonstatic int
2722101099Srwatsonmls_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
2723101099Srwatson    struct label *vplabel, uid_t uid, gid_t gid)
2724101099Srwatson{
2725101099Srwatson	struct mac_mls *subj, *obj;
2726101099Srwatson
2727101099Srwatson	if (!mls_enabled)
2728172955Srwatson		return (0);
2729168976Srwatson
2730104530Srwatson	subj = SLOT(cred->cr_label);
2731104530Srwatson	obj = SLOT(vplabel);
2732104530Srwatson
2733104530Srwatson	if (!mls_dominate_effective(obj, subj))
2734172955Srwatson		return (EACCES);
2735104530Srwatson
2736104530Srwatson	return (0);
2737122524Srwatson}
2738168976Srwatson
2739104530Srwatsonstatic int
2740172955Srwatsonmls_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
2741104530Srwatson    struct label *vplabel, struct timespec atime, struct timespec mtime)
2742104530Srwatson{
2743168976Srwatson	struct mac_mls *subj, *obj;
2744104530Srwatson
2745172955Srwatson	if (!mls_enabled)
2746104530Srwatson		return (0);
2747104530Srwatson
2748104530Srwatson	subj = SLOT(cred->cr_label);
2749104530Srwatson	obj = SLOT(vplabel);
2750104530Srwatson
2751104530Srwatson	if (!mls_dominate_effective(obj, subj))
2752172955Srwatson		return (EACCES);
2753168976Srwatson
2754119202Srwatson	return (0);
2755119202Srwatson}
2756119202Srwatson
2757172955Srwatsonstatic int
2758119202Srwatsonmls_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred,
2759119202Srwatson    struct vnode *vp, struct label *vplabel)
2760122524Srwatson{
2761168976Srwatson	struct mac_mls *subj, *obj;
2762119202Srwatson
2763172955Srwatson	if (!mls_enabled)
2764119202Srwatson		return (0);
2765119202Srwatson
2766119202Srwatson	subj = SLOT(active_cred->cr_label);
2767119202Srwatson	obj = SLOT(vplabel);
2768119202Srwatson
2769119202Srwatson	if (!mls_dominate_effective(subj, obj))
2770172955Srwatson		return (EACCES);
2771168976Srwatson
2772101099Srwatson	return (0);
2773101099Srwatson}
2774103759Srwatson
2775172955Srwatsonstatic int
2776101099Srwatsonmls_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
2777103759Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2778122524Srwatson    struct componentname *cnp)
2779168976Srwatson{
2780103759Srwatson	struct mac_mls *subj, *obj;
2781172955Srwatson
2782101099Srwatson	if (!mls_enabled)
2783101099Srwatson		return (0);
2784103759Srwatson
2785101099Srwatson	subj = SLOT(cred->cr_label);
2786101099Srwatson	obj = SLOT(dvplabel);
2787101099Srwatson
2788172955Srwatson	if (!mls_dominate_effective(obj, subj))
2789168976Srwatson		return (EACCES);
2790104546Srwatson
2791104546Srwatson	obj = SLOT(vplabel);
2792104546Srwatson
2793104546Srwatson	if (!mls_dominate_effective(obj, subj))
2794104546Srwatson		return (EACCES);
2795104546Srwatson
2796104546Srwatson	return (0);
2797172955Srwatson}
2798104546Srwatson
2799104546Srwatsonstatic int
2800122524Srwatsonmls_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred,
2801168976Srwatson    struct vnode *vp, struct label *vplabel)
2802104546Srwatson{
2803104546Srwatson	struct mac_mls *subj, *obj;
2804172955Srwatson
2805104546Srwatson	if (!mls_enabled || !revocation_enabled)
2806104546Srwatson		return (0);
2807145076Scsjp
2808172955Srwatson	subj = SLOT(active_cred->cr_label);
2809104546Srwatson	obj = SLOT(vplabel);
2810104546Srwatson
2811104546Srwatson	if (!mls_dominate_effective(obj, subj))
2812104569Srwatson		return (EACCES);
2813104546Srwatson
2814104546Srwatson	return (0);
2815104546Srwatson}
2816172955Srwatson
2817168976Srwatsonstatic int
2818101099Srwatsonmls_vnode_create_extattr(struct ucred *cred, struct mount *mp,
2819101099Srwatson    struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
2820101099Srwatson    struct vnode *vp, struct label *vplabel, struct componentname *cnp)
2821172955Srwatson{
2822101099Srwatson	struct mac_mls *source, *dest, mm_temp;
2823101099Srwatson	size_t buflen;
2824122524Srwatson	int error;
2825168976Srwatson
2826101099Srwatson	buflen = sizeof(mm_temp);
2827101099Srwatson	bzero(&mm_temp, buflen);
2828101099Srwatson
2829172955Srwatson	source = SLOT(cred->cr_label);
2830101099Srwatson	dest = SLOT(vplabel);
2831101099Srwatson	mls_copy_effective(source, &mm_temp);
2832101099Srwatson
2833172955Srwatson	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2834101099Srwatson	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
2835101099Srwatson	if (error == 0)
2836101099Srwatson		mls_copy_effective(source, dest);
2837101099Srwatson	return (error);
2838101099Srwatson}
2839101099Srwatson
2840101099Srwatsonstatic void
2841172955Srwatsonmls_vnode_relabel(struct ucred *cred, struct vnode *vp,
2842168976Srwatson    struct label *vplabel, struct label *label)
2843102112Srwatson{
2844102112Srwatson	struct mac_mls *source, *dest;
2845102112Srwatson
2846172955Srwatson	source = SLOT(label);
2847102112Srwatson	dest = SLOT(vplabel);
2848102112Srwatson
2849122524Srwatson	mls_copy(source, dest);
2850168976Srwatson}
2851102112Srwatson
2852172955Srwatsonstatic int
2853102112Srwatsonmls_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
2854102112Srwatson    struct label *vplabel, struct label *intlabel)
2855102112Srwatson{
2856102112Srwatson	struct mac_mls *source, mm_temp;
2857102112Srwatson	size_t buflen;
2858102112Srwatson	int error;
2859172955Srwatson
2860168976Srwatson	buflen = sizeof(mm_temp);
2861102112Srwatson	bzero(&mm_temp, buflen);
2862102112Srwatson
2863102112Srwatson	source = SLOT(intlabel);
2864172955Srwatson	if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0)
2865102112Srwatson		return (0);
2866102112Srwatson
2867122524Srwatson	mls_copy_effective(source, &mm_temp);
2868168976Srwatson
2869102112Srwatson	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2870172955Srwatson	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
2871102112Srwatson	return (error);
2872102112Srwatson}
2873102112Srwatson
2874102112Srwatsonstatic struct mac_policy_ops mls_ops =
2875102112Srwatson{
2876102112Srwatson	.mpo_init = mls_init,
2877172955Srwatson
2878168976Srwatson	.mpo_bpfdesc_check_receive = mls_bpfdesc_check_receive,
2879101099Srwatson	.mpo_bpfdesc_create = mls_bpfdesc_create,
2880101099Srwatson	.mpo_bpfdesc_create_mbuf = mls_bpfdesc_create_mbuf,
2881101099Srwatson	.mpo_bpfdesc_destroy_label = mls_destroy_label,
2882172955Srwatson	.mpo_bpfdesc_init_label = mls_init_label,
2883101099Srwatson
2884101099Srwatson	.mpo_cred_check_relabel = mls_cred_check_relabel,
2885122524Srwatson	.mpo_cred_check_visible = mls_cred_check_visible,
2886168976Srwatson	.mpo_cred_copy_label = mls_copy_label,
2887101099Srwatson	.mpo_cred_destroy_label = mls_destroy_label,
2888172955Srwatson	.mpo_cred_externalize_label = mls_externalize_label,
2889101099Srwatson	.mpo_cred_init_label = mls_init_label,
2890101099Srwatson	.mpo_cred_internalize_label = mls_internalize_label,
2891101099Srwatson	.mpo_cred_relabel = mls_cred_relabel,
2892101099Srwatson
2893101099Srwatson	.mpo_devfs_create_device = mls_devfs_create_device,
2894101099Srwatson	.mpo_devfs_create_directory = mls_devfs_create_directory,
2895172955Srwatson	.mpo_devfs_create_symlink = mls_devfs_create_symlink,
2896168976Srwatson	.mpo_devfs_destroy_label = mls_destroy_label,
2897101099Srwatson	.mpo_devfs_init_label = mls_init_label,
2898101099Srwatson	.mpo_devfs_update = mls_devfs_update,
2899101099Srwatson	.mpo_devfs_vnode_associate = mls_devfs_vnode_associate,
2900172955Srwatson
2901101099Srwatson	.mpo_ifnet_check_relabel = mls_ifnet_check_relabel,
2902101099Srwatson	.mpo_ifnet_check_transmit = mls_ifnet_check_transmit,
2903122524Srwatson	.mpo_ifnet_copy_label = mls_copy_label,
2904168976Srwatson	.mpo_ifnet_create = mls_ifnet_create,
2905101099Srwatson	.mpo_ifnet_create_mbuf = mls_ifnet_create_mbuf,
2906172955Srwatson	.mpo_ifnet_destroy_label = mls_destroy_label,
2907101099Srwatson	.mpo_ifnet_externalize_label = mls_externalize_label,
2908101099Srwatson	.mpo_ifnet_init_label = mls_init_label,
2909101099Srwatson	.mpo_ifnet_internalize_label = mls_internalize_label,
2910101099Srwatson	.mpo_ifnet_relabel = mls_ifnet_relabel,
2911101099Srwatson
2912101099Srwatson	.mpo_inpcb_check_deliver = mls_inpcb_check_deliver,
2913172955Srwatson	.mpo_inpcb_create = mls_inpcb_create,
2914168976Srwatson	.mpo_inpcb_create_mbuf = mls_inpcb_create_mbuf,
2915101099Srwatson	.mpo_inpcb_destroy_label = mls_destroy_label,
2916101099Srwatson	.mpo_inpcb_init_label = mls_init_label_waitcheck,
2917105634Srwatson	.mpo_inpcb_sosetlabel = mls_inpcb_sosetlabel,
2918101099Srwatson
2919168976Srwatson	.mpo_ipq_create = mls_ipq_create,
2920101099Srwatson	.mpo_ipq_destroy_label = mls_destroy_label,
2921122524Srwatson	.mpo_ipq_init_label = mls_init_label_waitcheck,
2922101099Srwatson	.mpo_ipq_match = mls_ipq_match,
2923101099Srwatson	.mpo_ipq_reassemble = mls_ipq_reassemble,
2924105634Srwatson	.mpo_ipq_update = mls_ipq_update,
2925132232Srwatson
2926101099Srwatson	.mpo_mbuf_copy_label = mls_copy_label,
2927132232Srwatson	.mpo_mbuf_destroy_label = mls_destroy_label,
2928105634Srwatson	.mpo_mbuf_init_label = mls_init_label_waitcheck,
2929105634Srwatson
2930101099Srwatson	.mpo_mount_check_stat = mls_mount_check_stat,
2931101099Srwatson	.mpo_mount_create = mls_mount_create,
2932105634Srwatson	.mpo_mount_destroy_label = mls_destroy_label,
2933105634Srwatson	.mpo_mount_init_label = mls_init_label,
2934101099Srwatson
2935172955Srwatson	.mpo_netatalk_aarp_send = mls_netatalk_aarp_send,
2936101099Srwatson
2937101099Srwatson	.mpo_netinet_arp_send = mls_netinet_arp_send,
2938101099Srwatson	.mpo_netinet_firewall_reply = mls_netinet_firewall_reply,
2939105634Srwatson	.mpo_netinet_firewall_send = mls_netinet_firewall_send,
2940101099Srwatson	.mpo_netinet_fragment = mls_netinet_fragment,
2941132232Srwatson	.mpo_netinet_icmp_reply = mls_netinet_icmp_reply,
2942105634Srwatson	.mpo_netinet_igmp_send = mls_netinet_igmp_send,
2943105634Srwatson
2944105634Srwatson	.mpo_netinet6_nd6_send = mls_netinet6_nd6_send,
2945105634Srwatson
2946172955Srwatson	.mpo_pipe_check_ioctl = mls_pipe_check_ioctl,
2947105634Srwatson	.mpo_pipe_check_poll = mls_pipe_check_poll,
2948101099Srwatson	.mpo_pipe_check_read = mls_pipe_check_read,
2949105634Srwatson	.mpo_pipe_check_relabel = mls_pipe_check_relabel,
2950172955Srwatson	.mpo_pipe_check_stat = mls_pipe_check_stat,
2951172955Srwatson	.mpo_pipe_check_write = mls_pipe_check_write,
2952105634Srwatson	.mpo_pipe_copy_label = mls_copy_label,
2953172955Srwatson	.mpo_pipe_create = mls_pipe_create,
2954172955Srwatson	.mpo_pipe_destroy_label = mls_destroy_label,
2955105634Srwatson	.mpo_pipe_externalize_label = mls_externalize_label,
2956105634Srwatson	.mpo_pipe_init_label = mls_init_label,
2957105634Srwatson	.mpo_pipe_internalize_label = mls_internalize_label,
2958105634Srwatson	.mpo_pipe_relabel = mls_pipe_relabel,
2959105634Srwatson
2960105634Srwatson	.mpo_posixsem_check_destroy = mls_posixsem_check_write,
2961101099Srwatson	.mpo_posixsem_check_getvalue = mls_posixsem_check_rdonly,
2962101099Srwatson	.mpo_posixsem_check_open = mls_posixsem_check_write,
2963101099Srwatson	.mpo_posixsem_check_post = mls_posixsem_check_write,
2964172955Srwatson	.mpo_posixsem_check_unlink = mls_posixsem_check_write,
2965168976Srwatson	.mpo_posixsem_check_wait = mls_posixsem_check_write,
2966101099Srwatson	.mpo_posixsem_create = mls_posixsem_create,
2967101099Srwatson	.mpo_posixsem_destroy_label = mls_destroy_label,
2968101099Srwatson	.mpo_posixsem_init_label = mls_init_label,
2969101099Srwatson
2970172955Srwatson	.mpo_proc_associate_nfsd = mls_proc_associate_nfsd,
2971101099Srwatson	.mpo_proc_check_debug = mls_proc_check_debug,
2972101099Srwatson	.mpo_proc_check_sched = mls_proc_check_sched,
2973122524Srwatson	.mpo_proc_check_signal = mls_proc_check_signal,
2974168976Srwatson	.mpo_proc_create_init = mls_proc_create_init,
2975101099Srwatson	.mpo_proc_create_swapper = mls_proc_create_swapper,
2976172955Srwatson
2977101099Srwatson	.mpo_socket_check_deliver = mls_socket_check_deliver,
2978101099Srwatson	.mpo_socket_check_relabel = mls_socket_check_relabel,
2979168976Srwatson	.mpo_socket_check_visible = mls_socket_check_visible,
2980101099Srwatson	.mpo_socket_copy_label = mls_copy_label,
2981172955Srwatson	.mpo_socket_create = mls_socket_create,
2982101099Srwatson	.mpo_socket_create_mbuf = mls_socket_create_mbuf,
2983101099Srwatson	.mpo_socket_destroy_label = mls_destroy_label,
2984101099Srwatson	.mpo_socket_externalize_label = mls_externalize_label,
2985101099Srwatson	.mpo_socket_init_label = mls_init_label_waitcheck,
2986101099Srwatson	.mpo_socket_internalize_label = mls_internalize_label,
2987101099Srwatson	.mpo_socket_newconn = mls_socket_newconn,
2988172955Srwatson	.mpo_socket_relabel = mls_socket_relabel,
2989168976Srwatson
2990168976Srwatson	.mpo_socketpeer_destroy_label = mls_destroy_label,
2991101099Srwatson	.mpo_socketpeer_externalize_label = mls_externalize_label,
2992101099Srwatson	.mpo_socketpeer_init_label = mls_init_label_waitcheck,
2993101099Srwatson	.mpo_socketpeer_set_from_mbuf = mls_socketpeer_set_from_mbuf,
2994172955Srwatson	.mpo_socketpeer_set_from_socket = mls_socketpeer_set_from_socket,
2995101099Srwatson
2996101099Srwatson	.mpo_syncache_create = mls_syncache_create,
2997122524Srwatson	.mpo_syncache_create_mbuf = mls_syncache_create_mbuf,
2998168976Srwatson	.mpo_syncache_destroy_label = mls_destroy_label,
2999101099Srwatson	.mpo_syncache_init_label = mls_init_label_waitcheck,
3000172955Srwatson
3001101099Srwatson	.mpo_sysvmsg_cleanup = mls_sysvmsg_cleanup,
3002101099Srwatson	.mpo_sysvmsg_create = mls_sysvmsg_create,
3003101099Srwatson	.mpo_sysvmsg_destroy_label = mls_destroy_label,
3004168976Srwatson	.mpo_sysvmsg_init_label = mls_init_label,
3005101099Srwatson
3006172955Srwatson	.mpo_sysvmsq_check_msgrcv = mls_sysvmsq_check_msgrcv,
3007101099Srwatson	.mpo_sysvmsq_check_msgrmid = mls_sysvmsq_check_msgrmid,
3008101099Srwatson	.mpo_sysvmsq_check_msqget = mls_sysvmsq_check_msqget,
3009101099Srwatson	.mpo_sysvmsq_check_msqsnd = mls_sysvmsq_check_msqsnd,
3010101099Srwatson	.mpo_sysvmsq_check_msqrcv = mls_sysvmsq_check_msqrcv,
3011101099Srwatson	.mpo_sysvmsq_check_msqctl = mls_sysvmsq_check_msqctl,
3012101099Srwatson	.mpo_sysvmsq_cleanup = mls_sysvmsq_cleanup,
3013101099Srwatson	.mpo_sysvmsq_destroy_label = mls_destroy_label,
3014172955Srwatson	.mpo_sysvmsq_init_label = mls_init_label,
3015168976Srwatson	.mpo_sysvmsq_create = mls_sysvmsq_create,
3016101099Srwatson
3017101099Srwatson	.mpo_sysvsem_check_semctl = mls_sysvsem_check_semctl,
3018101099Srwatson	.mpo_sysvsem_check_semget = mls_sysvsem_check_semget,
3019172955Srwatson	.mpo_sysvsem_check_semop = mls_sysvsem_check_semop,
3020101099Srwatson	.mpo_sysvsem_cleanup = mls_sysvsem_cleanup,
3021101099Srwatson	.mpo_sysvsem_create = mls_sysvsem_create,
3022122524Srwatson	.mpo_sysvsem_destroy_label = mls_destroy_label,
3023168976Srwatson	.mpo_sysvsem_init_label = mls_init_label,
3024101099Srwatson
3025172955Srwatson	.mpo_sysvshm_check_shmat = mls_sysvshm_check_shmat,
3026101099Srwatson	.mpo_sysvshm_check_shmctl = mls_sysvshm_check_shmctl,
3027101099Srwatson	.mpo_sysvshm_check_shmget = mls_sysvshm_check_shmget,
3028101099Srwatson	.mpo_sysvshm_cleanup = mls_sysvshm_cleanup,
3029101099Srwatson	.mpo_sysvshm_create = mls_sysvshm_create,
3030101099Srwatson	.mpo_sysvshm_destroy_label = mls_destroy_label,
3031101099Srwatson	.mpo_sysvshm_init_label = mls_init_label,
3032172955Srwatson
3033168976Srwatson
3034101099Srwatson	.mpo_system_check_acct = mls_system_check_acct,
3035101099Srwatson	.mpo_system_check_auditctl = mls_system_check_auditctl,
3036101099Srwatson	.mpo_system_check_swapon = mls_system_check_swapon,
3037172955Srwatson
3038101099Srwatson	.mpo_vnode_associate_extattr = mls_vnode_associate_extattr,
3039101099Srwatson	.mpo_vnode_associate_singlelabel = mls_vnode_associate_singlelabel,
3040122524Srwatson	.mpo_vnode_check_access = mls_vnode_check_open,
3041168976Srwatson	.mpo_vnode_check_chdir = mls_vnode_check_chdir,
3042101099Srwatson	.mpo_vnode_check_chroot = mls_vnode_check_chroot,
3043172955Srwatson	.mpo_vnode_check_create = mls_vnode_check_create,
3044101099Srwatson	.mpo_vnode_check_deleteacl = mls_vnode_check_deleteacl,
3045101099Srwatson	.mpo_vnode_check_deleteextattr = mls_vnode_check_deleteextattr,
3046101099Srwatson	.mpo_vnode_check_exec = mls_vnode_check_exec,
3047101099Srwatson	.mpo_vnode_check_getacl = mls_vnode_check_getacl,
3048101099Srwatson	.mpo_vnode_check_getextattr = mls_vnode_check_getextattr,
3049101099Srwatson	.mpo_vnode_check_link = mls_vnode_check_link,
3050172955Srwatson	.mpo_vnode_check_listextattr = mls_vnode_check_listextattr,
3051168976Srwatson	.mpo_vnode_check_lookup = mls_vnode_check_lookup,
3052101099Srwatson	.mpo_vnode_check_mmap = mls_vnode_check_mmap,
3053101099Srwatson	.mpo_vnode_check_open = mls_vnode_check_open,
3054101099Srwatson	.mpo_vnode_check_poll = mls_vnode_check_poll,
3055101099Srwatson	.mpo_vnode_check_read = mls_vnode_check_read,
3056172955Srwatson	.mpo_vnode_check_readdir = mls_vnode_check_readdir,
3057101099Srwatson	.mpo_vnode_check_readlink = mls_vnode_check_readlink,
3058101099Srwatson	.mpo_vnode_check_relabel = mls_vnode_check_relabel,
3059122524Srwatson	.mpo_vnode_check_rename_from = mls_vnode_check_rename_from,
3060168976Srwatson	.mpo_vnode_check_rename_to = mls_vnode_check_rename_to,
3061101099Srwatson	.mpo_vnode_check_revoke = mls_vnode_check_revoke,
3062172955Srwatson	.mpo_vnode_check_setacl = mls_vnode_check_setacl,
3063101099Srwatson	.mpo_vnode_check_setextattr = mls_vnode_check_setextattr,
3064101099Srwatson	.mpo_vnode_check_setflags = mls_vnode_check_setflags,
3065101099Srwatson	.mpo_vnode_check_setmode = mls_vnode_check_setmode,
3066101099Srwatson	.mpo_vnode_check_setowner = mls_vnode_check_setowner,
3067101099Srwatson	.mpo_vnode_check_setutimes = mls_vnode_check_setutimes,
3068101099Srwatson	.mpo_vnode_check_stat = mls_vnode_check_stat,
3069101099Srwatson	.mpo_vnode_check_unlink = mls_vnode_check_unlink,
3070101099Srwatson	.mpo_vnode_check_write = mls_vnode_check_write,
3071172955Srwatson	.mpo_vnode_copy_label = mls_copy_label,
3072168976Srwatson	.mpo_vnode_create_extattr = mls_vnode_create_extattr,
3073101099Srwatson	.mpo_vnode_destroy_label = mls_destroy_label,
3074101099Srwatson	.mpo_vnode_externalize_label = mls_externalize_label,
3075101099Srwatson	.mpo_vnode_init_label = mls_init_label,
3076172955Srwatson	.mpo_vnode_internalize_label = mls_internalize_label,
3077101099Srwatson	.mpo_vnode_relabel = mls_vnode_relabel,
3078101099Srwatson	.mpo_vnode_setlabel_extattr = mls_vnode_setlabel_extattr,
3079122524Srwatson};
3080168976Srwatson
3081101099SrwatsonMAC_POLICY_SET(&mls_ops, mac_mls, "TrustedBSD MAC/MLS",
3082172955Srwatson    MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mls_slot);
3083101099Srwatson