1101099Srwatson/*-
2225344Srwatson * Copyright (c) 1999-2002, 2007-2011 Robert N. M. Watson
3140629Srwatson * Copyright (c) 2001-2005 McAfee, Inc.
4172930Srwatson * Copyright (c) 2006 SPARTA, Inc.
5101099Srwatson * All rights reserved.
6101099Srwatson *
7101099Srwatson * This software was developed by Robert Watson for the TrustedBSD Project.
8101099Srwatson *
9140629Srwatson * This software was developed for the FreeBSD Project in part by McAfee
10140629Srwatson * Research, the Security Research Division of McAfee, Inc. under
11140629Srwatson * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
12140629Srwatson * CHATS research program.
13101099Srwatson *
14172930Srwatson * This software was enhanced by SPARTA ISSO under SPAWAR contract
15172930Srwatson * N66001-04-C-6019 ("SEFOS").
16172930Srwatson *
17225344Srwatson * This software was developed at the University of Cambridge Computer
18225344Srwatson * Laboratory with support from a grant from Google, Inc.
19225344Srwatson *
20101099Srwatson * Redistribution and use in source and binary forms, with or without
21101099Srwatson * modification, are permitted provided that the following conditions
22101099Srwatson * are met:
23101099Srwatson * 1. Redistributions of source code must retain the above copyright
24101099Srwatson *    notice, this list of conditions and the following disclaimer.
25101099Srwatson * 2. Redistributions in binary form must reproduce the above copyright
26101099Srwatson *    notice, this list of conditions and the following disclaimer in the
27101099Srwatson *    documentation and/or other materials provided with the distribution.
28101099Srwatson *
29101099Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
30101099Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31101099Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32101099Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
33101099Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34101099Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35101099Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36101099Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37101099Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38101099Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39101099Srwatson * SUCH DAMAGE.
40101099Srwatson *
41101099Srwatson * $FreeBSD$
42101099Srwatson */
43101099Srwatson
44101099Srwatson/*
45101099Srwatson * Developed by the TrustedBSD Project.
46168977Srwatson *
47101099Srwatson * MLS fixed label mandatory confidentiality policy.
48101099Srwatson */
49101099Srwatson
50101099Srwatson#include <sys/types.h>
51101099Srwatson#include <sys/param.h>
52101099Srwatson#include <sys/acl.h>
53101099Srwatson#include <sys/conf.h>
54105988Srwatson#include <sys/extattr.h>
55101099Srwatson#include <sys/kernel.h>
56164184Strhodes#include <sys/ksem.h>
57145076Scsjp#include <sys/mman.h>
58103183Sbde#include <sys/malloc.h>
59101099Srwatson#include <sys/mount.h>
60101099Srwatson#include <sys/proc.h>
61115497Srwatson#include <sys/sbuf.h>
62101099Srwatson#include <sys/systm.h>
63101099Srwatson#include <sys/sysproto.h>
64101099Srwatson#include <sys/sysent.h>
65105696Srwatson#include <sys/systm.h>
66101099Srwatson#include <sys/vnode.h>
67101099Srwatson#include <sys/file.h>
68101099Srwatson#include <sys/socket.h>
69101099Srwatson#include <sys/socketvar.h>
70101099Srwatson#include <sys/pipe.h>
71150340Sphk#include <sys/sx.h>
72101099Srwatson#include <sys/sysctl.h>
73140629Srwatson#include <sys/msg.h>
74140629Srwatson#include <sys/sem.h>
75140629Srwatson#include <sys/shm.h>
76101099Srwatson
77101099Srwatson#include <fs/devfs/devfs.h>
78101099Srwatson
79101099Srwatson#include <net/bpfdesc.h>
80101099Srwatson#include <net/if.h>
81101099Srwatson#include <net/if_types.h>
82101099Srwatson#include <net/if_var.h>
83101099Srwatson
84101099Srwatson#include <netinet/in.h>
85122875Srwatson#include <netinet/in_pcb.h>
86101099Srwatson#include <netinet/ip_var.h>
87101099Srwatson
88122879Srwatson#include <vm/uma.h>
89101099Srwatson#include <vm/vm.h>
90101099Srwatson
91165469Srwatson#include <security/mac/mac_policy.h>
92101099Srwatson#include <security/mac_mls/mac_mls.h>
93101099Srwatson
94101099SrwatsonSYSCTL_DECL(_security_mac);
95101099Srwatson
96248085Smariusstatic SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
97101099Srwatson    "TrustedBSD mac_mls policy controls");
98101099Srwatson
99172955Srwatsonstatic int	mls_label_size = sizeof(struct mac_mls);
100105988SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
101172955Srwatson    &mls_label_size, 0, "Size of struct mac_mls");
102105988Srwatson
103172955Srwatsonstatic int	mls_enabled = 1;
104172955SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW, &mls_enabled, 0,
105172955Srwatson    "Enforce MAC/MLS policy");
106172955SrwatsonTUNABLE_INT("security.mac.mls.enabled", &mls_enabled);
107101099Srwatson
108101099Srwatsonstatic int	destroyed_not_inited;
109101099SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
110101099Srwatson    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
111101099Srwatson
112105606Srwatsonstatic int	ptys_equal = 0;
113105606SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
114105606Srwatson    &ptys_equal, 0, "Label pty devices as mls/equal on create");
115105606SrwatsonTUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
116105606Srwatson
117105640Srwatsonstatic int	revocation_enabled = 0;
118101099SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
119105640Srwatson    &revocation_enabled, 0, "Revoke access to objects on relabel");
120105640SrwatsonTUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled);
121101099Srwatson
122105643Srwatsonstatic int	max_compartments = MAC_MLS_MAX_COMPARTMENTS;
123105643SrwatsonSYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
124105643Srwatson    &max_compartments, 0, "Maximum compartments the policy supports");
125105643Srwatson
126172955Srwatsonstatic int	mls_slot;
127172955Srwatson#define	SLOT(l)	((struct mac_mls *)mac_label_get((l), mls_slot))
128172955Srwatson#define	SLOT_SET(l, val) mac_label_set((l), mls_slot, (uintptr_t)(val))
129101099Srwatson
130122879Srwatsonstatic uma_zone_t	zone_mls;
131101099Srwatson
132105643Srwatsonstatic __inline int
133105643Srwatsonmls_bit_set_empty(u_char *set) {
134105643Srwatson	int i;
135105643Srwatson
136105643Srwatson	for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++)
137105643Srwatson		if (set[i] != 0)
138105643Srwatson			return (0);
139105643Srwatson	return (1);
140105643Srwatson}
141105643Srwatson
142101099Srwatsonstatic struct mac_mls *
143104514Srwatsonmls_alloc(int flag)
144101099Srwatson{
145101099Srwatson
146122879Srwatson	return (uma_zalloc(zone_mls, flag | M_ZERO));
147101099Srwatson}
148101099Srwatson
149101099Srwatsonstatic void
150172955Srwatsonmls_free(struct mac_mls *mm)
151101099Srwatson{
152101099Srwatson
153172955Srwatson	if (mm != NULL)
154172955Srwatson		uma_zfree(zone_mls, mm);
155101099Srwatson	else
156101099Srwatson		atomic_add_int(&destroyed_not_inited, 1);
157101099Srwatson}
158101099Srwatson
159101099Srwatsonstatic int
160172955Srwatsonmls_atmostflags(struct mac_mls *mm, int flags)
161105634Srwatson{
162105634Srwatson
163172955Srwatson	if ((mm->mm_flags & flags) != mm->mm_flags)
164105634Srwatson		return (EINVAL);
165105634Srwatson	return (0);
166105634Srwatson}
167105634Srwatson
168105634Srwatsonstatic int
169172955Srwatsonmls_dominate_element(struct mac_mls_element *a, struct mac_mls_element *b)
170101099Srwatson{
171105643Srwatson	int bit;
172101099Srwatson
173105736Srwatson	switch (a->mme_type) {
174101099Srwatson	case MAC_MLS_TYPE_EQUAL:
175101099Srwatson	case MAC_MLS_TYPE_HIGH:
176101099Srwatson		return (1);
177101099Srwatson
178101099Srwatson	case MAC_MLS_TYPE_LOW:
179101099Srwatson		switch (b->mme_type) {
180101099Srwatson		case MAC_MLS_TYPE_LEVEL:
181101099Srwatson		case MAC_MLS_TYPE_HIGH:
182101099Srwatson			return (0);
183101099Srwatson
184101099Srwatson		case MAC_MLS_TYPE_EQUAL:
185101099Srwatson		case MAC_MLS_TYPE_LOW:
186101099Srwatson			return (1);
187101099Srwatson
188101099Srwatson		default:
189172955Srwatson			panic("mls_dominate_element: b->mme_type invalid");
190101099Srwatson		}
191101099Srwatson
192101099Srwatson	case MAC_MLS_TYPE_LEVEL:
193101099Srwatson		switch (b->mme_type) {
194101099Srwatson		case MAC_MLS_TYPE_EQUAL:
195101099Srwatson		case MAC_MLS_TYPE_LOW:
196101099Srwatson			return (1);
197101099Srwatson
198101099Srwatson		case MAC_MLS_TYPE_HIGH:
199101099Srwatson			return (0);
200101099Srwatson
201101099Srwatson		case MAC_MLS_TYPE_LEVEL:
202105643Srwatson			for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++)
203105643Srwatson				if (!MAC_MLS_BIT_TEST(bit,
204105643Srwatson				    a->mme_compartments) &&
205105643Srwatson				    MAC_MLS_BIT_TEST(bit, b->mme_compartments))
206105643Srwatson					return (0);
207101099Srwatson			return (a->mme_level >= b->mme_level);
208101099Srwatson
209101099Srwatson		default:
210172955Srwatson			panic("mls_dominate_element: b->mme_type invalid");
211101099Srwatson		}
212101099Srwatson
213101099Srwatson	default:
214172955Srwatson		panic("mls_dominate_element: a->mme_type invalid");
215101099Srwatson	}
216101099Srwatson
217101099Srwatson	return (0);
218101099Srwatson}
219101099Srwatson
220101099Srwatsonstatic int
221172955Srwatsonmls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
222101099Srwatson{
223101099Srwatson
224172955Srwatson	return (mls_dominate_element(&rangeb->mm_rangehigh,
225101099Srwatson	    &rangea->mm_rangehigh) &&
226172955Srwatson	    mls_dominate_element(&rangea->mm_rangelow,
227101099Srwatson	    &rangeb->mm_rangelow));
228101099Srwatson}
229101099Srwatson
230101099Srwatsonstatic int
231172955Srwatsonmls_effective_in_range(struct mac_mls *effective, struct mac_mls *range)
232101099Srwatson{
233101099Srwatson
234132232Srwatson	KASSERT((effective->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
235172955Srwatson	    ("mls_effective_in_range: a not effective"));
236103750Srwatson	KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
237172955Srwatson	    ("mls_effective_in_range: b not range"));
238101099Srwatson
239172955Srwatson	return (mls_dominate_element(&range->mm_rangehigh,
240132232Srwatson	    &effective->mm_effective) &&
241172955Srwatson	    mls_dominate_element(&effective->mm_effective,
242101099Srwatson	    &range->mm_rangelow));
243101099Srwatson
244101099Srwatson	return (1);
245101099Srwatson}
246101099Srwatson
247101099Srwatsonstatic int
248172955Srwatsonmls_dominate_effective(struct mac_mls *a, struct mac_mls *b)
249101099Srwatson{
250132232Srwatson	KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
251172955Srwatson	    ("mls_dominate_effective: a not effective"));
252132232Srwatson	KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
253172955Srwatson	    ("mls_dominate_effective: b not effective"));
254101099Srwatson
255172955Srwatson	return (mls_dominate_element(&a->mm_effective, &b->mm_effective));
256101099Srwatson}
257101099Srwatson
258101099Srwatsonstatic int
259172955Srwatsonmls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
260101099Srwatson{
261101099Srwatson
262101099Srwatson	if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
263101099Srwatson	    b->mme_type == MAC_MLS_TYPE_EQUAL)
264101099Srwatson		return (1);
265101099Srwatson
266101099Srwatson	return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
267101099Srwatson}
268101099Srwatson
269101099Srwatsonstatic int
270172955Srwatsonmls_equal_effective(struct mac_mls *a, struct mac_mls *b)
271101099Srwatson{
272101099Srwatson
273132232Srwatson	KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
274172955Srwatson	    ("mls_equal_effective: a not effective"));
275132232Srwatson	KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
276172955Srwatson	    ("mls_equal_effective: b not effective"));
277101099Srwatson
278172955Srwatson	return (mls_equal_element(&a->mm_effective, &b->mm_effective));
279101099Srwatson}
280101099Srwatson
281101099Srwatsonstatic int
282172955Srwatsonmls_contains_equal(struct mac_mls *mm)
283105634Srwatson{
284105634Srwatson
285172955Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
286172955Srwatson		if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
287105634Srwatson			return (1);
288105634Srwatson
289172955Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
290172955Srwatson		if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL)
291105634Srwatson			return (1);
292172955Srwatson		if (mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
293105634Srwatson			return (1);
294105634Srwatson	}
295105634Srwatson
296105634Srwatson	return (0);
297105634Srwatson}
298105634Srwatson
299105634Srwatsonstatic int
300172955Srwatsonmls_subject_privileged(struct mac_mls *mm)
301105634Srwatson{
302105634Srwatson
303172955Srwatson	KASSERT((mm->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH,
304172955Srwatson	    ("mls_subject_privileged: subject doesn't have both labels"));
305105634Srwatson
306132232Srwatson	/* If the effective is EQUAL, it's ok. */
307172955Srwatson	if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
308105634Srwatson		return (0);
309105634Srwatson
310105634Srwatson	/* If either range endpoint is EQUAL, it's ok. */
311172955Srwatson	if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL ||
312172955Srwatson	    mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
313105634Srwatson		return (0);
314105634Srwatson
315105634Srwatson	/* If the range is low-high, it's ok. */
316172955Srwatson	if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW &&
317172955Srwatson	    mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH)
318105634Srwatson		return (0);
319105634Srwatson
320105634Srwatson	/* It's not ok. */
321105634Srwatson	return (EPERM);
322105634Srwatson}
323105634Srwatson
324105634Srwatsonstatic int
325172955Srwatsonmls_valid(struct mac_mls *mm)
326101099Srwatson{
327101099Srwatson
328172955Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
329172955Srwatson		switch (mm->mm_effective.mme_type) {
330101099Srwatson		case MAC_MLS_TYPE_LEVEL:
331101099Srwatson			break;
332101099Srwatson
333101099Srwatson		case MAC_MLS_TYPE_EQUAL:
334101099Srwatson		case MAC_MLS_TYPE_HIGH:
335101099Srwatson		case MAC_MLS_TYPE_LOW:
336172955Srwatson			if (mm->mm_effective.mme_level != 0 ||
337105643Srwatson			    !MAC_MLS_BIT_SET_EMPTY(
338172955Srwatson			    mm->mm_effective.mme_compartments))
339101099Srwatson				return (EINVAL);
340101099Srwatson			break;
341101099Srwatson
342101099Srwatson		default:
343101099Srwatson			return (EINVAL);
344101099Srwatson		}
345101099Srwatson	} else {
346172955Srwatson		if (mm->mm_effective.mme_type != MAC_MLS_TYPE_UNDEF)
347101099Srwatson			return (EINVAL);
348101099Srwatson	}
349101099Srwatson
350172955Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
351172955Srwatson		switch (mm->mm_rangelow.mme_type) {
352101099Srwatson		case MAC_MLS_TYPE_LEVEL:
353101099Srwatson			break;
354101099Srwatson
355101099Srwatson		case MAC_MLS_TYPE_EQUAL:
356101099Srwatson		case MAC_MLS_TYPE_HIGH:
357101099Srwatson		case MAC_MLS_TYPE_LOW:
358172955Srwatson			if (mm->mm_rangelow.mme_level != 0 ||
359105643Srwatson			    !MAC_MLS_BIT_SET_EMPTY(
360172955Srwatson			    mm->mm_rangelow.mme_compartments))
361101099Srwatson				return (EINVAL);
362101099Srwatson			break;
363101099Srwatson
364101099Srwatson		default:
365101099Srwatson			return (EINVAL);
366101099Srwatson		}
367101099Srwatson
368172955Srwatson		switch (mm->mm_rangehigh.mme_type) {
369101099Srwatson		case MAC_MLS_TYPE_LEVEL:
370101099Srwatson			break;
371101099Srwatson
372101099Srwatson		case MAC_MLS_TYPE_EQUAL:
373101099Srwatson		case MAC_MLS_TYPE_HIGH:
374101099Srwatson		case MAC_MLS_TYPE_LOW:
375172955Srwatson			if (mm->mm_rangehigh.mme_level != 0 ||
376105643Srwatson			    !MAC_MLS_BIT_SET_EMPTY(
377172955Srwatson			    mm->mm_rangehigh.mme_compartments))
378101099Srwatson				return (EINVAL);
379101099Srwatson			break;
380101099Srwatson
381101099Srwatson		default:
382101099Srwatson			return (EINVAL);
383101099Srwatson		}
384172955Srwatson		if (!mls_dominate_element(&mm->mm_rangehigh,
385172955Srwatson		    &mm->mm_rangelow))
386101099Srwatson			return (EINVAL);
387101099Srwatson	} else {
388172955Srwatson		if (mm->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
389172955Srwatson		    mm->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
390101099Srwatson			return (EINVAL);
391101099Srwatson	}
392101099Srwatson
393101099Srwatson	return (0);
394101099Srwatson}
395101099Srwatson
396101099Srwatsonstatic void
397172955Srwatsonmls_set_range(struct mac_mls *mm, u_short typelow, u_short levellow,
398172955Srwatson    u_char *compartmentslow, u_short typehigh, u_short levelhigh,
399172955Srwatson    u_char *compartmentshigh)
400101099Srwatson{
401101099Srwatson
402172955Srwatson	mm->mm_rangelow.mme_type = typelow;
403172955Srwatson	mm->mm_rangelow.mme_level = levellow;
404105643Srwatson	if (compartmentslow != NULL)
405181217Srwatson		memcpy(mm->mm_rangelow.mme_compartments, compartmentslow,
406172955Srwatson		    sizeof(mm->mm_rangelow.mme_compartments));
407172955Srwatson	mm->mm_rangehigh.mme_type = typehigh;
408172955Srwatson	mm->mm_rangehigh.mme_level = levelhigh;
409105643Srwatson	if (compartmentshigh != NULL)
410181217Srwatson		memcpy(mm->mm_rangehigh.mme_compartments, compartmentshigh,
411172955Srwatson		    sizeof(mm->mm_rangehigh.mme_compartments));
412172955Srwatson	mm->mm_flags |= MAC_MLS_FLAG_RANGE;
413101099Srwatson}
414101099Srwatson
415101099Srwatsonstatic void
416172955Srwatsonmls_set_effective(struct mac_mls *mm, u_short type, u_short level,
417105643Srwatson    u_char *compartments)
418101099Srwatson{
419101099Srwatson
420172955Srwatson	mm->mm_effective.mme_type = type;
421172955Srwatson	mm->mm_effective.mme_level = level;
422105643Srwatson	if (compartments != NULL)
423172955Srwatson		memcpy(mm->mm_effective.mme_compartments, compartments,
424172955Srwatson		    sizeof(mm->mm_effective.mme_compartments));
425172955Srwatson	mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
426101099Srwatson}
427101099Srwatson
428101099Srwatsonstatic void
429172955Srwatsonmls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
430101099Srwatson{
431105643Srwatson
432101099Srwatson	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
433172955Srwatson	    ("mls_copy_range: labelfrom not range"));
434101099Srwatson
435101099Srwatson	labelto->mm_rangelow = labelfrom->mm_rangelow;
436101099Srwatson	labelto->mm_rangehigh = labelfrom->mm_rangehigh;
437101099Srwatson	labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
438101099Srwatson}
439101099Srwatson
440101099Srwatsonstatic void
441172955Srwatsonmls_copy_effective(struct mac_mls *labelfrom, struct mac_mls *labelto)
442101099Srwatson{
443101099Srwatson
444132232Srwatson	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
445172955Srwatson	    ("mls_copy_effective: labelfrom not effective"));
446101099Srwatson
447132232Srwatson	labelto->mm_effective = labelfrom->mm_effective;
448132232Srwatson	labelto->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
449101099Srwatson}
450101099Srwatson
451105656Srwatsonstatic void
452172955Srwatsonmls_copy(struct mac_mls *source, struct mac_mls *dest)
453105656Srwatson{
454105656Srwatson
455132232Srwatson	if (source->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
456172955Srwatson		mls_copy_effective(source, dest);
457105656Srwatson	if (source->mm_flags & MAC_MLS_FLAG_RANGE)
458172955Srwatson		mls_copy_range(source, dest);
459105656Srwatson}
460105656Srwatson
461101099Srwatson/*
462101099Srwatson * Policy module operations.
463101099Srwatson */
464101099Srwatsonstatic void
465172955Srwatsonmls_init(struct mac_policy_conf *conf)
466101099Srwatson{
467101099Srwatson
468122879Srwatson	zone_mls = uma_zcreate("mac_mls", sizeof(struct mac_mls), NULL,
469122879Srwatson	    NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
470101099Srwatson}
471101099Srwatson
472101099Srwatson/*
473101099Srwatson * Label operations.
474101099Srwatson */
475101099Srwatsonstatic void
476172955Srwatsonmls_init_label(struct label *label)
477101099Srwatson{
478101099Srwatson
479132781Skan	SLOT_SET(label, mls_alloc(M_WAITOK));
480101099Srwatson}
481101099Srwatson
482101099Srwatsonstatic int
483172955Srwatsonmls_init_label_waitcheck(struct label *label, int flag)
484101099Srwatson{
485101099Srwatson
486132781Skan	SLOT_SET(label, mls_alloc(flag));
487101099Srwatson	if (SLOT(label) == NULL)
488101099Srwatson		return (ENOMEM);
489101099Srwatson
490101099Srwatson	return (0);
491101099Srwatson}
492101099Srwatson
493101099Srwatsonstatic void
494172955Srwatsonmls_destroy_label(struct label *label)
495101099Srwatson{
496101099Srwatson
497101099Srwatson	mls_free(SLOT(label));
498132781Skan	SLOT_SET(label, NULL);
499101099Srwatson}
500101099Srwatson
501105696Srwatson/*
502172955Srwatson * mls_element_to_string() accepts an sbuf and MLS element.  It converts the
503172955Srwatson * MLS element to a string and stores the result in the sbuf; if there isn't
504172955Srwatson * space in the sbuf, -1 is returned.
505105696Srwatson */
506115497Srwatsonstatic int
507172955Srwatsonmls_element_to_string(struct sbuf *sb, struct mac_mls_element *element)
508105696Srwatson{
509115497Srwatson	int i, first;
510105696Srwatson
511105696Srwatson	switch (element->mme_type) {
512105696Srwatson	case MAC_MLS_TYPE_HIGH:
513115497Srwatson		return (sbuf_printf(sb, "high"));
514105696Srwatson
515105696Srwatson	case MAC_MLS_TYPE_LOW:
516115497Srwatson		return (sbuf_printf(sb, "low"));
517105696Srwatson
518105696Srwatson	case MAC_MLS_TYPE_EQUAL:
519115497Srwatson		return (sbuf_printf(sb, "equal"));
520105696Srwatson
521105696Srwatson	case MAC_MLS_TYPE_LEVEL:
522115497Srwatson		if (sbuf_printf(sb, "%d", element->mme_level) == -1)
523115497Srwatson			return (-1);
524115497Srwatson
525115497Srwatson		first = 1;
526115497Srwatson		for (i = 1; i <= MAC_MLS_MAX_COMPARTMENTS; i++) {
527115497Srwatson			if (MAC_MLS_BIT_TEST(i, element->mme_compartments)) {
528115497Srwatson				if (first) {
529115497Srwatson					if (sbuf_putc(sb, ':') == -1)
530115497Srwatson						return (-1);
531115497Srwatson					if (sbuf_printf(sb, "%d", i) == -1)
532115497Srwatson						return (-1);
533115497Srwatson					first = 0;
534115497Srwatson				} else {
535115497Srwatson					if (sbuf_printf(sb, "+%d", i) == -1)
536115497Srwatson						return (-1);
537115497Srwatson				}
538115497Srwatson			}
539105696Srwatson		}
540115497Srwatson		return (0);
541105696Srwatson
542105696Srwatson	default:
543172955Srwatson		panic("mls_element_to_string: invalid type (%d)",
544105696Srwatson		    element->mme_type);
545105696Srwatson	}
546105696Srwatson}
547105696Srwatson
548115497Srwatson/*
549172955Srwatson * mls_to_string() converts an MLS label to a string, and places the results
550172955Srwatson * in the passed sbuf.  It returns 0 on success, or EINVAL if there isn't
551172955Srwatson * room in the sbuf.  Note: the sbuf will be modified even in a failure case,
552172955Srwatson * so the caller may need to revert the sbuf by restoring the offset if
553172955Srwatson * that's undesired.
554115497Srwatson */
555115497Srwatsonstatic int
556172955Srwatsonmls_to_string(struct sbuf *sb, struct mac_mls *mm)
557105696Srwatson{
558105696Srwatson
559172955Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
560172955Srwatson		if (mls_element_to_string(sb, &mm->mm_effective) == -1)
561105696Srwatson			return (EINVAL);
562105696Srwatson	}
563105696Srwatson
564172955Srwatson	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
565116701Srwatson		if (sbuf_putc(sb, '(') == -1)
566105696Srwatson			return (EINVAL);
567105696Srwatson
568172955Srwatson		if (mls_element_to_string(sb, &mm->mm_rangelow) == -1)
569105696Srwatson			return (EINVAL);
570105696Srwatson
571116701Srwatson		if (sbuf_putc(sb, '-') == -1)
572105696Srwatson			return (EINVAL);
573105696Srwatson
574172955Srwatson		if (mls_element_to_string(sb, &mm->mm_rangehigh) == -1)
575105696Srwatson			return (EINVAL);
576105696Srwatson
577116701Srwatson		if (sbuf_putc(sb, ')') == -1)
578105696Srwatson			return (EINVAL);
579105696Srwatson	}
580105696Srwatson
581105696Srwatson	return (0);
582105696Srwatson}
583105696Srwatson
584101099Srwatsonstatic int
585172955Srwatsonmls_externalize_label(struct label *label, char *element_name,
586116701Srwatson    struct sbuf *sb, int *claimed)
587101099Srwatson{
588172955Srwatson	struct mac_mls *mm;
589101099Srwatson
590105696Srwatson	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
591105696Srwatson		return (0);
592105696Srwatson
593105696Srwatson	(*claimed)++;
594105696Srwatson
595172955Srwatson	mm = SLOT(label);
596101099Srwatson
597172955Srwatson	return (mls_to_string(sb, mm));
598105696Srwatson}
599105696Srwatson
600105696Srwatsonstatic int
601172955Srwatsonmls_parse_element(struct mac_mls_element *element, char *string)
602101099Srwatson{
603115395Srwatson	char *compartment, *end, *level;
604115395Srwatson	int value;
605105696Srwatson
606172955Srwatson	if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) {
607105696Srwatson		element->mme_type = MAC_MLS_TYPE_HIGH;
608105696Srwatson		element->mme_level = MAC_MLS_TYPE_UNDEF;
609172955Srwatson	} else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) {
610105696Srwatson		element->mme_type = MAC_MLS_TYPE_LOW;
611105696Srwatson		element->mme_level = MAC_MLS_TYPE_UNDEF;
612105696Srwatson	} else if (strcmp(string, "equal") == 0 ||
613105696Srwatson	    strcmp(string, "eq") == 0) {
614105696Srwatson		element->mme_type = MAC_MLS_TYPE_EQUAL;
615105696Srwatson		element->mme_level = MAC_MLS_TYPE_UNDEF;
616105696Srwatson	} else {
617115395Srwatson		element->mme_type = MAC_MLS_TYPE_LEVEL;
618105696Srwatson
619115395Srwatson		/*
620115395Srwatson		 * Numeric level piece of the element.
621115395Srwatson		 */
622115395Srwatson		level = strsep(&string, ":");
623115395Srwatson		value = strtol(level, &end, 10);
624115395Srwatson		if (end == level || *end != '\0')
625105696Srwatson			return (EINVAL);
626115395Srwatson		if (value < 0 || value > 65535)
627115395Srwatson			return (EINVAL);
628115395Srwatson		element->mme_level = value;
629105696Srwatson
630115395Srwatson		/*
631172955Srwatson		 * Optional compartment piece of the element.  If none are
632172955Srwatson		 * included, we assume that the label has no compartments.
633115395Srwatson		 */
634115395Srwatson		if (string == NULL)
635115395Srwatson			return (0);
636115395Srwatson		if (*string == '\0')
637115395Srwatson			return (0);
638105696Srwatson
639115395Srwatson		while ((compartment = strsep(&string, "+")) != NULL) {
640115395Srwatson			value = strtol(compartment, &end, 10);
641115395Srwatson			if (compartment == end || *end != '\0')
642105696Srwatson				return (EINVAL);
643115395Srwatson			if (value < 1 || value > MAC_MLS_MAX_COMPARTMENTS)
644105696Srwatson				return (EINVAL);
645115395Srwatson			MAC_MLS_BIT_SET(value, element->mme_compartments);
646105696Srwatson		}
647105696Srwatson	}
648105696Srwatson
649105696Srwatson	return (0);
650105696Srwatson}
651105696Srwatson
652105696Srwatson/*
653172955Srwatson * Note: destructively consumes the string, make a local copy before calling
654172955Srwatson * if that's a problem.
655105696Srwatson */
656105696Srwatsonstatic int
657172955Srwatsonmls_parse(struct mac_mls *mm, char *string)
658105696Srwatson{
659132232Srwatson	char *rangehigh, *rangelow, *effective;
660101099Srwatson	int error;
661101099Srwatson
662132232Srwatson	effective = strsep(&string, "(");
663132232Srwatson	if (*effective == '\0')
664132232Srwatson		effective = NULL;
665115395Srwatson
666115395Srwatson	if (string != NULL) {
667115395Srwatson		rangelow = strsep(&string, "-");
668115395Srwatson		if (string == NULL)
669105696Srwatson			return (EINVAL);
670115395Srwatson		rangehigh = strsep(&string, ")");
671115395Srwatson		if (string == NULL)
672105696Srwatson			return (EINVAL);
673115395Srwatson		if (*string != '\0')
674105696Srwatson			return (EINVAL);
675115414Srwatson	} else {
676115414Srwatson		rangelow = NULL;
677115414Srwatson		rangehigh = NULL;
678105696Srwatson	}
679115395Srwatson
680105696Srwatson	KASSERT((rangelow != NULL && rangehigh != NULL) ||
681105696Srwatson	    (rangelow == NULL && rangehigh == NULL),
682172955Srwatson	    ("mls_parse: range mismatch"));
683101099Srwatson
684172955Srwatson	bzero(mm, sizeof(*mm));
685132232Srwatson	if (effective != NULL) {
686172955Srwatson		error = mls_parse_element(&mm->mm_effective, effective);
687105696Srwatson		if (error)
688105696Srwatson			return (error);
689172955Srwatson		mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
690105696Srwatson	}
691105696Srwatson
692105696Srwatson	if (rangelow != NULL) {
693181217Srwatson		error = mls_parse_element(&mm->mm_rangelow, rangelow);
694105696Srwatson		if (error)
695105696Srwatson			return (error);
696181217Srwatson		error = mls_parse_element(&mm->mm_rangehigh, rangehigh);
697105696Srwatson		if (error)
698105696Srwatson			return (error);
699172955Srwatson		mm->mm_flags |= MAC_MLS_FLAG_RANGE;
700105696Srwatson	}
701105696Srwatson
702172955Srwatson	error = mls_valid(mm);
703101099Srwatson	if (error)
704101099Srwatson		return (error);
705101099Srwatson
706105696Srwatson	return (0);
707105696Srwatson}
708101099Srwatson
709105696Srwatsonstatic int
710172955Srwatsonmls_internalize_label(struct label *label, char *element_name,
711105696Srwatson    char *element_data, int *claimed)
712105696Srwatson{
713172955Srwatson	struct mac_mls *mm, mm_temp;
714105696Srwatson	int error;
715105696Srwatson
716105696Srwatson	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
717105696Srwatson		return (0);
718105696Srwatson
719105696Srwatson	(*claimed)++;
720105696Srwatson
721172955Srwatson	error = mls_parse(&mm_temp, element_data);
722105696Srwatson	if (error)
723105696Srwatson		return (error);
724105696Srwatson
725172955Srwatson	mm = SLOT(label);
726172955Srwatson	*mm = mm_temp;
727105696Srwatson
728101099Srwatson	return (0);
729101099Srwatson}
730101099Srwatson
731105696Srwatsonstatic void
732172955Srwatsonmls_copy_label(struct label *src, struct label *dest)
733105696Srwatson{
734105696Srwatson
735105696Srwatson	*SLOT(dest) = *SLOT(src);
736105696Srwatson}
737105696Srwatson
738101099Srwatson/*
739173138Srwatson * Object-specific entry point implementations are sorted alphabetically by
740173138Srwatson * object type name and then by operation.
741101099Srwatson */
742173138Srwatsonstatic int
743173138Srwatsonmls_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel,
744173138Srwatson     struct ifnet *ifp, struct label *ifplabel)
745173138Srwatson{
746173138Srwatson	struct mac_mls *a, *b;
747173138Srwatson
748173138Srwatson	if (!mls_enabled)
749173138Srwatson		return (0);
750173138Srwatson
751173138Srwatson	a = SLOT(dlabel);
752173138Srwatson	b = SLOT(ifplabel);
753173138Srwatson
754173138Srwatson	if (mls_equal_effective(a, b))
755173138Srwatson		return (0);
756173138Srwatson	return (EACCES);
757173138Srwatson}
758173138Srwatson
759101099Srwatsonstatic void
760173138Srwatsonmls_bpfdesc_create(struct ucred *cred, struct bpf_d *d, struct label *dlabel)
761173138Srwatson{
762173138Srwatson	struct mac_mls *source, *dest;
763173138Srwatson
764173138Srwatson	source = SLOT(cred->cr_label);
765173138Srwatson	dest = SLOT(dlabel);
766173138Srwatson
767173138Srwatson	mls_copy_effective(source, dest);
768173138Srwatson}
769173138Srwatson
770173138Srwatsonstatic void
771173138Srwatsonmls_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel,
772173138Srwatson    struct mbuf *m, struct label *mlabel)
773173138Srwatson{
774173138Srwatson	struct mac_mls *source, *dest;
775173138Srwatson
776173138Srwatson	source = SLOT(dlabel);
777173138Srwatson	dest = SLOT(mlabel);
778173138Srwatson
779173138Srwatson	mls_copy_effective(source, dest);
780173138Srwatson}
781173138Srwatson
782184407Srwatsonstatic void
783184407Srwatsonmls_cred_associate_nfsd(struct ucred *cred)
784184407Srwatson{
785184407Srwatson	struct mac_mls *label;
786184407Srwatson
787184407Srwatson	label = SLOT(cred->cr_label);
788184407Srwatson	mls_set_effective(label, MAC_MLS_TYPE_LOW, 0, NULL);
789184407Srwatson	mls_set_range(label, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
790184407Srwatson	    NULL);
791184407Srwatson}
792184407Srwatson
793173138Srwatsonstatic int
794173138Srwatsonmls_cred_check_relabel(struct ucred *cred, struct label *newlabel)
795173138Srwatson{
796173138Srwatson	struct mac_mls *subj, *new;
797173138Srwatson	int error;
798173138Srwatson
799173138Srwatson	subj = SLOT(cred->cr_label);
800173138Srwatson	new = SLOT(newlabel);
801173138Srwatson
802173138Srwatson	/*
803173138Srwatson	 * If there is an MLS label update for the credential, it may be an
804173138Srwatson	 * update of effective, range, or both.
805173138Srwatson	 */
806173138Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
807173138Srwatson	if (error)
808173138Srwatson		return (error);
809173138Srwatson
810173138Srwatson	/*
811173138Srwatson	 * If the MLS label is to be changed, authorize as appropriate.
812173138Srwatson	 */
813173138Srwatson	if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
814173138Srwatson		/*
815173138Srwatson		 * If the change request modifies both the MLS label
816173138Srwatson		 * effective and range, check that the new effective will be
817173138Srwatson		 * in the new range.
818173138Srwatson		 */
819173138Srwatson		if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) ==
820173138Srwatson		    MAC_MLS_FLAGS_BOTH && !mls_effective_in_range(new, new))
821173138Srwatson			return (EINVAL);
822173138Srwatson
823173138Srwatson		/*
824173138Srwatson		 * To change the MLS effective label on a credential, the new
825173138Srwatson		 * effective label must be in the current range.
826173138Srwatson		 */
827173138Srwatson		if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE &&
828173138Srwatson		    !mls_effective_in_range(new, subj))
829173138Srwatson			return (EPERM);
830173138Srwatson
831173138Srwatson		/*
832173138Srwatson		 * To change the MLS range label on a credential, the new
833173138Srwatson		 * range must be in the current range.
834173138Srwatson		 */
835173138Srwatson		if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
836173138Srwatson		    !mls_range_in_range(new, subj))
837173138Srwatson			return (EPERM);
838173138Srwatson
839173138Srwatson		/*
840173138Srwatson		 * To have EQUAL in any component of the new credential MLS
841173138Srwatson		 * label, the subject must already have EQUAL in their label.
842173138Srwatson		 */
843173138Srwatson		if (mls_contains_equal(new)) {
844173138Srwatson			error = mls_subject_privileged(subj);
845173138Srwatson			if (error)
846173138Srwatson				return (error);
847173138Srwatson		}
848173138Srwatson	}
849173138Srwatson
850173138Srwatson	return (0);
851173138Srwatson}
852173138Srwatson
853173138Srwatsonstatic int
854173138Srwatsonmls_cred_check_visible(struct ucred *cr1, struct ucred *cr2)
855173138Srwatson{
856173138Srwatson	struct mac_mls *subj, *obj;
857173138Srwatson
858173138Srwatson	if (!mls_enabled)
859173138Srwatson		return (0);
860173138Srwatson
861173138Srwatson	subj = SLOT(cr1->cr_label);
862173138Srwatson	obj = SLOT(cr2->cr_label);
863173138Srwatson
864173138Srwatson	/* XXX: range */
865173138Srwatson	if (!mls_dominate_effective(subj, obj))
866173138Srwatson		return (ESRCH);
867173138Srwatson
868173138Srwatson	return (0);
869173138Srwatson}
870173138Srwatson
871173138Srwatsonstatic void
872184407Srwatsonmls_cred_create_init(struct ucred *cred)
873184407Srwatson{
874184407Srwatson	struct mac_mls *dest;
875184407Srwatson
876184407Srwatson	dest = SLOT(cred->cr_label);
877184407Srwatson
878184407Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_LOW, 0, NULL);
879184407Srwatson	mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
880184407Srwatson	    NULL);
881184407Srwatson}
882184407Srwatson
883184407Srwatsonstatic void
884184407Srwatsonmls_cred_create_swapper(struct ucred *cred)
885184407Srwatson{
886184407Srwatson	struct mac_mls *dest;
887184407Srwatson
888184407Srwatson	dest = SLOT(cred->cr_label);
889184407Srwatson
890184407Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
891184407Srwatson	mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
892184407Srwatson	    NULL);
893184407Srwatson}
894184407Srwatson
895184407Srwatsonstatic void
896173138Srwatsonmls_cred_relabel(struct ucred *cred, struct label *newlabel)
897173138Srwatson{
898173138Srwatson	struct mac_mls *source, *dest;
899173138Srwatson
900173138Srwatson	source = SLOT(newlabel);
901173138Srwatson	dest = SLOT(cred->cr_label);
902173138Srwatson
903173138Srwatson	mls_copy(source, dest);
904173138Srwatson}
905173138Srwatson
906173138Srwatsonstatic void
907172955Srwatsonmls_devfs_create_device(struct ucred *cred, struct mount *mp,
908168976Srwatson    struct cdev *dev, struct devfs_dirent *de, struct label *delabel)
909101099Srwatson{
910172955Srwatson	struct mac_mls *mm;
911232405Sed	const char *dn;
912101099Srwatson	int mls_type;
913101099Srwatson
914172955Srwatson	mm = SLOT(delabel);
915232405Sed	dn = devtoname(dev);
916232405Sed	if (strcmp(dn, "null") == 0 ||
917232405Sed	    strcmp(dn, "zero") == 0 ||
918232405Sed	    strcmp(dn, "random") == 0 ||
919232405Sed	    strncmp(dn, "fd/", strlen("fd/")) == 0)
920101099Srwatson		mls_type = MAC_MLS_TYPE_EQUAL;
921232405Sed	else if (strcmp(dn, "kmem") == 0 ||
922232405Sed	    strcmp(dn, "mem") == 0)
923101099Srwatson		mls_type = MAC_MLS_TYPE_HIGH;
924105606Srwatson	else if (ptys_equal &&
925232405Sed	    (strncmp(dn, "ttyp", strlen("ttyp")) == 0 ||
926232405Sed	    strncmp(dn, "pts/", strlen("pts/")) == 0 ||
927232405Sed	    strncmp(dn, "ptyp", strlen("ptyp")) == 0))
928105606Srwatson		mls_type = MAC_MLS_TYPE_EQUAL;
929101099Srwatson	else
930101099Srwatson		mls_type = MAC_MLS_TYPE_LOW;
931172955Srwatson	mls_set_effective(mm, mls_type, 0, NULL);
932101099Srwatson}
933101099Srwatson
934101099Srwatsonstatic void
935172955Srwatsonmls_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
936172955Srwatson    struct devfs_dirent *de, struct label *delabel)
937101099Srwatson{
938172955Srwatson	struct mac_mls *mm;
939101099Srwatson
940172955Srwatson	mm = SLOT(delabel);
941172955Srwatson	mls_set_effective(mm, MAC_MLS_TYPE_LOW, 0, NULL);
942101099Srwatson}
943101099Srwatson
944101099Srwatsonstatic void
945172955Srwatsonmls_devfs_create_symlink(struct ucred *cred, struct mount *mp,
946107698Srwatson    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
947122563Srwatson    struct label *delabel)
948104535Srwatson{
949104535Srwatson	struct mac_mls *source, *dest;
950104535Srwatson
951122524Srwatson	source = SLOT(cred->cr_label);
952104535Srwatson	dest = SLOT(delabel);
953104535Srwatson
954172955Srwatson	mls_copy_effective(source, dest);
955104535Srwatson}
956104535Srwatson
957104535Srwatsonstatic void
958172955Srwatsonmls_devfs_update(struct mount *mp, struct devfs_dirent *de,
959168976Srwatson    struct label *delabel, struct vnode *vp, struct label *vplabel)
960101099Srwatson{
961101099Srwatson	struct mac_mls *source, *dest;
962101099Srwatson
963168976Srwatson	source = SLOT(vplabel);
964168976Srwatson	dest = SLOT(delabel);
965101099Srwatson
966172955Srwatson	mls_copy_effective(source, dest);
967101099Srwatson}
968101099Srwatson
969101099Srwatsonstatic void
970172955Srwatsonmls_devfs_vnode_associate(struct mount *mp, struct label *mplabel,
971105988Srwatson    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
972168976Srwatson    struct label *vplabel)
973101099Srwatson{
974101099Srwatson	struct mac_mls *source, *dest;
975101099Srwatson
976105988Srwatson	source = SLOT(delabel);
977168976Srwatson	dest = SLOT(vplabel);
978101099Srwatson
979172955Srwatson	mls_copy_effective(source, dest);
980101099Srwatson}
981101099Srwatson
982101099Srwatsonstatic int
983173138Srwatsonmls_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp,
984173138Srwatson    struct label *ifplabel, struct label *newlabel)
985101099Srwatson{
986173138Srwatson	struct mac_mls *subj, *new;
987173138Srwatson	int error;
988101099Srwatson
989173138Srwatson	subj = SLOT(cred->cr_label);
990173138Srwatson	new = SLOT(newlabel);
991101099Srwatson
992173138Srwatson	/*
993173138Srwatson	 * If there is an MLS label update for the interface, it may be an
994173138Srwatson	 * update of effective, range, or both.
995173138Srwatson	 */
996173138Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
997173138Srwatson	if (error)
998101099Srwatson		return (error);
999101099Srwatson
1000173138Srwatson	/*
1001173138Srwatson	 * Relabeling network interfaces requires MLS privilege.
1002173138Srwatson	 */
1003175747Srwatson	return (mls_subject_privileged(subj));
1004101099Srwatson}
1005101099Srwatson
1006105988Srwatsonstatic int
1007173138Srwatsonmls_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel,
1008173138Srwatson    struct mbuf *m, struct label *mlabel)
1009105988Srwatson{
1010173138Srwatson	struct mac_mls *p, *i;
1011105988Srwatson
1012173138Srwatson	if (!mls_enabled)
1013105988Srwatson		return (0);
1014105988Srwatson
1015173138Srwatson	p = SLOT(mlabel);
1016173138Srwatson	i = SLOT(ifplabel);
1017105988Srwatson
1018173138Srwatson	return (mls_effective_in_range(p, i) ? 0 : EACCES);
1019105988Srwatson}
1020105988Srwatson
1021101099Srwatsonstatic void
1022173138Srwatsonmls_ifnet_create(struct ifnet *ifp, struct label *ifplabel)
1023122875Srwatson{
1024173138Srwatson	struct mac_mls *dest;
1025173138Srwatson	int type;
1026122875Srwatson
1027173138Srwatson	dest = SLOT(ifplabel);
1028122875Srwatson
1029173138Srwatson	if (ifp->if_type == IFT_LOOP)
1030173138Srwatson		type = MAC_MLS_TYPE_EQUAL;
1031173138Srwatson	else
1032173138Srwatson		type = MAC_MLS_TYPE_LOW;
1033173138Srwatson
1034173138Srwatson	mls_set_effective(dest, type, 0, NULL);
1035173138Srwatson	mls_set_range(dest, type, 0, NULL, type, 0, NULL);
1036122875Srwatson}
1037122875Srwatson
1038122875Srwatsonstatic void
1039173138Srwatsonmls_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel,
1040168976Srwatson    struct mbuf *m, struct label *mlabel)
1041101099Srwatson{
1042101099Srwatson	struct mac_mls *source, *dest;
1043101099Srwatson
1044173138Srwatson	source = SLOT(ifplabel);
1045168976Srwatson	dest = SLOT(mlabel);
1046101099Srwatson
1047172955Srwatson	mls_copy_effective(source, dest);
1048101099Srwatson}
1049101099Srwatson
1050101099Srwatsonstatic void
1051173138Srwatsonmls_ifnet_relabel(struct ucred *cred, struct ifnet *ifp,
1052173138Srwatson    struct label *ifplabel, struct label *newlabel)
1053101099Srwatson{
1054101099Srwatson	struct mac_mls *source, *dest;
1055101099Srwatson
1056173138Srwatson	source = SLOT(newlabel);
1057173138Srwatson	dest = SLOT(ifplabel);
1058101099Srwatson
1059173138Srwatson	mls_copy(source, dest);
1060101099Srwatson}
1061101099Srwatson
1062173138Srwatsonstatic int
1063173138Srwatsonmls_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel,
1064173138Srwatson    struct mbuf *m, struct label *mlabel)
1065101099Srwatson{
1066173138Srwatson	struct mac_mls *p, *i;
1067101099Srwatson
1068173138Srwatson	if (!mls_enabled)
1069173138Srwatson		return (0);
1070101099Srwatson
1071173138Srwatson	p = SLOT(mlabel);
1072173138Srwatson	i = SLOT(inplabel);
1073173138Srwatson
1074173138Srwatson	return (mls_equal_effective(p, i) ? 0 : EACCES);
1075101099Srwatson}
1076101099Srwatson
1077183980Sbzstatic int
1078183980Sbzmls_inpcb_check_visible(struct ucred *cred, struct inpcb *inp,
1079183980Sbz    struct label *inplabel)
1080183980Sbz{
1081183980Sbz	struct mac_mls *subj, *obj;
1082183980Sbz
1083183980Sbz	if (!mls_enabled)
1084183980Sbz		return (0);
1085183980Sbz
1086183980Sbz	subj = SLOT(cred->cr_label);
1087183980Sbz	obj = SLOT(inplabel);
1088183980Sbz
1089183980Sbz	if (!mls_dominate_effective(subj, obj))
1090183980Sbz		return (ENOENT);
1091183980Sbz
1092183980Sbz	return (0);
1093183980Sbz}
1094183980Sbz
1095101099Srwatsonstatic void
1096173138Srwatsonmls_inpcb_create(struct socket *so, struct label *solabel, struct inpcb *inp,
1097173138Srwatson    struct label *inplabel)
1098145855Srwatson{
1099145855Srwatson	struct mac_mls *source, *dest;
1100145855Srwatson
1101173138Srwatson	source = SLOT(solabel);
1102173138Srwatson	dest = SLOT(inplabel);
1103145855Srwatson
1104172955Srwatson	mls_copy_effective(source, dest);
1105145855Srwatson}
1106145855Srwatson
1107145855Srwatsonstatic void
1108173138Srwatsonmls_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel,
1109173138Srwatson    struct mbuf *m, struct label *mlabel)
1110101099Srwatson{
1111101099Srwatson	struct mac_mls *source, *dest;
1112101099Srwatson
1113173138Srwatson	source = SLOT(inplabel);
1114173138Srwatson	dest = SLOT(mlabel);
1115101099Srwatson
1116172955Srwatson	mls_copy_effective(source, dest);
1117101099Srwatson}
1118101099Srwatson
1119101099Srwatsonstatic void
1120173138Srwatsonmls_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1121173138Srwatson    struct inpcb *inp, struct label *inplabel)
1122101099Srwatson{
1123101099Srwatson	struct mac_mls *source, *dest;
1124101099Srwatson
1125193391Srwatson	SOCK_LOCK_ASSERT(so);
1126193391Srwatson
1127173138Srwatson	source = SLOT(solabel);
1128173138Srwatson	dest = SLOT(inplabel);
1129101099Srwatson
1130172955Srwatson	mls_copy(source, dest);
1131101099Srwatson}
1132101099Srwatson
1133101099Srwatsonstatic void
1134184308Srwatsonmls_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1135184308Srwatson    struct label *q6label)
1136184308Srwatson{
1137184308Srwatson	struct mac_mls *source, *dest;
1138184308Srwatson
1139184308Srwatson	source = SLOT(mlabel);
1140184308Srwatson	dest = SLOT(q6label);
1141184308Srwatson
1142184308Srwatson	mls_copy_effective(source, dest);
1143184308Srwatson}
1144184308Srwatson
1145184308Srwatsonstatic int
1146184308Srwatsonmls_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1147184308Srwatson    struct label *q6label)
1148184308Srwatson{
1149184308Srwatson	struct mac_mls *a, *b;
1150184308Srwatson
1151184308Srwatson	a = SLOT(q6label);
1152184308Srwatson	b = SLOT(mlabel);
1153184308Srwatson
1154184308Srwatson	return (mls_equal_effective(a, b));
1155184308Srwatson}
1156184308Srwatson
1157184308Srwatsonstatic void
1158184308Srwatsonmls_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m,
1159184308Srwatson    struct label *mlabel)
1160184308Srwatson{
1161184308Srwatson	struct mac_mls *source, *dest;
1162184308Srwatson
1163184308Srwatson	source = SLOT(q6label);
1164184308Srwatson	dest = SLOT(mlabel);
1165184308Srwatson
1166184308Srwatson	/* Just use the head, since we require them all to match. */
1167184308Srwatson	mls_copy_effective(source, dest);
1168184308Srwatson}
1169184308Srwatson
1170184308Srwatsonstatic void
1171184308Srwatsonmls_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1172184308Srwatson    struct label *q6label)
1173184308Srwatson{
1174184308Srwatson
1175184308Srwatson	/* NOOP: we only accept matching labels, so no need to update */
1176184308Srwatson}
1177184308Srwatson
1178184308Srwatsonstatic void
1179179781Srwatsonmls_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q,
1180179781Srwatson    struct label *qlabel)
1181101099Srwatson{
1182101099Srwatson	struct mac_mls *source, *dest;
1183101099Srwatson
1184173138Srwatson	source = SLOT(mlabel);
1185179781Srwatson	dest = SLOT(qlabel);
1186101099Srwatson
1187173138Srwatson	mls_copy_effective(source, dest);
1188101099Srwatson}
1189101099Srwatson
1190173138Srwatsonstatic int
1191179781Srwatsonmls_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
1192179781Srwatson    struct label *qlabel)
1193101099Srwatson{
1194173138Srwatson	struct mac_mls *a, *b;
1195101099Srwatson
1196179781Srwatson	a = SLOT(qlabel);
1197173138Srwatson	b = SLOT(mlabel);
1198101099Srwatson
1199173138Srwatson	return (mls_equal_effective(a, b));
1200101099Srwatson}
1201101099Srwatson
1202140629Srwatsonstatic void
1203179781Srwatsonmls_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m,
1204173138Srwatson    struct label *mlabel)
1205140629Srwatson{
1206140629Srwatson	struct mac_mls *source, *dest;
1207140629Srwatson
1208179781Srwatson	source = SLOT(qlabel);
1209173138Srwatson	dest = SLOT(mlabel);
1210140629Srwatson
1211173138Srwatson	/* Just use the head, since we require them all to match. */
1212172955Srwatson	mls_copy_effective(source, dest);
1213140629Srwatson}
1214140629Srwatson
1215140629Srwatsonstatic void
1216179781Srwatsonmls_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
1217179781Srwatson    struct label *qlabel)
1218140629Srwatson{
1219140629Srwatson
1220173138Srwatson	/* NOOP: we only accept matching labels, so no need to update */
1221140629Srwatson}
1222140629Srwatson
1223173138Srwatsonstatic int
1224173138Srwatsonmls_mount_check_stat(struct ucred *cred, struct mount *mp,
1225173138Srwatson    struct label *mntlabel)
1226140629Srwatson{
1227173138Srwatson	struct mac_mls *subj, *obj;
1228140629Srwatson
1229173138Srwatson	if (!mls_enabled)
1230173138Srwatson		return (0);
1231140629Srwatson
1232173138Srwatson	subj = SLOT(cred->cr_label);
1233173138Srwatson	obj = SLOT(mntlabel);
1234140629Srwatson
1235173138Srwatson	if (!mls_dominate_effective(subj, obj))
1236173138Srwatson		return (EACCES);
1237140629Srwatson
1238173138Srwatson	return (0);
1239140629Srwatson}
1240140629Srwatson
1241101099Srwatsonstatic void
1242173138Srwatsonmls_mount_create(struct ucred *cred, struct mount *mp, struct label *mplabel)
1243101099Srwatson{
1244101099Srwatson	struct mac_mls *source, *dest;
1245101099Srwatson
1246173138Srwatson	source = SLOT(cred->cr_label);
1247173138Srwatson	dest = SLOT(mplabel);
1248101099Srwatson
1249172955Srwatson	mls_copy_effective(source, dest);
1250101099Srwatson}
1251101099Srwatson
1252101099Srwatsonstatic void
1253173138Srwatsonmls_netatalk_aarp_send(struct ifnet *ifp, struct label *ifplabel,
1254173138Srwatson    struct mbuf *m, struct label *mlabel)
1255101099Srwatson{
1256173138Srwatson	struct mac_mls *dest;
1257101099Srwatson
1258173138Srwatson	dest = SLOT(mlabel);
1259101099Srwatson
1260173138Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1261101099Srwatson}
1262101099Srwatson
1263101099Srwatsonstatic void
1264173138Srwatsonmls_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel,
1265173138Srwatson    struct mbuf *m, struct label *mlabel)
1266101099Srwatson{
1267101099Srwatson	struct mac_mls *dest;
1268101099Srwatson
1269173138Srwatson	dest = SLOT(mlabel);
1270101099Srwatson
1271173138Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1272101099Srwatson}
1273101099Srwatson
1274101099Srwatsonstatic void
1275173138Srwatsonmls_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1276173138Srwatson    struct mbuf *msend, struct label *msendlabel)
1277101099Srwatson{
1278101099Srwatson	struct mac_mls *source, *dest;
1279101099Srwatson
1280173138Srwatson	source = SLOT(mrecvlabel);
1281173138Srwatson	dest = SLOT(msendlabel);
1282101099Srwatson
1283172955Srwatson	mls_copy_effective(source, dest);
1284101099Srwatson}
1285101099Srwatson
1286101099Srwatsonstatic void
1287173138Srwatsonmls_netinet_firewall_send(struct mbuf *m, struct label *mlabel)
1288101099Srwatson{
1289173138Srwatson	struct mac_mls *dest;
1290101099Srwatson
1291168976Srwatson	dest = SLOT(mlabel);
1292101099Srwatson
1293173138Srwatson	/* XXX: where is the label for the firewall really comming from? */
1294173138Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1295101099Srwatson}
1296101099Srwatson
1297101099Srwatsonstatic void
1298172955Srwatsonmls_netinet_fragment(struct mbuf *m, struct label *mlabel, struct mbuf *frag,
1299172955Srwatson    struct label *fraglabel)
1300101099Srwatson{
1301101099Srwatson	struct mac_mls *source, *dest;
1302101099Srwatson
1303168976Srwatson	source = SLOT(mlabel);
1304168976Srwatson	dest = SLOT(fraglabel);
1305101099Srwatson
1306172955Srwatson	mls_copy_effective(source, dest);
1307101099Srwatson}
1308101099Srwatson
1309101099Srwatsonstatic void
1310173138Srwatsonmls_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1311173138Srwatson    struct mbuf *msend, struct label *msendlabel)
1312123607Srwatson{
1313123607Srwatson	struct mac_mls *source, *dest;
1314123607Srwatson
1315173138Srwatson	source = SLOT(mrecvlabel);
1316173138Srwatson	dest = SLOT(msendlabel);
1317123607Srwatson
1318172955Srwatson	mls_copy_effective(source, dest);
1319123607Srwatson}
1320123607Srwatson
1321123607Srwatsonstatic void
1322173138Srwatsonmls_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel,
1323168976Srwatson    struct mbuf *m, struct label *mlabel)
1324101099Srwatson{
1325173138Srwatson	struct mac_mls *dest;
1326101099Srwatson
1327168976Srwatson	dest = SLOT(mlabel);
1328101099Srwatson
1329173138Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1330101099Srwatson}
1331101099Srwatson
1332101099Srwatsonstatic void
1333173138Srwatsonmls_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel,
1334168976Srwatson    struct mbuf *m, struct label *mlabel)
1335101099Srwatson{
1336173138Srwatson	struct mac_mls *dest;
1337101099Srwatson
1338168976Srwatson	dest = SLOT(mlabel);
1339101099Srwatson
1340173138Srwatson	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1341101099Srwatson}
1342101099Srwatson
1343101099Srwatsonstatic int
1344173138Srwatsonmls_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
1345173138Srwatson    struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1346101099Srwatson{
1347101099Srwatson
1348173138Srwatson	if (!mls_enabled)
1349173138Srwatson		return (0);
1350101099Srwatson
1351173138Srwatson	/* XXX: This will be implemented soon... */
1352173138Srwatson
1353173138Srwatson	return (0);
1354101099Srwatson}
1355101099Srwatson
1356173138Srwatsonstatic int
1357173138Srwatsonmls_pipe_check_poll(struct ucred *cred, struct pipepair *pp,
1358173138Srwatson    struct label *pplabel)
1359101099Srwatson{
1360173138Srwatson	struct mac_mls *subj, *obj;
1361101099Srwatson
1362173138Srwatson	if (!mls_enabled)
1363173138Srwatson		return (0);
1364101099Srwatson
1365173138Srwatson	subj = SLOT(cred->cr_label);
1366173138Srwatson	obj = SLOT(pplabel);
1367101099Srwatson
1368173138Srwatson	if (!mls_dominate_effective(subj, obj))
1369173138Srwatson		return (EACCES);
1370101099Srwatson
1371173138Srwatson	return (0);
1372101099Srwatson}
1373101099Srwatson
1374173138Srwatsonstatic int
1375173138Srwatsonmls_pipe_check_read(struct ucred *cred, struct pipepair *pp,
1376173138Srwatson    struct label *pplabel)
1377122875Srwatson{
1378173138Srwatson	struct mac_mls *subj, *obj;
1379122875Srwatson
1380173138Srwatson	if (!mls_enabled)
1381173138Srwatson		return (0);
1382122875Srwatson
1383173138Srwatson	subj = SLOT(cred->cr_label);
1384173138Srwatson	obj = SLOT(pplabel);
1385173138Srwatson
1386173138Srwatson	if (!mls_dominate_effective(subj, obj))
1387173138Srwatson		return (EACCES);
1388173138Srwatson
1389173138Srwatson	return (0);
1390122875Srwatson}
1391122875Srwatson
1392173138Srwatsonstatic int
1393173138Srwatsonmls_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
1394173138Srwatson    struct label *pplabel, struct label *newlabel)
1395173095Srwatson{
1396173138Srwatson	struct mac_mls *subj, *obj, *new;
1397173138Srwatson	int error;
1398173095Srwatson
1399173138Srwatson	new = SLOT(newlabel);
1400173138Srwatson	subj = SLOT(cred->cr_label);
1401173138Srwatson	obj = SLOT(pplabel);
1402173095Srwatson
1403173138Srwatson	/*
1404173138Srwatson	 * If there is an MLS label update for a pipe, it must be a effective
1405173138Srwatson	 * update.
1406173138Srwatson	 */
1407173138Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1408173138Srwatson	if (error)
1409173138Srwatson		return (error);
1410173095Srwatson
1411173138Srwatson	/*
1412173138Srwatson	 * To perform a relabel of a pipe (MLS label or not), MLS must
1413173138Srwatson	 * authorize the relabel.
1414173138Srwatson	 */
1415173138Srwatson	if (!mls_effective_in_range(obj, subj))
1416173138Srwatson		return (EPERM);
1417173095Srwatson
1418173138Srwatson	/*
1419173138Srwatson	 * If the MLS label is to be changed, authorize as appropriate.
1420173138Srwatson	 */
1421173138Srwatson	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1422173138Srwatson		/*
1423173138Srwatson		 * To change the MLS label on a pipe, the new pipe label must
1424173138Srwatson		 * be in the subject range.
1425173138Srwatson		 */
1426173138Srwatson		if (!mls_effective_in_range(new, subj))
1427173138Srwatson			return (EPERM);
1428173095Srwatson
1429173138Srwatson		/*
1430173138Srwatson		 * To change the MLS label on a pipe to be EQUAL, the subject
1431173138Srwatson		 * must have appropriate privilege.
1432173138Srwatson		 */
1433173138Srwatson		if (mls_contains_equal(new)) {
1434173138Srwatson			error = mls_subject_privileged(subj);
1435173138Srwatson			if (error)
1436173138Srwatson				return (error);
1437173138Srwatson		}
1438173138Srwatson	}
1439173138Srwatson
1440173138Srwatson	return (0);
1441173095Srwatson}
1442173095Srwatson
1443173138Srwatsonstatic int
1444173138Srwatsonmls_pipe_check_stat(struct ucred *cred, struct pipepair *pp,
1445173138Srwatson    struct label *pplabel)
1446173102Srwatson{
1447173138Srwatson	struct mac_mls *subj, *obj;
1448173102Srwatson
1449173138Srwatson	if (!mls_enabled)
1450173138Srwatson		return (0);
1451173102Srwatson
1452173138Srwatson	subj = SLOT(cred->cr_label);
1453173138Srwatson	obj = SLOT(pplabel);
1454173138Srwatson
1455173138Srwatson	if (!mls_dominate_effective(subj, obj))
1456173138Srwatson		return (EACCES);
1457173138Srwatson
1458173138Srwatson	return (0);
1459173102Srwatson}
1460173102Srwatson
1461173138Srwatsonstatic int
1462173138Srwatsonmls_pipe_check_write(struct ucred *cred, struct pipepair *pp,
1463173138Srwatson    struct label *pplabel)
1464162238Scsjp{
1465173138Srwatson	struct mac_mls *subj, *obj;
1466162238Scsjp
1467173138Srwatson	if (!mls_enabled)
1468173138Srwatson		return (0);
1469162238Scsjp
1470173138Srwatson	subj = SLOT(cred->cr_label);
1471173138Srwatson	obj = SLOT(pplabel);
1472173138Srwatson
1473173138Srwatson	if (!mls_dominate_effective(obj, subj))
1474173138Srwatson		return (EACCES);
1475173138Srwatson
1476173138Srwatson	return (0);
1477162238Scsjp}
1478162238Scsjp
1479165150Scsjpstatic void
1480173138Srwatsonmls_pipe_create(struct ucred *cred, struct pipepair *pp,
1481173138Srwatson    struct label *pplabel)
1482173102Srwatson{
1483173102Srwatson	struct mac_mls *source, *dest;
1484173102Srwatson
1485173138Srwatson	source = SLOT(cred->cr_label);
1486173138Srwatson	dest = SLOT(pplabel);
1487173102Srwatson
1488173102Srwatson	mls_copy_effective(source, dest);
1489173102Srwatson}
1490173102Srwatson
1491173102Srwatsonstatic void
1492173138Srwatsonmls_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1493173138Srwatson    struct label *pplabel, struct label *newlabel)
1494173095Srwatson{
1495173138Srwatson	struct mac_mls *source, *dest;
1496173095Srwatson
1497173138Srwatson	source = SLOT(newlabel);
1498173138Srwatson	dest = SLOT(pplabel);
1499173095Srwatson
1500173138Srwatson	mls_copy(source, dest);
1501173095Srwatson}
1502173095Srwatson
1503173138Srwatsonstatic int
1504180059Sjhbmls_posixsem_check_openunlink(struct ucred *cred, struct ksem *ks,
1505173138Srwatson    struct label *kslabel)
1506173095Srwatson{
1507173138Srwatson	struct mac_mls *subj, *obj;
1508173095Srwatson
1509173138Srwatson	if (!mls_enabled)
1510173138Srwatson		return (0);
1511173095Srwatson
1512173138Srwatson	subj = SLOT(cred->cr_label);
1513173138Srwatson	obj = SLOT(kslabel);
1514173095Srwatson
1515180059Sjhb	if (!mls_dominate_effective(obj, subj))
1516180059Sjhb		return (EACCES);
1517180059Sjhb
1518180059Sjhb	return (0);
1519180059Sjhb}
1520180059Sjhb
1521180059Sjhbstatic int
1522180059Sjhbmls_posixsem_check_rdonly(struct ucred *active_cred, struct ucred *file_cred,
1523180059Sjhb    struct ksem *ks, struct label *kslabel)
1524180059Sjhb{
1525180059Sjhb	struct mac_mls *subj, *obj;
1526180059Sjhb
1527180059Sjhb	if (!mls_enabled)
1528180059Sjhb		return (0);
1529180059Sjhb
1530180059Sjhb	subj = SLOT(active_cred->cr_label);
1531180059Sjhb	obj = SLOT(kslabel);
1532180059Sjhb
1533173138Srwatson	if (!mls_dominate_effective(subj, obj))
1534173138Srwatson		return (EACCES);
1535165150Scsjp
1536173138Srwatson	return (0);
1537165150Scsjp}
1538165150Scsjp
1539173138Srwatsonstatic int
1540225344Srwatsonmls_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
1541225344Srwatson    struct label *shmlabel, mode_t mode)
1542225344Srwatson{
1543225344Srwatson	struct mac_mls *subj, *obj;
1544225344Srwatson
1545225344Srwatson	if (!mls_enabled)
1546225344Srwatson		return (0);
1547225344Srwatson
1548225344Srwatson	subj = SLOT(cred->cr_label);
1549225344Srwatson	obj = SLOT(shmlabel);
1550225344Srwatson
1551225344Srwatson	if (!mls_dominate_effective(obj, subj))
1552225344Srwatson		return (EACCES);
1553225344Srwatson
1554225344Srwatson	return (0);
1555225344Srwatson}
1556225344Srwatson
1557225344Srwatsonstatic int
1558225344Srwatsonmls_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
1559225344Srwatson    struct label *shmlabel, uid_t uid, gid_t gid)
1560225344Srwatson{
1561225344Srwatson	struct mac_mls *subj, *obj;
1562225344Srwatson
1563225344Srwatson	if (!mls_enabled)
1564225344Srwatson		return (0);
1565225344Srwatson
1566225344Srwatson	subj = SLOT(cred->cr_label);
1567225344Srwatson	obj = SLOT(shmlabel);
1568225344Srwatson
1569225344Srwatson	if (!mls_dominate_effective(obj, subj))
1570225344Srwatson		return (EACCES);
1571225344Srwatson
1572225344Srwatson	return (0);
1573225344Srwatson}
1574225344Srwatson
1575225344Srwatsonstatic int
1576180059Sjhbmls_posixsem_check_write(struct ucred *active_cred, struct ucred *file_cred,
1577180059Sjhb    struct ksem *ks, struct label *kslabel)
1578165150Scsjp{
1579173138Srwatson	struct mac_mls *subj, *obj;
1580165150Scsjp
1581173138Srwatson	if (!mls_enabled)
1582173138Srwatson		return (0);
1583172955Srwatson
1584180059Sjhb	subj = SLOT(active_cred->cr_label);
1585173138Srwatson	obj = SLOT(kslabel);
1586165150Scsjp
1587173138Srwatson	if (!mls_dominate_effective(obj, subj))
1588173138Srwatson		return (EACCES);
1589101099Srwatson
1590173138Srwatson	return (0);
1591101099Srwatson}
1592101099Srwatson
1593101099Srwatsonstatic void
1594173138Srwatsonmls_posixsem_create(struct ucred *cred, struct ksem *ks,
1595173138Srwatson    struct label *kslabel)
1596101099Srwatson{
1597173138Srwatson	struct mac_mls *source, *dest;
1598101099Srwatson
1599173138Srwatson	source = SLOT(cred->cr_label);
1600173138Srwatson	dest = SLOT(kslabel);
1601101099Srwatson
1602173138Srwatson	mls_copy_effective(source, dest);
1603101099Srwatson}
1604101099Srwatson
1605173138Srwatsonstatic int
1606225344Srwatsonmls_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
1607225344Srwatson    struct label *shmlabel, int prot, int flags)
1608225344Srwatson{
1609225344Srwatson	struct mac_mls *subj, *obj;
1610225344Srwatson
1611225344Srwatson	if (!mls_enabled)
1612225344Srwatson		return (0);
1613225344Srwatson
1614225344Srwatson	subj = SLOT(cred->cr_label);
1615225344Srwatson	obj = SLOT(shmlabel);
1616225344Srwatson
1617225344Srwatson	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
1618225344Srwatson		if (!mls_dominate_effective(subj, obj))
1619225344Srwatson			return (EACCES);
1620225344Srwatson	}
1621225344Srwatson	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
1622225344Srwatson		if (!mls_dominate_effective(obj, subj))
1623225344Srwatson			return (EACCES);
1624225344Srwatson	}
1625225344Srwatson
1626225344Srwatson	return (0);
1627225344Srwatson}
1628225344Srwatson
1629225344Srwatsonstatic int
1630225344Srwatsonmls_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
1631225344Srwatson    struct label *shmlabel, accmode_t accmode)
1632225344Srwatson{
1633225344Srwatson	struct mac_mls *subj, *obj;
1634225344Srwatson
1635225344Srwatson	if (!mls_enabled)
1636225344Srwatson		return (0);
1637225344Srwatson
1638225344Srwatson	subj = SLOT(cred->cr_label);
1639225344Srwatson	obj = SLOT(shmlabel);
1640225344Srwatson
1641225344Srwatson	if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
1642225344Srwatson		if (!mls_dominate_effective(subj, obj))
1643225344Srwatson			return (EACCES);
1644225344Srwatson	}
1645225344Srwatson	if (accmode & VMODIFY_PERMS) {
1646225344Srwatson		if (!mls_dominate_effective(obj, subj))
1647225344Srwatson			return (EACCES);
1648225344Srwatson	}
1649225344Srwatson
1650225344Srwatson	return (0);
1651225344Srwatson}
1652225344Srwatson
1653225344Srwatsonstatic int
1654225344Srwatsonmls_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
1655225344Srwatson    struct label *shmlabel, mode_t mode)
1656225344Srwatson{
1657225344Srwatson	struct mac_mls *subj, *obj;
1658225344Srwatson
1659225344Srwatson	if (!mls_enabled)
1660225344Srwatson		return (0);
1661225344Srwatson
1662225344Srwatson	subj = SLOT(cred->cr_label);
1663225344Srwatson	obj = SLOT(shmlabel);
1664225344Srwatson
1665225344Srwatson	if (!mls_dominate_effective(obj, subj))
1666225344Srwatson		return (EACCES);
1667225344Srwatson
1668225344Srwatson	return (0);
1669225344Srwatson}
1670225344Srwatson
1671225344Srwatsonstatic int
1672225344Srwatsonmls_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
1673225344Srwatson    struct label *shmlabel, uid_t uid, gid_t gid)
1674225344Srwatson{
1675225344Srwatson	struct mac_mls *subj, *obj;
1676225344Srwatson
1677225344Srwatson	if (!mls_enabled)
1678225344Srwatson		return (0);
1679225344Srwatson
1680225344Srwatson	subj = SLOT(cred->cr_label);
1681225344Srwatson	obj = SLOT(shmlabel);
1682225344Srwatson
1683225344Srwatson	if (!mls_dominate_effective(obj, subj))
1684225344Srwatson		return (EACCES);
1685225344Srwatson
1686225344Srwatson	return (0);
1687225344Srwatson}
1688225344Srwatson
1689225344Srwatsonstatic int
1690225344Srwatsonmls_posixshm_check_stat(struct ucred *active_cred, struct ucred *file_cred,
1691225344Srwatson    struct shmfd *shmfd, struct label *shmlabel)
1692225344Srwatson{
1693225344Srwatson	struct mac_mls *subj, *obj;
1694225344Srwatson
1695225344Srwatson	if (!mls_enabled)
1696225344Srwatson		return (0);
1697225344Srwatson
1698225344Srwatson	subj = SLOT(active_cred->cr_label);
1699225344Srwatson	obj = SLOT(shmlabel);
1700225344Srwatson
1701225344Srwatson	if (!mls_dominate_effective(subj, obj))
1702225344Srwatson		return (EACCES);
1703225344Srwatson
1704225344Srwatson	return (0);
1705225344Srwatson}
1706225344Srwatson
1707225344Srwatsonstatic int
1708225344Srwatsonmls_posixshm_check_truncate(struct ucred *active_cred,
1709225344Srwatson    struct ucred *file_cred, struct shmfd *shmfd, struct label *shmlabel)
1710225344Srwatson{
1711225344Srwatson	struct mac_mls *subj, *obj;
1712225344Srwatson
1713225344Srwatson	if (!mls_enabled)
1714225344Srwatson		return (0);
1715225344Srwatson
1716225344Srwatson	subj = SLOT(active_cred->cr_label);
1717225344Srwatson	obj = SLOT(shmlabel);
1718225344Srwatson
1719225344Srwatson	if (!mls_dominate_effective(obj, subj))
1720225344Srwatson		return (EACCES);
1721225344Srwatson
1722225344Srwatson	return (0);
1723225344Srwatson}
1724225344Srwatson
1725225344Srwatsonstatic int
1726225344Srwatsonmls_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd,
1727225344Srwatson    struct label *shmlabel)
1728225344Srwatson{
1729225344Srwatson	struct mac_mls *subj, *obj;
1730225344Srwatson
1731225344Srwatson	if (!mls_enabled)
1732225344Srwatson		return (0);
1733225344Srwatson
1734225344Srwatson	subj = SLOT(cred->cr_label);
1735225344Srwatson	obj = SLOT(shmlabel);
1736225344Srwatson
1737225344Srwatson	if (!mls_dominate_effective(obj, subj))
1738225344Srwatson		return (EACCES);
1739225344Srwatson
1740225344Srwatson	return (0);
1741225344Srwatson}
1742225344Srwatson
1743225344Srwatsonstatic void
1744225344Srwatsonmls_posixshm_create(struct ucred *cred, struct shmfd *shmfd,
1745225344Srwatson    struct label *shmlabel)
1746225344Srwatson{
1747225344Srwatson	struct mac_mls *source, *dest;
1748225344Srwatson
1749225344Srwatson	source = SLOT(cred->cr_label);
1750225344Srwatson	dest = SLOT(shmlabel);
1751225344Srwatson
1752225344Srwatson	mls_copy_effective(source, dest);
1753225344Srwatson}
1754225344Srwatson
1755225344Srwatsonstatic int
1756173138Srwatsonmls_proc_check_debug(struct ucred *cred, struct proc *p)
1757101099Srwatson{
1758173138Srwatson	struct mac_mls *subj, *obj;
1759101099Srwatson
1760173138Srwatson	if (!mls_enabled)
1761173138Srwatson		return (0);
1762101099Srwatson
1763173138Srwatson	subj = SLOT(cred->cr_label);
1764173138Srwatson	obj = SLOT(p->p_ucred->cr_label);
1765173138Srwatson
1766173138Srwatson	/* XXX: range checks */
1767173138Srwatson	if (!mls_dominate_effective(subj, obj))
1768173138Srwatson		return (ESRCH);
1769173138Srwatson	if (!mls_dominate_effective(obj, subj))
1770173138Srwatson		return (EACCES);
1771173138Srwatson
1772173138Srwatson	return (0);
1773101099Srwatson}
1774101099Srwatson
1775173138Srwatsonstatic int
1776173138Srwatsonmls_proc_check_sched(struct ucred *cred, struct proc *p)
1777140629Srwatson{
1778173138Srwatson	struct mac_mls *subj, *obj;
1779140629Srwatson
1780173138Srwatson	if (!mls_enabled)
1781173138Srwatson		return (0);
1782173138Srwatson
1783173138Srwatson	subj = SLOT(cred->cr_label);
1784173138Srwatson	obj = SLOT(p->p_ucred->cr_label);
1785173138Srwatson
1786173138Srwatson	/* XXX: range checks */
1787173138Srwatson	if (!mls_dominate_effective(subj, obj))
1788173138Srwatson		return (ESRCH);
1789173138Srwatson	if (!mls_dominate_effective(obj, subj))
1790173138Srwatson		return (EACCES);
1791173138Srwatson
1792173138Srwatson	return (0);
1793140629Srwatson}
1794140629Srwatson
1795173138Srwatsonstatic int
1796173138Srwatsonmls_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
1797140629Srwatson{
1798173138Srwatson	struct mac_mls *subj, *obj;
1799140629Srwatson
1800173138Srwatson	if (!mls_enabled)
1801173138Srwatson		return (0);
1802173138Srwatson
1803173138Srwatson	subj = SLOT(cred->cr_label);
1804173138Srwatson	obj = SLOT(p->p_ucred->cr_label);
1805173138Srwatson
1806173138Srwatson	/* XXX: range checks */
1807173138Srwatson	if (!mls_dominate_effective(subj, obj))
1808173138Srwatson		return (ESRCH);
1809173138Srwatson	if (!mls_dominate_effective(obj, subj))
1810173138Srwatson		return (EACCES);
1811173138Srwatson
1812173138Srwatson	return (0);
1813140629Srwatson}
1814140629Srwatson
1815101099Srwatsonstatic int
1816173138Srwatsonmls_socket_check_deliver(struct socket *so, struct label *solabel,
1817173138Srwatson    struct mbuf *m, struct label *mlabel)
1818101099Srwatson{
1819173138Srwatson	struct mac_mls *p, *s;
1820193391Srwatson	int error;
1821101099Srwatson
1822172955Srwatson	if (!mls_enabled)
1823101099Srwatson		return (0);
1824101099Srwatson
1825173138Srwatson	p = SLOT(mlabel);
1826173138Srwatson	s = SLOT(solabel);
1827101099Srwatson
1828193391Srwatson	SOCK_LOCK(so);
1829193391Srwatson	error = mls_equal_effective(p, s) ? 0 : EACCES;
1830193391Srwatson	SOCK_UNLOCK(so);
1831193391Srwatson
1832193391Srwatson	return (error);
1833101099Srwatson}
1834101099Srwatson
1835101099Srwatsonstatic int
1836173138Srwatsonmls_socket_check_relabel(struct ucred *cred, struct socket *so,
1837173138Srwatson    struct label *solabel, struct label *newlabel)
1838101099Srwatson{
1839173138Srwatson	struct mac_mls *subj, *obj, *new;
1840105634Srwatson	int error;
1841101099Srwatson
1842193391Srwatson	SOCK_LOCK_ASSERT(so);
1843193391Srwatson
1844173138Srwatson	new = SLOT(newlabel);
1845122524Srwatson	subj = SLOT(cred->cr_label);
1846173138Srwatson	obj = SLOT(solabel);
1847101099Srwatson
1848101099Srwatson	/*
1849173138Srwatson	 * If there is an MLS label update for the socket, it may be an
1850173138Srwatson	 * update of effective.
1851101099Srwatson	 */
1852173138Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1853105634Srwatson	if (error)
1854105634Srwatson		return (error);
1855101099Srwatson
1856101099Srwatson	/*
1857173138Srwatson	 * To relabel a socket, the old socket effective must be in the
1858173138Srwatson	 * subject range.
1859173138Srwatson	 */
1860173138Srwatson	if (!mls_effective_in_range(obj, subj))
1861173138Srwatson		return (EPERM);
1862173138Srwatson
1863173138Srwatson	/*
1864105634Srwatson	 * If the MLS label is to be changed, authorize as appropriate.
1865101099Srwatson	 */
1866173138Srwatson	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1867105634Srwatson		/*
1868173138Srwatson		 * To relabel a socket, the new socket effective must be in
1869173138Srwatson		 * the subject range.
1870110351Srwatson		 */
1871173138Srwatson		if (!mls_effective_in_range(new, subj))
1872105634Srwatson			return (EPERM);
1873101099Srwatson
1874105634Srwatson		/*
1875173138Srwatson		 * To change the MLS label on the socket to contain EQUAL,
1876173138Srwatson		 * the subject must have appropriate privilege.
1877105634Srwatson		 */
1878172955Srwatson		if (mls_contains_equal(new)) {
1879172955Srwatson			error = mls_subject_privileged(subj);
1880105634Srwatson			if (error)
1881105634Srwatson				return (error);
1882105634Srwatson		}
1883105634Srwatson	}
1884105634Srwatson
1885101099Srwatson	return (0);
1886101099Srwatson}
1887101099Srwatson
1888101099Srwatsonstatic int
1889173138Srwatsonmls_socket_check_visible(struct ucred *cred, struct socket *so,
1890173138Srwatson    struct label *solabel)
1891101099Srwatson{
1892101099Srwatson	struct mac_mls *subj, *obj;
1893101099Srwatson
1894172955Srwatson	if (!mls_enabled)
1895101099Srwatson		return (0);
1896101099Srwatson
1897173138Srwatson	subj = SLOT(cred->cr_label);
1898173138Srwatson	obj = SLOT(solabel);
1899101099Srwatson
1900193391Srwatson	SOCK_LOCK(so);
1901193391Srwatson	if (!mls_dominate_effective(subj, obj)) {
1902193391Srwatson		SOCK_UNLOCK(so);
1903173138Srwatson		return (ENOENT);
1904193391Srwatson	}
1905193391Srwatson	SOCK_UNLOCK(so);
1906101099Srwatson
1907101099Srwatson	return (0);
1908101099Srwatson}
1909101099Srwatson
1910173138Srwatsonstatic void
1911173138Srwatsonmls_socket_create(struct ucred *cred, struct socket *so,
1912173138Srwatson    struct label *solabel)
1913173138Srwatson{
1914173138Srwatson	struct mac_mls *source, *dest;
1915173138Srwatson
1916173138Srwatson	source = SLOT(cred->cr_label);
1917173138Srwatson	dest = SLOT(solabel);
1918173138Srwatson
1919173138Srwatson	mls_copy_effective(source, dest);
1920173138Srwatson}
1921173138Srwatson
1922173138Srwatsonstatic void
1923173138Srwatsonmls_socket_create_mbuf(struct socket *so, struct label *solabel,
1924173138Srwatson    struct mbuf *m, struct label *mlabel)
1925173138Srwatson{
1926173138Srwatson	struct mac_mls *source, *dest;
1927173138Srwatson
1928173138Srwatson	source = SLOT(solabel);
1929173138Srwatson	dest = SLOT(mlabel);
1930173138Srwatson
1931193391Srwatson	SOCK_LOCK(so);
1932173138Srwatson	mls_copy_effective(source, dest);
1933193391Srwatson	SOCK_UNLOCK(so);
1934173138Srwatson}
1935173138Srwatson
1936173138Srwatsonstatic void
1937173138Srwatsonmls_socket_newconn(struct socket *oldso, struct label *oldsolabel,
1938173138Srwatson    struct socket *newso, struct label *newsolabel)
1939173138Srwatson{
1940193391Srwatson	struct mac_mls source, *dest;
1941173138Srwatson
1942193391Srwatson	SOCK_LOCK(oldso);
1943193391Srwatson	source = *SLOT(oldsolabel);
1944193391Srwatson	SOCK_UNLOCK(oldso);
1945193391Srwatson
1946173138Srwatson	dest = SLOT(newsolabel);
1947173138Srwatson
1948193391Srwatson	SOCK_LOCK(newso);
1949193391Srwatson	mls_copy_effective(&source, dest);
1950193391Srwatson	SOCK_UNLOCK(newso);
1951173138Srwatson}
1952173138Srwatson
1953173138Srwatsonstatic void
1954173138Srwatsonmls_socket_relabel(struct ucred *cred, struct socket *so,
1955173138Srwatson    struct label *solabel, struct label *newlabel)
1956173138Srwatson{
1957173138Srwatson	struct mac_mls *source, *dest;
1958173138Srwatson
1959193391Srwatson	SOCK_LOCK_ASSERT(so);
1960193391Srwatson
1961173138Srwatson	source = SLOT(newlabel);
1962173138Srwatson	dest = SLOT(solabel);
1963173138Srwatson
1964173138Srwatson	mls_copy(source, dest);
1965173138Srwatson}
1966173138Srwatson
1967173138Srwatsonstatic void
1968173138Srwatsonmls_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel,
1969173138Srwatson    struct socket *so, struct label *sopeerlabel)
1970173138Srwatson{
1971173138Srwatson	struct mac_mls *source, *dest;
1972173138Srwatson
1973173138Srwatson	source = SLOT(mlabel);
1974173138Srwatson	dest = SLOT(sopeerlabel);
1975173138Srwatson
1976193391Srwatson	SOCK_LOCK(so);
1977173138Srwatson	mls_copy_effective(source, dest);
1978193391Srwatson	SOCK_UNLOCK(so);
1979173138Srwatson}
1980173138Srwatson
1981173138Srwatsonstatic void
1982173138Srwatsonmls_socketpeer_set_from_socket(struct socket *oldso,
1983173138Srwatson    struct label *oldsolabel, struct socket *newso,
1984173138Srwatson    struct label *newsopeerlabel)
1985173138Srwatson{
1986193391Srwatson	struct mac_mls source, *dest;
1987173138Srwatson
1988193391Srwatson	SOCK_LOCK(oldso);
1989193391Srwatson	source = *SLOT(oldsolabel);
1990193391Srwatson	SOCK_UNLOCK(oldso);
1991193391Srwatson
1992173138Srwatson	dest = SLOT(newsopeerlabel);
1993173138Srwatson
1994193391Srwatson	SOCK_LOCK(newso);
1995193391Srwatson	mls_copy_effective(&source, dest);
1996193391Srwatson	SOCK_UNLOCK(newso);
1997173138Srwatson}
1998173138Srwatson
1999173138Srwatsonstatic void
2000173138Srwatsonmls_syncache_create(struct label *label, struct inpcb *inp)
2001173138Srwatson{
2002173138Srwatson	struct mac_mls *source, *dest;
2003173138Srwatson
2004173138Srwatson	source = SLOT(inp->inp_label);
2005173138Srwatson	dest = SLOT(label);
2006173138Srwatson
2007173138Srwatson	mls_copy_effective(source, dest);
2008173138Srwatson}
2009173138Srwatson
2010173138Srwatsonstatic void
2011173138Srwatsonmls_syncache_create_mbuf(struct label *sc_label, struct mbuf *m,
2012173138Srwatson    struct label *mlabel)
2013173138Srwatson{
2014173138Srwatson	struct mac_mls *source, *dest;
2015173138Srwatson
2016173138Srwatson	source = SLOT(sc_label);
2017173138Srwatson	dest = SLOT(mlabel);
2018173138Srwatson
2019173138Srwatson	mls_copy_effective(source, dest);
2020173138Srwatson}
2021173138Srwatson
2022101099Srwatsonstatic int
2023173138Srwatsonmls_system_check_acct(struct ucred *cred, struct vnode *vp,
2024173138Srwatson    struct label *vplabel)
2025101099Srwatson{
2026173138Srwatson	struct mac_mls *subj, *obj;
2027101099Srwatson
2028173138Srwatson	if (!mls_enabled)
2029173138Srwatson		return (0);
2030173138Srwatson
2031235511Sbrueffer	if (vplabel == NULL)
2032235511Sbrueffer		return (0);
2033235511Sbrueffer
2034122524Srwatson	subj = SLOT(cred->cr_label);
2035173138Srwatson	obj = SLOT(vplabel);
2036101099Srwatson
2037173138Srwatson	if (!mls_dominate_effective(obj, subj) ||
2038173138Srwatson	    !mls_dominate_effective(subj, obj))
2039173138Srwatson		return (EACCES);
2040101099Srwatson
2041105634Srwatson	return (0);
2042101099Srwatson}
2043101099Srwatson
2044101099Srwatsonstatic int
2045173138Srwatsonmls_system_check_auditctl(struct ucred *cred, struct vnode *vp,
2046173138Srwatson    struct label *vplabel)
2047101099Srwatson{
2048173138Srwatson	struct mac_mls *subj, *obj;
2049101099Srwatson
2050172955Srwatson	if (!mls_enabled)
2051101099Srwatson		return (0);
2052101099Srwatson
2053173138Srwatson	subj = SLOT(cred->cr_label);
2054173138Srwatson	obj = SLOT(vplabel);
2055101099Srwatson
2056173138Srwatson	if (!mls_dominate_effective(obj, subj) ||
2057173138Srwatson	    !mls_dominate_effective(subj, obj))
2058173138Srwatson		return (EACCES);
2059173138Srwatson
2060173138Srwatson	return (0);
2061101099Srwatson}
2062101099Srwatson
2063101099Srwatsonstatic int
2064173138Srwatsonmls_system_check_swapon(struct ucred *cred, struct vnode *vp,
2065173138Srwatson    struct label *vplabel)
2066122875Srwatson{
2067173138Srwatson	struct mac_mls *subj, *obj;
2068122875Srwatson
2069172955Srwatson	if (!mls_enabled)
2070122875Srwatson		return (0);
2071122875Srwatson
2072173138Srwatson	subj = SLOT(cred->cr_label);
2073173138Srwatson	obj = SLOT(vplabel);
2074122875Srwatson
2075173138Srwatson	if (!mls_dominate_effective(obj, subj) ||
2076173138Srwatson	    !mls_dominate_effective(subj, obj))
2077173138Srwatson		return (EACCES);
2078173138Srwatson
2079173138Srwatson	return (0);
2080122875Srwatson}
2081122875Srwatson
2082173138Srwatsonstatic void
2083173138Srwatsonmls_sysvmsg_cleanup(struct label *msglabel)
2084173138Srwatson{
2085173138Srwatson
2086173138Srwatson	bzero(SLOT(msglabel), sizeof(struct mac_mls));
2087173138Srwatson}
2088173138Srwatson
2089173138Srwatsonstatic void
2090173138Srwatsonmls_sysvmsg_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2091173138Srwatson    struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
2092173138Srwatson{
2093173138Srwatson	struct mac_mls *source, *dest;
2094173138Srwatson
2095173138Srwatson	/* Ignore the msgq label. */
2096173138Srwatson	source = SLOT(cred->cr_label);
2097173138Srwatson	dest = SLOT(msglabel);
2098173138Srwatson
2099173138Srwatson	mls_copy_effective(source, dest);
2100173138Srwatson}
2101173138Srwatson
2102122875Srwatsonstatic int
2103172955Srwatsonmls_sysvmsq_check_msgrcv(struct ucred *cred, struct msg *msgptr,
2104140629Srwatson    struct label *msglabel)
2105140629Srwatson{
2106140629Srwatson	struct mac_mls *subj, *obj;
2107140629Srwatson
2108172955Srwatson	if (!mls_enabled)
2109140629Srwatson		return (0);
2110140629Srwatson
2111140629Srwatson	subj = SLOT(cred->cr_label);
2112140629Srwatson	obj = SLOT(msglabel);
2113140629Srwatson
2114172955Srwatson	if (!mls_dominate_effective(subj, obj))
2115140629Srwatson		return (EACCES);
2116140629Srwatson
2117140629Srwatson	return (0);
2118140629Srwatson}
2119140629Srwatson
2120140629Srwatsonstatic int
2121172955Srwatsonmls_sysvmsq_check_msgrmid(struct ucred *cred, struct msg *msgptr,
2122140629Srwatson    struct label *msglabel)
2123140629Srwatson{
2124140629Srwatson	struct mac_mls *subj, *obj;
2125140629Srwatson
2126172955Srwatson	if (!mls_enabled)
2127140629Srwatson		return (0);
2128140629Srwatson
2129140629Srwatson	subj = SLOT(cred->cr_label);
2130140629Srwatson	obj = SLOT(msglabel);
2131140629Srwatson
2132172955Srwatson	if (!mls_dominate_effective(obj, subj))
2133140629Srwatson		return (EACCES);
2134140629Srwatson
2135140629Srwatson	return (0);
2136140629Srwatson}
2137140629Srwatson
2138140629Srwatsonstatic int
2139172955Srwatsonmls_sysvmsq_check_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
2140172955Srwatson    struct label *msqklabel)
2141140629Srwatson{
2142140629Srwatson	struct mac_mls *subj, *obj;
2143140629Srwatson
2144172955Srwatson	if (!mls_enabled)
2145140629Srwatson		return (0);
2146140629Srwatson
2147140629Srwatson	subj = SLOT(cred->cr_label);
2148140629Srwatson	obj = SLOT(msqklabel);
2149140629Srwatson
2150172955Srwatson	if (!mls_dominate_effective(subj, obj))
2151140629Srwatson		return (EACCES);
2152140629Srwatson
2153140629Srwatson	return (0);
2154140629Srwatson}
2155140629Srwatson
2156140629Srwatsonstatic int
2157172955Srwatsonmls_sysvmsq_check_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
2158172955Srwatson    struct label *msqklabel)
2159140629Srwatson{
2160140629Srwatson	struct mac_mls *subj, *obj;
2161140629Srwatson
2162172955Srwatson	if (!mls_enabled)
2163140629Srwatson		return (0);
2164140629Srwatson
2165140629Srwatson	subj = SLOT(cred->cr_label);
2166140629Srwatson	obj = SLOT(msqklabel);
2167140629Srwatson
2168172955Srwatson	if (!mls_dominate_effective(obj, subj))
2169140629Srwatson		return (EACCES);
2170140629Srwatson
2171140629Srwatson	return (0);
2172140629Srwatson}
2173140629Srwatson
2174140629Srwatsonstatic int
2175172955Srwatsonmls_sysvmsq_check_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
2176172955Srwatson    struct label *msqklabel)
2177140629Srwatson{
2178140629Srwatson	struct mac_mls *subj, *obj;
2179140629Srwatson
2180172955Srwatson	if (!mls_enabled)
2181140629Srwatson		return (0);
2182140629Srwatson
2183140629Srwatson	subj = SLOT(cred->cr_label);
2184140629Srwatson	obj = SLOT(msqklabel);
2185140629Srwatson
2186172955Srwatson	if (!mls_dominate_effective(subj, obj))
2187140629Srwatson		return (EACCES);
2188140629Srwatson
2189140629Srwatson	return (0);
2190140629Srwatson}
2191140629Srwatson
2192140629Srwatsonstatic int
2193172955Srwatsonmls_sysvmsq_check_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
2194172955Srwatson    struct label *msqklabel, int cmd)
2195140629Srwatson{
2196140629Srwatson	struct mac_mls *subj, *obj;
2197140629Srwatson
2198172955Srwatson	if (!mls_enabled)
2199140629Srwatson		return (0);
2200140629Srwatson
2201140629Srwatson	subj = SLOT(cred->cr_label);
2202140629Srwatson	obj = SLOT(msqklabel);
2203140629Srwatson
2204140629Srwatson	switch(cmd) {
2205140629Srwatson	case IPC_RMID:
2206140629Srwatson	case IPC_SET:
2207172955Srwatson		if (!mls_dominate_effective(obj, subj))
2208140629Srwatson			return (EACCES);
2209140629Srwatson		break;
2210140629Srwatson
2211140629Srwatson	case IPC_STAT:
2212172955Srwatson		if (!mls_dominate_effective(subj, obj))
2213140629Srwatson			return (EACCES);
2214140629Srwatson		break;
2215140629Srwatson
2216140629Srwatson	default:
2217140629Srwatson		return (EACCES);
2218140629Srwatson	}
2219140629Srwatson
2220140629Srwatson	return (0);
2221140629Srwatson}
2222140629Srwatson
2223173138Srwatsonstatic void
2224173138Srwatsonmls_sysvmsq_cleanup(struct label *msqlabel)
2225173138Srwatson{
2226173138Srwatson
2227173138Srwatson	bzero(SLOT(msqlabel), sizeof(struct mac_mls));
2228173138Srwatson}
2229173138Srwatson
2230173138Srwatsonstatic void
2231173138Srwatsonmls_sysvmsq_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2232173138Srwatson    struct label *msqlabel)
2233173138Srwatson{
2234173138Srwatson	struct mac_mls *source, *dest;
2235173138Srwatson
2236173138Srwatson	source = SLOT(cred->cr_label);
2237173138Srwatson	dest = SLOT(msqlabel);
2238173138Srwatson
2239173138Srwatson	mls_copy_effective(source, dest);
2240173138Srwatson}
2241173138Srwatson
2242140629Srwatsonstatic int
2243172955Srwatsonmls_sysvsem_check_semctl(struct ucred *cred, struct semid_kernel *semakptr,
2244172955Srwatson    struct label *semaklabel, int cmd)
2245140629Srwatson{
2246140629Srwatson	struct mac_mls *subj, *obj;
2247140629Srwatson
2248172955Srwatson	if (!mls_enabled)
2249140629Srwatson		return (0);
2250140629Srwatson
2251140629Srwatson	subj = SLOT(cred->cr_label);
2252140629Srwatson	obj = SLOT(semaklabel);
2253140629Srwatson
2254140629Srwatson	switch(cmd) {
2255140629Srwatson	case IPC_RMID:
2256140629Srwatson	case IPC_SET:
2257140629Srwatson	case SETVAL:
2258140629Srwatson	case SETALL:
2259172955Srwatson		if (!mls_dominate_effective(obj, subj))
2260140629Srwatson			return (EACCES);
2261140629Srwatson		break;
2262140629Srwatson
2263140629Srwatson	case IPC_STAT:
2264140629Srwatson	case GETVAL:
2265140629Srwatson	case GETPID:
2266140629Srwatson	case GETNCNT:
2267140629Srwatson	case GETZCNT:
2268140629Srwatson	case GETALL:
2269172955Srwatson		if (!mls_dominate_effective(subj, obj))
2270140629Srwatson			return (EACCES);
2271140629Srwatson		break;
2272140629Srwatson
2273140629Srwatson	default:
2274140629Srwatson		return (EACCES);
2275140629Srwatson	}
2276140629Srwatson
2277140629Srwatson	return (0);
2278140629Srwatson}
2279140629Srwatson
2280140629Srwatsonstatic int
2281172955Srwatsonmls_sysvsem_check_semget(struct ucred *cred, struct semid_kernel *semakptr,
2282172955Srwatson    struct label *semaklabel)
2283140629Srwatson{
2284140629Srwatson	struct mac_mls *subj, *obj;
2285140629Srwatson
2286172955Srwatson	if (!mls_enabled)
2287140629Srwatson		return (0);
2288140629Srwatson
2289140629Srwatson	subj = SLOT(cred->cr_label);
2290140629Srwatson	obj = SLOT(semaklabel);
2291140629Srwatson
2292172955Srwatson	if (!mls_dominate_effective(subj, obj))
2293140629Srwatson		return (EACCES);
2294140629Srwatson
2295140629Srwatson	return (0);
2296140629Srwatson}
2297140629Srwatson
2298140629Srwatsonstatic int
2299172955Srwatsonmls_sysvsem_check_semop(struct ucred *cred, struct semid_kernel *semakptr,
2300172955Srwatson    struct label *semaklabel, size_t accesstype)
2301140629Srwatson{
2302140629Srwatson	struct mac_mls *subj, *obj;
2303140629Srwatson
2304172955Srwatson	if (!mls_enabled)
2305140629Srwatson		return (0);
2306140629Srwatson
2307140629Srwatson	subj = SLOT(cred->cr_label);
2308140629Srwatson	obj = SLOT(semaklabel);
2309140629Srwatson
2310140629Srwatson	if( accesstype & SEM_R )
2311172955Srwatson		if (!mls_dominate_effective(subj, obj))
2312140629Srwatson			return (EACCES);
2313140629Srwatson
2314140629Srwatson	if( accesstype & SEM_A )
2315172955Srwatson		if (!mls_dominate_effective(obj, subj))
2316140629Srwatson			return (EACCES);
2317140629Srwatson
2318140629Srwatson	return (0);
2319140629Srwatson}
2320140629Srwatson
2321173138Srwatsonstatic void
2322173138Srwatsonmls_sysvsem_cleanup(struct label *semalabel)
2323173138Srwatson{
2324173138Srwatson
2325173138Srwatson	bzero(SLOT(semalabel), sizeof(struct mac_mls));
2326173138Srwatson}
2327173138Srwatson
2328173138Srwatsonstatic void
2329173138Srwatsonmls_sysvsem_create(struct ucred *cred, struct semid_kernel *semakptr,
2330173138Srwatson    struct label *semalabel)
2331173138Srwatson{
2332173138Srwatson	struct mac_mls *source, *dest;
2333173138Srwatson
2334173138Srwatson	source = SLOT(cred->cr_label);
2335173138Srwatson	dest = SLOT(semalabel);
2336173138Srwatson
2337173138Srwatson	mls_copy_effective(source, dest);
2338173138Srwatson}
2339173138Srwatson
2340140629Srwatsonstatic int
2341172955Srwatsonmls_sysvshm_check_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
2342172955Srwatson    struct label *shmseglabel, int shmflg)
2343140629Srwatson{
2344140629Srwatson	struct mac_mls *subj, *obj;
2345140629Srwatson
2346172955Srwatson	if (!mls_enabled)
2347140629Srwatson		return (0);
2348140629Srwatson
2349140629Srwatson	subj = SLOT(cred->cr_label);
2350140629Srwatson	obj = SLOT(shmseglabel);
2351140629Srwatson
2352172955Srwatson	if (!mls_dominate_effective(subj, obj))
2353172955Srwatson		return (EACCES);
2354172955Srwatson	if ((shmflg & SHM_RDONLY) == 0) {
2355172955Srwatson		if (!mls_dominate_effective(obj, subj))
2356140629Srwatson			return (EACCES);
2357172955Srwatson	}
2358140629Srwatson
2359140629Srwatson	return (0);
2360140629Srwatson}
2361140629Srwatson
2362140629Srwatsonstatic int
2363172955Srwatsonmls_sysvshm_check_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
2364172955Srwatson    struct label *shmseglabel, int cmd)
2365140629Srwatson{
2366140629Srwatson	struct mac_mls *subj, *obj;
2367140629Srwatson
2368172955Srwatson	if (!mls_enabled)
2369140629Srwatson		return (0);
2370140629Srwatson
2371140629Srwatson	subj = SLOT(cred->cr_label);
2372140629Srwatson	obj = SLOT(shmseglabel);
2373140629Srwatson
2374140629Srwatson	switch(cmd) {
2375140629Srwatson	case IPC_RMID:
2376140629Srwatson	case IPC_SET:
2377172955Srwatson		if (!mls_dominate_effective(obj, subj))
2378140629Srwatson			return (EACCES);
2379140629Srwatson		break;
2380140629Srwatson
2381140629Srwatson	case IPC_STAT:
2382140629Srwatson	case SHM_STAT:
2383172955Srwatson		if (!mls_dominate_effective(subj, obj))
2384140629Srwatson			return (EACCES);
2385140629Srwatson		break;
2386140629Srwatson
2387140629Srwatson	default:
2388140629Srwatson		return (EACCES);
2389140629Srwatson	}
2390140629Srwatson
2391140629Srwatson	return (0);
2392140629Srwatson}
2393140629Srwatson
2394140629Srwatsonstatic int
2395172955Srwatsonmls_sysvshm_check_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
2396172955Srwatson    struct label *shmseglabel, int shmflg)
2397140629Srwatson{
2398140629Srwatson	struct mac_mls *subj, *obj;
2399140629Srwatson
2400172955Srwatson	if (!mls_enabled)
2401140629Srwatson		return (0);
2402140629Srwatson
2403140629Srwatson	subj = SLOT(cred->cr_label);
2404140629Srwatson	obj = SLOT(shmseglabel);
2405140629Srwatson
2406172955Srwatson	if (!mls_dominate_effective(obj, subj))
2407140629Srwatson		return (EACCES);
2408140629Srwatson
2409140629Srwatson	return (0);
2410140629Srwatson}
2411140629Srwatson
2412173138Srwatsonstatic void
2413173138Srwatsonmls_sysvshm_cleanup(struct label *shmlabel)
2414101099Srwatson{
2415101099Srwatson
2416173138Srwatson	bzero(SLOT(shmlabel), sizeof(struct mac_mls));
2417101099Srwatson}
2418101099Srwatson
2419173138Srwatsonstatic void
2420173138Srwatsonmls_sysvshm_create(struct ucred *cred, struct shmid_kernel *shmsegptr,
2421173138Srwatson    struct label *shmlabel)
2422101099Srwatson{
2423173138Srwatson	struct mac_mls *source, *dest;
2424103759Srwatson
2425173138Srwatson	source = SLOT(cred->cr_label);
2426173138Srwatson	dest = SLOT(shmlabel);
2427101099Srwatson
2428173138Srwatson	mls_copy_effective(source, dest);
2429101099Srwatson}
2430101099Srwatson
2431101099Srwatsonstatic int
2432173138Srwatsonmls_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2433173138Srwatson    struct vnode *vp, struct label *vplabel)
2434101099Srwatson{
2435173138Srwatson	struct mac_mls mm_temp, *source, *dest;
2436173138Srwatson	int buflen, error;
2437101099Srwatson
2438173138Srwatson	source = SLOT(mplabel);
2439173138Srwatson	dest = SLOT(vplabel);
2440101099Srwatson
2441173138Srwatson	buflen = sizeof(mm_temp);
2442173138Srwatson	bzero(&mm_temp, buflen);
2443101099Srwatson
2444173138Srwatson	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2445173138Srwatson	    MAC_MLS_EXTATTR_NAME, &buflen, (char *) &mm_temp, curthread);
2446173138Srwatson	if (error == ENOATTR || error == EOPNOTSUPP) {
2447173138Srwatson		/* Fall back to the mntlabel. */
2448173138Srwatson		mls_copy_effective(source, dest);
2449102115Srwatson		return (0);
2450173138Srwatson	} else if (error)
2451105634Srwatson		return (error);
2452101099Srwatson
2453173138Srwatson	if (buflen != sizeof(mm_temp)) {
2454173138Srwatson		printf("mls_vnode_associate_extattr: bad size %d\n", buflen);
2455101099Srwatson		return (EPERM);
2456105634Srwatson	}
2457173138Srwatson	if (mls_valid(&mm_temp) != 0) {
2458173138Srwatson		printf("mls_vnode_associate_extattr: invalid\n");
2459101099Srwatson		return (EPERM);
2460105634Srwatson	}
2461173138Srwatson	if ((mm_temp.mm_flags & MAC_MLS_FLAGS_BOTH) !=
2462173138Srwatson	    MAC_MLS_FLAG_EFFECTIVE) {
2463173138Srwatson		printf("mls_associated_vnode_extattr: not effective\n");
2464173138Srwatson		return (EPERM);
2465173138Srwatson	}
2466105634Srwatson
2467173138Srwatson	mls_copy_effective(&mm_temp, dest);
2468101099Srwatson	return (0);
2469101099Srwatson}
2470101099Srwatson
2471173138Srwatsonstatic void
2472173138Srwatsonmls_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2473173138Srwatson    struct vnode *vp, struct label *vplabel)
2474101099Srwatson{
2475173138Srwatson	struct mac_mls *source, *dest;
2476101099Srwatson
2477173138Srwatson	source = SLOT(mplabel);
2478173138Srwatson	dest = SLOT(vplabel);
2479101099Srwatson
2480173138Srwatson	mls_copy_effective(source, dest);
2481101099Srwatson}
2482101099Srwatson
2483101099Srwatsonstatic int
2484172955Srwatsonmls_vnode_check_chdir(struct ucred *cred, struct vnode *dvp,
2485168976Srwatson    struct label *dvplabel)
2486101099Srwatson{
2487101099Srwatson	struct mac_mls *subj, *obj;
2488101099Srwatson
2489172955Srwatson	if (!mls_enabled)
2490101099Srwatson		return (0);
2491101099Srwatson
2492122524Srwatson	subj = SLOT(cred->cr_label);
2493168976Srwatson	obj = SLOT(dvplabel);
2494101099Srwatson
2495172955Srwatson	if (!mls_dominate_effective(subj, obj))
2496101099Srwatson		return (EACCES);
2497101099Srwatson
2498101099Srwatson	return (0);
2499101099Srwatson}
2500101099Srwatson
2501101099Srwatsonstatic int
2502172955Srwatsonmls_vnode_check_chroot(struct ucred *cred, struct vnode *dvp,
2503168976Srwatson    struct label *dvplabel)
2504101099Srwatson{
2505101099Srwatson	struct mac_mls *subj, *obj;
2506101099Srwatson
2507172955Srwatson	if (!mls_enabled)
2508101099Srwatson		return (0);
2509101099Srwatson
2510122524Srwatson	subj = SLOT(cred->cr_label);
2511168976Srwatson	obj = SLOT(dvplabel);
2512101099Srwatson
2513172955Srwatson	if (!mls_dominate_effective(subj, obj))
2514101099Srwatson		return (EACCES);
2515101099Srwatson
2516101099Srwatson	return (0);
2517101099Srwatson}
2518101099Srwatson
2519101099Srwatsonstatic int
2520172955Srwatsonmls_vnode_check_create(struct ucred *cred, struct vnode *dvp,
2521168976Srwatson    struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2522101099Srwatson{
2523101099Srwatson	struct mac_mls *subj, *obj;
2524101099Srwatson
2525172955Srwatson	if (!mls_enabled)
2526101099Srwatson		return (0);
2527101099Srwatson
2528122524Srwatson	subj = SLOT(cred->cr_label);
2529168976Srwatson	obj = SLOT(dvplabel);
2530101099Srwatson
2531172955Srwatson	if (!mls_dominate_effective(obj, subj))
2532101099Srwatson		return (EACCES);
2533101099Srwatson
2534101099Srwatson	return (0);
2535101099Srwatson}
2536101099Srwatson
2537101099Srwatsonstatic int
2538172955Srwatsonmls_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
2539168976Srwatson    struct label *vplabel, acl_type_t type)
2540101099Srwatson{
2541101099Srwatson	struct mac_mls *subj, *obj;
2542101099Srwatson
2543172955Srwatson	if (!mls_enabled)
2544101099Srwatson		return (0);
2545101099Srwatson
2546122524Srwatson	subj = SLOT(cred->cr_label);
2547168976Srwatson	obj = SLOT(vplabel);
2548101099Srwatson
2549172955Srwatson	if (!mls_dominate_effective(obj, subj))
2550101099Srwatson		return (EACCES);
2551101099Srwatson
2552101099Srwatson	return (0);
2553101099Srwatson}
2554101099Srwatson
2555101099Srwatsonstatic int
2556172955Srwatsonmls_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
2557168976Srwatson    struct label *vplabel, int attrnamespace, const char *name)
2558119202Srwatson{
2559119202Srwatson	struct mac_mls *subj, *obj;
2560119202Srwatson
2561172955Srwatson	if (!mls_enabled)
2562119202Srwatson		return (0);
2563119202Srwatson
2564122524Srwatson	subj = SLOT(cred->cr_label);
2565168976Srwatson	obj = SLOT(vplabel);
2566119202Srwatson
2567172955Srwatson	if (!mls_dominate_effective(obj, subj))
2568119202Srwatson		return (EACCES);
2569119202Srwatson
2570119202Srwatson	return (0);
2571119202Srwatson}
2572119202Srwatson
2573119202Srwatsonstatic int
2574172955Srwatsonmls_vnode_check_exec(struct ucred *cred, struct vnode *vp,
2575168976Srwatson    struct label *vplabel, struct image_params *imgp,
2576106648Srwatson    struct label *execlabel)
2577101099Srwatson{
2578106648Srwatson	struct mac_mls *subj, *obj, *exec;
2579106648Srwatson	int error;
2580101099Srwatson
2581106648Srwatson	if (execlabel != NULL) {
2582106648Srwatson		/*
2583106648Srwatson		 * We currently don't permit labels to be changed at
2584172955Srwatson		 * exec-time as part of MLS, so disallow non-NULL MLS label
2585172955Srwatson		 * elements in the execlabel.
2586106648Srwatson		 */
2587106648Srwatson		exec = SLOT(execlabel);
2588106648Srwatson		error = mls_atmostflags(exec, 0);
2589106648Srwatson		if (error)
2590106648Srwatson			return (error);
2591106648Srwatson	}
2592106648Srwatson
2593172955Srwatson	if (!mls_enabled)
2594101099Srwatson		return (0);
2595101099Srwatson
2596122524Srwatson	subj = SLOT(cred->cr_label);
2597168976Srwatson	obj = SLOT(vplabel);
2598101099Srwatson
2599172955Srwatson	if (!mls_dominate_effective(subj, obj))
2600101099Srwatson		return (EACCES);
2601101099Srwatson
2602101099Srwatson	return (0);
2603101099Srwatson}
2604101099Srwatson
2605101099Srwatsonstatic int
2606172955Srwatsonmls_vnode_check_getacl(struct ucred *cred, struct vnode *vp,
2607168976Srwatson    struct label *vplabel, acl_type_t type)
2608101099Srwatson{
2609101099Srwatson	struct mac_mls *subj, *obj;
2610101099Srwatson
2611172955Srwatson	if (!mls_enabled)
2612101099Srwatson		return (0);
2613101099Srwatson
2614122524Srwatson	subj = SLOT(cred->cr_label);
2615168976Srwatson	obj = SLOT(vplabel);
2616101099Srwatson
2617172955Srwatson	if (!mls_dominate_effective(subj, obj))
2618101099Srwatson		return (EACCES);
2619101099Srwatson
2620101099Srwatson	return (0);
2621101099Srwatson}
2622101099Srwatson
2623101099Srwatsonstatic int
2624172955Srwatsonmls_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
2625189533Srwatson    struct label *vplabel, int attrnamespace, const char *name)
2626101099Srwatson{
2627101099Srwatson	struct mac_mls *subj, *obj;
2628101099Srwatson
2629172955Srwatson	if (!mls_enabled)
2630101099Srwatson		return (0);
2631101099Srwatson
2632122524Srwatson	subj = SLOT(cred->cr_label);
2633168976Srwatson	obj = SLOT(vplabel);
2634101099Srwatson
2635172955Srwatson	if (!mls_dominate_effective(subj, obj))
2636101099Srwatson		return (EACCES);
2637101099Srwatson
2638101099Srwatson	return (0);
2639101099Srwatson}
2640101099Srwatson
2641105634Srwatsonstatic int
2642172955Srwatsonmls_vnode_check_link(struct ucred *cred, struct vnode *dvp,
2643168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2644104530Srwatson    struct componentname *cnp)
2645104530Srwatson{
2646104530Srwatson	struct mac_mls *subj, *obj;
2647104530Srwatson
2648172955Srwatson	if (!mls_enabled)
2649104530Srwatson		return (0);
2650104530Srwatson
2651122524Srwatson	subj = SLOT(cred->cr_label);
2652168976Srwatson	obj = SLOT(dvplabel);
2653104530Srwatson
2654172955Srwatson	if (!mls_dominate_effective(obj, subj))
2655104530Srwatson		return (EACCES);
2656104530Srwatson
2657171555Srwatson	obj = SLOT(vplabel);
2658172955Srwatson	if (!mls_dominate_effective(obj, subj))
2659104530Srwatson		return (EACCES);
2660104530Srwatson
2661104530Srwatson	return (0);
2662104530Srwatson}
2663104530Srwatson
2664101099Srwatsonstatic int
2665172955Srwatsonmls_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
2666168976Srwatson    struct label *vplabel, int attrnamespace)
2667119202Srwatson{
2668119202Srwatson
2669119202Srwatson	struct mac_mls *subj, *obj;
2670119202Srwatson
2671172955Srwatson	if (!mls_enabled)
2672119202Srwatson		return (0);
2673119202Srwatson
2674122524Srwatson	subj = SLOT(cred->cr_label);
2675168976Srwatson	obj = SLOT(vplabel);
2676119202Srwatson
2677172955Srwatson	if (!mls_dominate_effective(subj, obj))
2678119202Srwatson		return (EACCES);
2679119202Srwatson
2680119202Srwatson	return (0);
2681119202Srwatson}
2682119202Srwatson
2683119202Srwatsonstatic int
2684172955Srwatsonmls_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
2685168976Srwatson    struct label *dvplabel, struct componentname *cnp)
2686101099Srwatson{
2687101099Srwatson	struct mac_mls *subj, *obj;
2688103759Srwatson
2689172955Srwatson	if (!mls_enabled)
2690101099Srwatson		return (0);
2691103759Srwatson
2692122524Srwatson	subj = SLOT(cred->cr_label);
2693168976Srwatson	obj = SLOT(dvplabel);
2694103759Srwatson
2695172955Srwatson	if (!mls_dominate_effective(subj, obj))
2696101099Srwatson		return (EACCES);
2697101099Srwatson
2698103759Srwatson	return (0);
2699101099Srwatson}
2700101099Srwatson
2701101099Srwatsonstatic int
2702172955Srwatsonmls_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
2703168976Srwatson    struct label *vplabel, int prot, int flags)
2704104546Srwatson{
2705104546Srwatson	struct mac_mls *subj, *obj;
2706104546Srwatson
2707104546Srwatson	/*
2708104546Srwatson	 * Rely on the use of open()-time protections to handle
2709104546Srwatson	 * non-revocation cases.
2710104546Srwatson	 */
2711172955Srwatson	if (!mls_enabled || !revocation_enabled)
2712104546Srwatson		return (0);
2713104546Srwatson
2714122524Srwatson	subj = SLOT(cred->cr_label);
2715168976Srwatson	obj = SLOT(vplabel);
2716104546Srwatson
2717104546Srwatson	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2718172955Srwatson		if (!mls_dominate_effective(subj, obj))
2719104546Srwatson			return (EACCES);
2720104546Srwatson	}
2721145076Scsjp	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2722172955Srwatson		if (!mls_dominate_effective(obj, subj))
2723104546Srwatson			return (EACCES);
2724104546Srwatson	}
2725104546Srwatson
2726105634Srwatson	return (0);
2727104546Srwatson}
2728104546Srwatson
2729104546Srwatsonstatic int
2730172955Srwatsonmls_vnode_check_open(struct ucred *cred, struct vnode *vp,
2731184413Strasz    struct label *vplabel, accmode_t accmode)
2732101099Srwatson{
2733101099Srwatson	struct mac_mls *subj, *obj;
2734101099Srwatson
2735172955Srwatson	if (!mls_enabled)
2736101099Srwatson		return (0);
2737101099Srwatson
2738122524Srwatson	subj = SLOT(cred->cr_label);
2739168976Srwatson	obj = SLOT(vplabel);
2740101099Srwatson
2741101099Srwatson	/* XXX privilege override for admin? */
2742190524Strasz	if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
2743172955Srwatson		if (!mls_dominate_effective(subj, obj))
2744101099Srwatson			return (EACCES);
2745101099Srwatson	}
2746190524Strasz	if (accmode & VMODIFY_PERMS) {
2747172955Srwatson		if (!mls_dominate_effective(obj, subj))
2748101099Srwatson			return (EACCES);
2749101099Srwatson	}
2750101099Srwatson
2751101099Srwatson	return (0);
2752101099Srwatson}
2753101099Srwatson
2754101099Srwatsonstatic int
2755172955Srwatsonmls_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
2756168976Srwatson    struct vnode *vp, struct label *vplabel)
2757102112Srwatson{
2758102112Srwatson	struct mac_mls *subj, *obj;
2759102112Srwatson
2760172955Srwatson	if (!mls_enabled || !revocation_enabled)
2761102112Srwatson		return (0);
2762102112Srwatson
2763122524Srwatson	subj = SLOT(active_cred->cr_label);
2764168976Srwatson	obj = SLOT(vplabel);
2765102112Srwatson
2766172955Srwatson	if (!mls_dominate_effective(subj, obj))
2767102112Srwatson		return (EACCES);
2768102112Srwatson
2769102112Srwatson	return (0);
2770102112Srwatson}
2771102112Srwatson
2772102112Srwatsonstatic int
2773172955Srwatsonmls_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
2774168976Srwatson    struct vnode *vp, struct label *vplabel)
2775102112Srwatson{
2776102112Srwatson	struct mac_mls *subj, *obj;
2777102112Srwatson
2778172955Srwatson	if (!mls_enabled || !revocation_enabled)
2779102112Srwatson		return (0);
2780102112Srwatson
2781122524Srwatson	subj = SLOT(active_cred->cr_label);
2782168976Srwatson	obj = SLOT(vplabel);
2783102112Srwatson
2784172955Srwatson	if (!mls_dominate_effective(subj, obj))
2785102112Srwatson		return (EACCES);
2786102112Srwatson
2787102112Srwatson	return (0);
2788102112Srwatson}
2789102112Srwatson
2790102112Srwatsonstatic int
2791172955Srwatsonmls_vnode_check_readdir(struct ucred *cred, struct vnode *dvp,
2792168976Srwatson    struct label *dvplabel)
2793101099Srwatson{
2794101099Srwatson	struct mac_mls *subj, *obj;
2795101099Srwatson
2796172955Srwatson	if (!mls_enabled)
2797101099Srwatson		return (0);
2798101099Srwatson
2799122524Srwatson	subj = SLOT(cred->cr_label);
2800168976Srwatson	obj = SLOT(dvplabel);
2801101099Srwatson
2802172955Srwatson	if (!mls_dominate_effective(subj, obj))
2803101099Srwatson		return (EACCES);
2804101099Srwatson
2805101099Srwatson	return (0);
2806101099Srwatson}
2807101099Srwatson
2808101099Srwatsonstatic int
2809172955Srwatsonmls_vnode_check_readlink(struct ucred *cred, struct vnode *vp,
2810168976Srwatson    struct label *vplabel)
2811101099Srwatson{
2812101099Srwatson	struct mac_mls *subj, *obj;
2813101099Srwatson
2814172955Srwatson	if (!mls_enabled)
2815101099Srwatson		return (0);
2816101099Srwatson
2817122524Srwatson	subj = SLOT(cred->cr_label);
2818168976Srwatson	obj = SLOT(vplabel);
2819101099Srwatson
2820172955Srwatson	if (!mls_dominate_effective(subj, obj))
2821101099Srwatson		return (EACCES);
2822101099Srwatson
2823101099Srwatson	return (0);
2824101099Srwatson}
2825101099Srwatson
2826101099Srwatsonstatic int
2827172955Srwatsonmls_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
2828168976Srwatson    struct label *vplabel, struct label *newlabel)
2829101099Srwatson{
2830101099Srwatson	struct mac_mls *old, *new, *subj;
2831105634Srwatson	int error;
2832101099Srwatson
2833168976Srwatson	old = SLOT(vplabel);
2834101099Srwatson	new = SLOT(newlabel);
2835122524Srwatson	subj = SLOT(cred->cr_label);
2836101099Srwatson
2837101099Srwatson	/*
2838105634Srwatson	 * If there is an MLS label update for the vnode, it must be a
2839132232Srwatson	 * effective label.
2840101099Srwatson	 */
2841132232Srwatson	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2842105634Srwatson	if (error)
2843105634Srwatson		return (error);
2844101099Srwatson
2845101099Srwatson	/*
2846105634Srwatson	 * To perform a relabel of the vnode (MLS label or not), MLS must
2847105634Srwatson	 * authorize the relabel.
2848101099Srwatson	 */
2849172955Srwatson	if (!mls_effective_in_range(old, subj))
2850101099Srwatson		return (EPERM);
2851101099Srwatson
2852101099Srwatson	/*
2853105634Srwatson	 * If the MLS label is to be changed, authorize as appropriate.
2854101099Srwatson	 */
2855132232Srwatson	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2856105634Srwatson		/*
2857105634Srwatson		 * To change the MLS label on a vnode, the new vnode label
2858105634Srwatson		 * must be in the subject range.
2859105634Srwatson		 */
2860172955Srwatson		if (!mls_effective_in_range(new, subj))
2861105634Srwatson			return (EPERM);
2862101099Srwatson
2863105634Srwatson		/*
2864172955Srwatson		 * To change the MLS label on the vnode to be EQUAL, the
2865172955Srwatson		 * subject must have appropriate privilege.
2866105634Srwatson		 */
2867172955Srwatson		if (mls_contains_equal(new)) {
2868172955Srwatson			error = mls_subject_privileged(subj);
2869105634Srwatson			if (error)
2870105634Srwatson				return (error);
2871105634Srwatson		}
2872105634Srwatson	}
2873105634Srwatson
2874105634Srwatson	return (0);
2875101099Srwatson}
2876101099Srwatson
2877101099Srwatsonstatic int
2878172955Srwatsonmls_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
2879168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2880101099Srwatson    struct componentname *cnp)
2881101099Srwatson{
2882101099Srwatson	struct mac_mls *subj, *obj;
2883101099Srwatson
2884172955Srwatson	if (!mls_enabled)
2885101099Srwatson		return (0);
2886101099Srwatson
2887122524Srwatson	subj = SLOT(cred->cr_label);
2888168976Srwatson	obj = SLOT(dvplabel);
2889101099Srwatson
2890172955Srwatson	if (!mls_dominate_effective(obj, subj))
2891101099Srwatson		return (EACCES);
2892101099Srwatson
2893168976Srwatson	obj = SLOT(vplabel);
2894101099Srwatson
2895172955Srwatson	if (!mls_dominate_effective(obj, subj))
2896101099Srwatson		return (EACCES);
2897101099Srwatson
2898101099Srwatson	return (0);
2899101099Srwatson}
2900101099Srwatson
2901101099Srwatsonstatic int
2902172955Srwatsonmls_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
2903168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2904168976Srwatson    int samedir, struct componentname *cnp)
2905101099Srwatson{
2906101099Srwatson	struct mac_mls *subj, *obj;
2907101099Srwatson
2908172955Srwatson	if (!mls_enabled)
2909101099Srwatson		return (0);
2910101099Srwatson
2911122524Srwatson	subj = SLOT(cred->cr_label);
2912168976Srwatson	obj = SLOT(dvplabel);
2913101099Srwatson
2914172955Srwatson	if (!mls_dominate_effective(obj, subj))
2915101099Srwatson		return (EACCES);
2916101099Srwatson
2917101099Srwatson	if (vp != NULL) {
2918168976Srwatson		obj = SLOT(vplabel);
2919101099Srwatson
2920172955Srwatson		if (!mls_dominate_effective(obj, subj))
2921101099Srwatson			return (EACCES);
2922101099Srwatson	}
2923101099Srwatson
2924101099Srwatson	return (0);
2925101099Srwatson}
2926101099Srwatson
2927101099Srwatsonstatic int
2928172955Srwatsonmls_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
2929168976Srwatson    struct label *vplabel)
2930101099Srwatson{
2931101099Srwatson	struct mac_mls *subj, *obj;
2932101099Srwatson
2933172955Srwatson	if (!mls_enabled)
2934101099Srwatson		return (0);
2935101099Srwatson
2936122524Srwatson	subj = SLOT(cred->cr_label);
2937168976Srwatson	obj = SLOT(vplabel);
2938101099Srwatson
2939172955Srwatson	if (!mls_dominate_effective(obj, subj))
2940101099Srwatson		return (EACCES);
2941101099Srwatson
2942101099Srwatson	return (0);
2943101099Srwatson}
2944101099Srwatson
2945101099Srwatsonstatic int
2946172955Srwatsonmls_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
2947168976Srwatson    struct label *vplabel, acl_type_t type, struct acl *acl)
2948101099Srwatson{
2949101099Srwatson	struct mac_mls *subj, *obj;
2950101099Srwatson
2951172955Srwatson	if (!mls_enabled)
2952101099Srwatson		return (0);
2953101099Srwatson
2954122524Srwatson	subj = SLOT(cred->cr_label);
2955168976Srwatson	obj = SLOT(vplabel);
2956101099Srwatson
2957172955Srwatson	if (!mls_dominate_effective(obj, subj))
2958101099Srwatson		return (EACCES);
2959101099Srwatson
2960101099Srwatson	return (0);
2961101099Srwatson}
2962101099Srwatson
2963101099Srwatsonstatic int
2964172955Srwatsonmls_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
2965189533Srwatson    struct label *vplabel, int attrnamespace, const char *name)
2966101099Srwatson{
2967101099Srwatson	struct mac_mls *subj, *obj;
2968101099Srwatson
2969172955Srwatson	if (!mls_enabled)
2970101099Srwatson		return (0);
2971101099Srwatson
2972122524Srwatson	subj = SLOT(cred->cr_label);
2973168976Srwatson	obj = SLOT(vplabel);
2974101099Srwatson
2975172955Srwatson	if (!mls_dominate_effective(obj, subj))
2976101099Srwatson		return (EACCES);
2977101099Srwatson
2978101099Srwatson	/* XXX: protect the MAC EA in a special way? */
2979101099Srwatson
2980101099Srwatson	return (0);
2981101099Srwatson}
2982101099Srwatson
2983101099Srwatsonstatic int
2984172955Srwatsonmls_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
2985168976Srwatson    struct label *vplabel, u_long flags)
2986101099Srwatson{
2987101099Srwatson	struct mac_mls *subj, *obj;
2988101099Srwatson
2989172955Srwatson	if (!mls_enabled)
2990101099Srwatson		return (0);
2991101099Srwatson
2992122524Srwatson	subj = SLOT(cred->cr_label);
2993168976Srwatson	obj = SLOT(vplabel);
2994101099Srwatson
2995172955Srwatson	if (!mls_dominate_effective(obj, subj))
2996101099Srwatson		return (EACCES);
2997101099Srwatson
2998101099Srwatson	return (0);
2999101099Srwatson}
3000101099Srwatson
3001101099Srwatsonstatic int
3002172955Srwatsonmls_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
3003168976Srwatson    struct label *vplabel, mode_t mode)
3004101099Srwatson{
3005101099Srwatson	struct mac_mls *subj, *obj;
3006101099Srwatson
3007172955Srwatson	if (!mls_enabled)
3008101099Srwatson		return (0);
3009101099Srwatson
3010122524Srwatson	subj = SLOT(cred->cr_label);
3011168976Srwatson	obj = SLOT(vplabel);
3012101099Srwatson
3013172955Srwatson	if (!mls_dominate_effective(obj, subj))
3014101099Srwatson		return (EACCES);
3015101099Srwatson
3016101099Srwatson	return (0);
3017101099Srwatson}
3018101099Srwatson
3019101099Srwatsonstatic int
3020172955Srwatsonmls_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
3021168976Srwatson    struct label *vplabel, uid_t uid, gid_t gid)
3022101099Srwatson{
3023101099Srwatson	struct mac_mls *subj, *obj;
3024101099Srwatson
3025172955Srwatson	if (!mls_enabled)
3026101099Srwatson		return (0);
3027101099Srwatson
3028122524Srwatson	subj = SLOT(cred->cr_label);
3029168976Srwatson	obj = SLOT(vplabel);
3030101099Srwatson
3031172955Srwatson	if (!mls_dominate_effective(obj, subj))
3032101099Srwatson		return (EACCES);
3033101099Srwatson
3034101099Srwatson	return (0);
3035101099Srwatson}
3036101099Srwatson
3037101099Srwatsonstatic int
3038172955Srwatsonmls_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
3039168976Srwatson    struct label *vplabel, struct timespec atime, struct timespec mtime)
3040101099Srwatson{
3041101099Srwatson	struct mac_mls *subj, *obj;
3042101099Srwatson
3043172955Srwatson	if (!mls_enabled)
3044101099Srwatson		return (0);
3045101099Srwatson
3046122524Srwatson	subj = SLOT(cred->cr_label);
3047168976Srwatson	obj = SLOT(vplabel);
3048101099Srwatson
3049172955Srwatson	if (!mls_dominate_effective(obj, subj))
3050101099Srwatson		return (EACCES);
3051101099Srwatson
3052101099Srwatson	return (0);
3053101099Srwatson}
3054101099Srwatson
3055101099Srwatsonstatic int
3056172955Srwatsonmls_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred,
3057168976Srwatson    struct vnode *vp, struct label *vplabel)
3058101099Srwatson{
3059101099Srwatson	struct mac_mls *subj, *obj;
3060101099Srwatson
3061172955Srwatson	if (!mls_enabled)
3062101099Srwatson		return (0);
3063101099Srwatson
3064122524Srwatson	subj = SLOT(active_cred->cr_label);
3065168976Srwatson	obj = SLOT(vplabel);
3066101099Srwatson
3067172955Srwatson	if (!mls_dominate_effective(subj, obj))
3068101099Srwatson		return (EACCES);
3069101099Srwatson
3070101099Srwatson	return (0);
3071101099Srwatson}
3072101099Srwatson
3073102112Srwatsonstatic int
3074172955Srwatsonmls_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
3075172107Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
3076172107Srwatson    struct componentname *cnp)
3077172107Srwatson{
3078172107Srwatson	struct mac_mls *subj, *obj;
3079172107Srwatson
3080172955Srwatson	if (!mls_enabled)
3081172107Srwatson		return (0);
3082172107Srwatson
3083172107Srwatson	subj = SLOT(cred->cr_label);
3084172107Srwatson	obj = SLOT(dvplabel);
3085172107Srwatson
3086172955Srwatson	if (!mls_dominate_effective(obj, subj))
3087172107Srwatson		return (EACCES);
3088172107Srwatson
3089172107Srwatson	obj = SLOT(vplabel);
3090172107Srwatson
3091172955Srwatson	if (!mls_dominate_effective(obj, subj))
3092172107Srwatson		return (EACCES);
3093172107Srwatson
3094172107Srwatson	return (0);
3095172107Srwatson}
3096172107Srwatson
3097172107Srwatsonstatic int
3098172955Srwatsonmls_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred,
3099168976Srwatson    struct vnode *vp, struct label *vplabel)
3100102112Srwatson{
3101102112Srwatson	struct mac_mls *subj, *obj;
3102102112Srwatson
3103172955Srwatson	if (!mls_enabled || !revocation_enabled)
3104102112Srwatson		return (0);
3105102112Srwatson
3106122524Srwatson	subj = SLOT(active_cred->cr_label);
3107168976Srwatson	obj = SLOT(vplabel);
3108102112Srwatson
3109172955Srwatson	if (!mls_dominate_effective(obj, subj))
3110102112Srwatson		return (EACCES);
3111102112Srwatson
3112102112Srwatson	return (0);
3113102112Srwatson}
3114102112Srwatson
3115173138Srwatsonstatic int
3116173138Srwatsonmls_vnode_create_extattr(struct ucred *cred, struct mount *mp,
3117173138Srwatson    struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
3118173138Srwatson    struct vnode *vp, struct label *vplabel, struct componentname *cnp)
3119173138Srwatson{
3120173138Srwatson	struct mac_mls *source, *dest, mm_temp;
3121173138Srwatson	size_t buflen;
3122173138Srwatson	int error;
3123173138Srwatson
3124173138Srwatson	buflen = sizeof(mm_temp);
3125173138Srwatson	bzero(&mm_temp, buflen);
3126173138Srwatson
3127173138Srwatson	source = SLOT(cred->cr_label);
3128173138Srwatson	dest = SLOT(vplabel);
3129173138Srwatson	mls_copy_effective(source, &mm_temp);
3130173138Srwatson
3131173138Srwatson	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
3132173138Srwatson	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
3133173138Srwatson	if (error == 0)
3134173138Srwatson		mls_copy_effective(source, dest);
3135173138Srwatson	return (error);
3136173138Srwatson}
3137173138Srwatson
3138173138Srwatsonstatic void
3139173138Srwatsonmls_vnode_relabel(struct ucred *cred, struct vnode *vp,
3140173138Srwatson    struct label *vplabel, struct label *label)
3141173138Srwatson{
3142173138Srwatson	struct mac_mls *source, *dest;
3143173138Srwatson
3144173138Srwatson	source = SLOT(label);
3145173138Srwatson	dest = SLOT(vplabel);
3146173138Srwatson
3147173138Srwatson	mls_copy(source, dest);
3148173138Srwatson}
3149173138Srwatson
3150173138Srwatsonstatic int
3151173138Srwatsonmls_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
3152173138Srwatson    struct label *vplabel, struct label *intlabel)
3153173138Srwatson{
3154173138Srwatson	struct mac_mls *source, mm_temp;
3155173138Srwatson	size_t buflen;
3156173138Srwatson	int error;
3157173138Srwatson
3158173138Srwatson	buflen = sizeof(mm_temp);
3159173138Srwatson	bzero(&mm_temp, buflen);
3160173138Srwatson
3161173138Srwatson	source = SLOT(intlabel);
3162173138Srwatson	if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0)
3163173138Srwatson		return (0);
3164173138Srwatson
3165173138Srwatson	mls_copy_effective(source, &mm_temp);
3166173138Srwatson
3167173138Srwatson	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
3168173138Srwatson	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
3169173138Srwatson	return (error);
3170173138Srwatson}
3171173138Srwatson
3172172955Srwatsonstatic struct mac_policy_ops mls_ops =
3173101099Srwatson{
3174172955Srwatson	.mpo_init = mls_init,
3175173138Srwatson
3176173138Srwatson	.mpo_bpfdesc_check_receive = mls_bpfdesc_check_receive,
3177173138Srwatson	.mpo_bpfdesc_create = mls_bpfdesc_create,
3178173138Srwatson	.mpo_bpfdesc_create_mbuf = mls_bpfdesc_create_mbuf,
3179173138Srwatson	.mpo_bpfdesc_destroy_label = mls_destroy_label,
3180172955Srwatson	.mpo_bpfdesc_init_label = mls_init_label,
3181173138Srwatson
3182184407Srwatson	.mpo_cred_associate_nfsd = mls_cred_associate_nfsd,
3183173138Srwatson	.mpo_cred_check_relabel = mls_cred_check_relabel,
3184173138Srwatson	.mpo_cred_check_visible = mls_cred_check_visible,
3185173138Srwatson	.mpo_cred_copy_label = mls_copy_label,
3186184407Srwatson	.mpo_cred_create_init = mls_cred_create_init,
3187184407Srwatson	.mpo_cred_create_swapper = mls_cred_create_swapper,
3188172955Srwatson	.mpo_cred_destroy_label = mls_destroy_label,
3189172955Srwatson	.mpo_cred_externalize_label = mls_externalize_label,
3190173138Srwatson	.mpo_cred_init_label = mls_init_label,
3191172955Srwatson	.mpo_cred_internalize_label = mls_internalize_label,
3192173138Srwatson	.mpo_cred_relabel = mls_cred_relabel,
3193173138Srwatson
3194172955Srwatson	.mpo_devfs_create_device = mls_devfs_create_device,
3195172955Srwatson	.mpo_devfs_create_directory = mls_devfs_create_directory,
3196172955Srwatson	.mpo_devfs_create_symlink = mls_devfs_create_symlink,
3197173138Srwatson	.mpo_devfs_destroy_label = mls_destroy_label,
3198173138Srwatson	.mpo_devfs_init_label = mls_init_label,
3199172955Srwatson	.mpo_devfs_update = mls_devfs_update,
3200172955Srwatson	.mpo_devfs_vnode_associate = mls_devfs_vnode_associate,
3201173138Srwatson
3202173138Srwatson	.mpo_ifnet_check_relabel = mls_ifnet_check_relabel,
3203173138Srwatson	.mpo_ifnet_check_transmit = mls_ifnet_check_transmit,
3204173138Srwatson	.mpo_ifnet_copy_label = mls_copy_label,
3205172955Srwatson	.mpo_ifnet_create = mls_ifnet_create,
3206173138Srwatson	.mpo_ifnet_create_mbuf = mls_ifnet_create_mbuf,
3207173138Srwatson	.mpo_ifnet_destroy_label = mls_destroy_label,
3208173138Srwatson	.mpo_ifnet_externalize_label = mls_externalize_label,
3209173138Srwatson	.mpo_ifnet_init_label = mls_init_label,
3210173138Srwatson	.mpo_ifnet_internalize_label = mls_internalize_label,
3211173138Srwatson	.mpo_ifnet_relabel = mls_ifnet_relabel,
3212173138Srwatson
3213173138Srwatson	.mpo_inpcb_check_deliver = mls_inpcb_check_deliver,
3214183980Sbz	.mpo_inpcb_check_visible = mls_inpcb_check_visible,
3215172955Srwatson	.mpo_inpcb_create = mls_inpcb_create,
3216173138Srwatson	.mpo_inpcb_create_mbuf = mls_inpcb_create_mbuf,
3217173138Srwatson	.mpo_inpcb_destroy_label = mls_destroy_label,
3218173138Srwatson	.mpo_inpcb_init_label = mls_init_label_waitcheck,
3219173138Srwatson	.mpo_inpcb_sosetlabel = mls_inpcb_sosetlabel,
3220173138Srwatson
3221184308Srwatson	.mpo_ip6q_create = mls_ip6q_create,
3222184308Srwatson	.mpo_ip6q_destroy_label = mls_destroy_label,
3223184308Srwatson	.mpo_ip6q_init_label = mls_init_label_waitcheck,
3224184308Srwatson	.mpo_ip6q_match = mls_ip6q_match,
3225184308Srwatson	.mpo_ip6q_reassemble = mls_ip6q_reassemble,
3226184308Srwatson	.mpo_ip6q_update = mls_ip6q_update,
3227184308Srwatson
3228172955Srwatson	.mpo_ipq_create = mls_ipq_create,
3229173138Srwatson	.mpo_ipq_destroy_label = mls_destroy_label,
3230173138Srwatson	.mpo_ipq_init_label = mls_init_label_waitcheck,
3231172955Srwatson	.mpo_ipq_match = mls_ipq_match,
3232173138Srwatson	.mpo_ipq_reassemble = mls_ipq_reassemble,
3233172955Srwatson	.mpo_ipq_update = mls_ipq_update,
3234173138Srwatson
3235173138Srwatson	.mpo_mbuf_copy_label = mls_copy_label,
3236173138Srwatson	.mpo_mbuf_destroy_label = mls_destroy_label,
3237173138Srwatson	.mpo_mbuf_init_label = mls_init_label_waitcheck,
3238173138Srwatson
3239172955Srwatson	.mpo_mount_check_stat = mls_mount_check_stat,
3240173138Srwatson	.mpo_mount_create = mls_mount_create,
3241173138Srwatson	.mpo_mount_destroy_label = mls_destroy_label,
3242173138Srwatson	.mpo_mount_init_label = mls_init_label,
3243173138Srwatson
3244173138Srwatson	.mpo_netatalk_aarp_send = mls_netatalk_aarp_send,
3245173138Srwatson
3246173138Srwatson	.mpo_netinet_arp_send = mls_netinet_arp_send,
3247173138Srwatson	.mpo_netinet_firewall_reply = mls_netinet_firewall_reply,
3248173138Srwatson	.mpo_netinet_firewall_send = mls_netinet_firewall_send,
3249173138Srwatson	.mpo_netinet_fragment = mls_netinet_fragment,
3250173138Srwatson	.mpo_netinet_icmp_reply = mls_netinet_icmp_reply,
3251173138Srwatson	.mpo_netinet_igmp_send = mls_netinet_igmp_send,
3252173138Srwatson
3253173138Srwatson	.mpo_netinet6_nd6_send = mls_netinet6_nd6_send,
3254173138Srwatson
3255172955Srwatson	.mpo_pipe_check_ioctl = mls_pipe_check_ioctl,
3256172955Srwatson	.mpo_pipe_check_poll = mls_pipe_check_poll,
3257172955Srwatson	.mpo_pipe_check_read = mls_pipe_check_read,
3258172955Srwatson	.mpo_pipe_check_relabel = mls_pipe_check_relabel,
3259172955Srwatson	.mpo_pipe_check_stat = mls_pipe_check_stat,
3260172955Srwatson	.mpo_pipe_check_write = mls_pipe_check_write,
3261173138Srwatson	.mpo_pipe_copy_label = mls_copy_label,
3262173138Srwatson	.mpo_pipe_create = mls_pipe_create,
3263173138Srwatson	.mpo_pipe_destroy_label = mls_destroy_label,
3264173138Srwatson	.mpo_pipe_externalize_label = mls_externalize_label,
3265173138Srwatson	.mpo_pipe_init_label = mls_init_label,
3266173138Srwatson	.mpo_pipe_internalize_label = mls_internalize_label,
3267173138Srwatson	.mpo_pipe_relabel = mls_pipe_relabel,
3268173138Srwatson
3269172955Srwatson	.mpo_posixsem_check_getvalue = mls_posixsem_check_rdonly,
3270180059Sjhb	.mpo_posixsem_check_open = mls_posixsem_check_openunlink,
3271172955Srwatson	.mpo_posixsem_check_post = mls_posixsem_check_write,
3272225344Srwatson	.mpo_posixsem_check_setmode = mls_posixsem_check_setmode,
3273225344Srwatson	.mpo_posixsem_check_setowner = mls_posixsem_check_setowner,
3274180059Sjhb	.mpo_posixsem_check_stat = mls_posixsem_check_rdonly,
3275180059Sjhb	.mpo_posixsem_check_unlink = mls_posixsem_check_openunlink,
3276172955Srwatson	.mpo_posixsem_check_wait = mls_posixsem_check_write,
3277173138Srwatson	.mpo_posixsem_create = mls_posixsem_create,
3278173138Srwatson	.mpo_posixsem_destroy_label = mls_destroy_label,
3279173138Srwatson	.mpo_posixsem_init_label = mls_init_label,
3280173138Srwatson
3281225344Srwatson	.mpo_posixshm_check_mmap = mls_posixshm_check_mmap,
3282225344Srwatson	.mpo_posixshm_check_open = mls_posixshm_check_open,
3283225344Srwatson	.mpo_posixshm_check_setmode = mls_posixshm_check_setmode,
3284225344Srwatson	.mpo_posixshm_check_setowner = mls_posixshm_check_setowner,
3285225344Srwatson	.mpo_posixshm_check_stat = mls_posixshm_check_stat,
3286225344Srwatson	.mpo_posixshm_check_truncate = mls_posixshm_check_truncate,
3287225344Srwatson	.mpo_posixshm_check_unlink = mls_posixshm_check_unlink,
3288225344Srwatson	.mpo_posixshm_create = mls_posixshm_create,
3289225344Srwatson	.mpo_posixshm_destroy_label = mls_destroy_label,
3290225344Srwatson	.mpo_posixshm_init_label = mls_init_label,
3291225344Srwatson
3292172955Srwatson	.mpo_proc_check_debug = mls_proc_check_debug,
3293172955Srwatson	.mpo_proc_check_sched = mls_proc_check_sched,
3294172955Srwatson	.mpo_proc_check_signal = mls_proc_check_signal,
3295173138Srwatson
3296172955Srwatson	.mpo_socket_check_deliver = mls_socket_check_deliver,
3297172955Srwatson	.mpo_socket_check_relabel = mls_socket_check_relabel,
3298172955Srwatson	.mpo_socket_check_visible = mls_socket_check_visible,
3299173138Srwatson	.mpo_socket_copy_label = mls_copy_label,
3300173138Srwatson	.mpo_socket_create = mls_socket_create,
3301173138Srwatson	.mpo_socket_create_mbuf = mls_socket_create_mbuf,
3302173138Srwatson	.mpo_socket_destroy_label = mls_destroy_label,
3303173138Srwatson	.mpo_socket_externalize_label = mls_externalize_label,
3304173138Srwatson	.mpo_socket_init_label = mls_init_label_waitcheck,
3305173138Srwatson	.mpo_socket_internalize_label = mls_internalize_label,
3306173138Srwatson	.mpo_socket_newconn = mls_socket_newconn,
3307173138Srwatson	.mpo_socket_relabel = mls_socket_relabel,
3308173138Srwatson
3309173138Srwatson	.mpo_socketpeer_destroy_label = mls_destroy_label,
3310173138Srwatson	.mpo_socketpeer_externalize_label = mls_externalize_label,
3311173138Srwatson	.mpo_socketpeer_init_label = mls_init_label_waitcheck,
3312173138Srwatson	.mpo_socketpeer_set_from_mbuf = mls_socketpeer_set_from_mbuf,
3313173138Srwatson	.mpo_socketpeer_set_from_socket = mls_socketpeer_set_from_socket,
3314173138Srwatson
3315173138Srwatson	.mpo_syncache_create = mls_syncache_create,
3316173138Srwatson	.mpo_syncache_create_mbuf = mls_syncache_create_mbuf,
3317173138Srwatson	.mpo_syncache_destroy_label = mls_destroy_label,
3318173138Srwatson	.mpo_syncache_init_label = mls_init_label_waitcheck,
3319173138Srwatson
3320173138Srwatson	.mpo_sysvmsg_cleanup = mls_sysvmsg_cleanup,
3321173138Srwatson	.mpo_sysvmsg_create = mls_sysvmsg_create,
3322173138Srwatson	.mpo_sysvmsg_destroy_label = mls_destroy_label,
3323173138Srwatson	.mpo_sysvmsg_init_label = mls_init_label,
3324173138Srwatson
3325173138Srwatson	.mpo_sysvmsq_check_msgrcv = mls_sysvmsq_check_msgrcv,
3326173138Srwatson	.mpo_sysvmsq_check_msgrmid = mls_sysvmsq_check_msgrmid,
3327173138Srwatson	.mpo_sysvmsq_check_msqget = mls_sysvmsq_check_msqget,
3328173138Srwatson	.mpo_sysvmsq_check_msqsnd = mls_sysvmsq_check_msqsnd,
3329173138Srwatson	.mpo_sysvmsq_check_msqrcv = mls_sysvmsq_check_msqrcv,
3330173138Srwatson	.mpo_sysvmsq_check_msqctl = mls_sysvmsq_check_msqctl,
3331173138Srwatson	.mpo_sysvmsq_cleanup = mls_sysvmsq_cleanup,
3332173138Srwatson	.mpo_sysvmsq_destroy_label = mls_destroy_label,
3333173138Srwatson	.mpo_sysvmsq_init_label = mls_init_label,
3334173138Srwatson	.mpo_sysvmsq_create = mls_sysvmsq_create,
3335173138Srwatson
3336173138Srwatson	.mpo_sysvsem_check_semctl = mls_sysvsem_check_semctl,
3337173138Srwatson	.mpo_sysvsem_check_semget = mls_sysvsem_check_semget,
3338173138Srwatson	.mpo_sysvsem_check_semop = mls_sysvsem_check_semop,
3339173138Srwatson	.mpo_sysvsem_cleanup = mls_sysvsem_cleanup,
3340173138Srwatson	.mpo_sysvsem_create = mls_sysvsem_create,
3341173138Srwatson	.mpo_sysvsem_destroy_label = mls_destroy_label,
3342173138Srwatson	.mpo_sysvsem_init_label = mls_init_label,
3343173138Srwatson
3344173138Srwatson	.mpo_sysvshm_check_shmat = mls_sysvshm_check_shmat,
3345173138Srwatson	.mpo_sysvshm_check_shmctl = mls_sysvshm_check_shmctl,
3346173138Srwatson	.mpo_sysvshm_check_shmget = mls_sysvshm_check_shmget,
3347173138Srwatson	.mpo_sysvshm_cleanup = mls_sysvshm_cleanup,
3348173138Srwatson	.mpo_sysvshm_create = mls_sysvshm_create,
3349173138Srwatson	.mpo_sysvshm_destroy_label = mls_destroy_label,
3350173138Srwatson	.mpo_sysvshm_init_label = mls_init_label,
3351173138Srwatson
3352173138Srwatson
3353172955Srwatson	.mpo_system_check_acct = mls_system_check_acct,
3354172955Srwatson	.mpo_system_check_auditctl = mls_system_check_auditctl,
3355172955Srwatson	.mpo_system_check_swapon = mls_system_check_swapon,
3356173138Srwatson
3357173138Srwatson	.mpo_vnode_associate_extattr = mls_vnode_associate_extattr,
3358173138Srwatson	.mpo_vnode_associate_singlelabel = mls_vnode_associate_singlelabel,
3359172955Srwatson	.mpo_vnode_check_access = mls_vnode_check_open,
3360172955Srwatson	.mpo_vnode_check_chdir = mls_vnode_check_chdir,
3361172955Srwatson	.mpo_vnode_check_chroot = mls_vnode_check_chroot,
3362172955Srwatson	.mpo_vnode_check_create = mls_vnode_check_create,
3363172955Srwatson	.mpo_vnode_check_deleteacl = mls_vnode_check_deleteacl,
3364172955Srwatson	.mpo_vnode_check_deleteextattr = mls_vnode_check_deleteextattr,
3365172955Srwatson	.mpo_vnode_check_exec = mls_vnode_check_exec,
3366172955Srwatson	.mpo_vnode_check_getacl = mls_vnode_check_getacl,
3367172955Srwatson	.mpo_vnode_check_getextattr = mls_vnode_check_getextattr,
3368172955Srwatson	.mpo_vnode_check_link = mls_vnode_check_link,
3369172955Srwatson	.mpo_vnode_check_listextattr = mls_vnode_check_listextattr,
3370172955Srwatson	.mpo_vnode_check_lookup = mls_vnode_check_lookup,
3371172955Srwatson	.mpo_vnode_check_mmap = mls_vnode_check_mmap,
3372172955Srwatson	.mpo_vnode_check_open = mls_vnode_check_open,
3373172955Srwatson	.mpo_vnode_check_poll = mls_vnode_check_poll,
3374172955Srwatson	.mpo_vnode_check_read = mls_vnode_check_read,
3375172955Srwatson	.mpo_vnode_check_readdir = mls_vnode_check_readdir,
3376172955Srwatson	.mpo_vnode_check_readlink = mls_vnode_check_readlink,
3377172955Srwatson	.mpo_vnode_check_relabel = mls_vnode_check_relabel,
3378172955Srwatson	.mpo_vnode_check_rename_from = mls_vnode_check_rename_from,
3379172955Srwatson	.mpo_vnode_check_rename_to = mls_vnode_check_rename_to,
3380172955Srwatson	.mpo_vnode_check_revoke = mls_vnode_check_revoke,
3381172955Srwatson	.mpo_vnode_check_setacl = mls_vnode_check_setacl,
3382172955Srwatson	.mpo_vnode_check_setextattr = mls_vnode_check_setextattr,
3383172955Srwatson	.mpo_vnode_check_setflags = mls_vnode_check_setflags,
3384172955Srwatson	.mpo_vnode_check_setmode = mls_vnode_check_setmode,
3385172955Srwatson	.mpo_vnode_check_setowner = mls_vnode_check_setowner,
3386172955Srwatson	.mpo_vnode_check_setutimes = mls_vnode_check_setutimes,
3387172955Srwatson	.mpo_vnode_check_stat = mls_vnode_check_stat,
3388172955Srwatson	.mpo_vnode_check_unlink = mls_vnode_check_unlink,
3389172955Srwatson	.mpo_vnode_check_write = mls_vnode_check_write,
3390173138Srwatson	.mpo_vnode_copy_label = mls_copy_label,
3391173138Srwatson	.mpo_vnode_create_extattr = mls_vnode_create_extattr,
3392173138Srwatson	.mpo_vnode_destroy_label = mls_destroy_label,
3393173138Srwatson	.mpo_vnode_externalize_label = mls_externalize_label,
3394173138Srwatson	.mpo_vnode_init_label = mls_init_label,
3395173138Srwatson	.mpo_vnode_internalize_label = mls_internalize_label,
3396173138Srwatson	.mpo_vnode_relabel = mls_vnode_relabel,
3397173138Srwatson	.mpo_vnode_setlabel_extattr = mls_vnode_setlabel_extattr,
3398101099Srwatson};
3399101099Srwatson
3400172955SrwatsonMAC_POLICY_SET(&mls_ops, mac_mls, "TrustedBSD MAC/MLS",
3401187016Srwatson    MPC_LOADTIME_FLAG_NOTLATE, &mls_slot);
3402