ugidfw_system.c revision 145412
1101099Srwatson/*-
2145412Strhodes * Copyright (c) 2005 Tom Rhodes
3126097Srwatson * Copyright (c) 1999-2002 Robert N. M. Watson
4145412Strhodes * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
5101099Srwatson * All rights reserved.
6101099Srwatson *
7101099Srwatson * This software was developed by Robert Watson for the TrustedBSD Project.
8145412Strhodes * It was later enhanced by Tom Rhodes for the TrustedBSD Project.
9101099Srwatson *
10106393Srwatson * This software was developed for the FreeBSD Project in part by Network
11106393Srwatson * Associates Laboratories, the Security Research Division of Network
12106393Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13106393Srwatson * as part of the DARPA CHATS research program.
14101099Srwatson *
15101099Srwatson * Redistribution and use in source and binary forms, with or without
16101099Srwatson * modification, are permitted provided that the following conditions
17101099Srwatson * are met:
18101099Srwatson * 1. Redistributions of source code must retain the above copyright
19101099Srwatson *    notice, this list of conditions and the following disclaimer.
20101099Srwatson * 2. Redistributions in binary form must reproduce the above copyright
21101099Srwatson *    notice, this list of conditions and the following disclaimer in the
22101099Srwatson *    documentation and/or other materials provided with the distribution.
23101099Srwatson *
24101099Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25101099Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26101099Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27101099Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28101099Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29101099Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30101099Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31101099Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32101099Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33101099Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34101099Srwatson * SUCH DAMAGE.
35101099Srwatson *
36101099Srwatson * $FreeBSD: head/sys/security/mac_bsdextended/mac_bsdextended.c 145412 2005-04-22 18:49:30Z trhodes $
37101099Srwatson */
38136774Srwatson
39101099Srwatson/*
40101099Srwatson * Developed by the TrustedBSD Project.
41101099Srwatson * "BSD Extended" MAC policy, allowing the administrator to impose
42101099Srwatson * mandatory rules regarding users and some system objects.
43101099Srwatson */
44101099Srwatson
45101099Srwatson#include <sys/types.h>
46101099Srwatson#include <sys/param.h>
47101099Srwatson#include <sys/acl.h>
48101099Srwatson#include <sys/conf.h>
49101099Srwatson#include <sys/kernel.h>
50145412Strhodes#include <sys/lock.h>
51101099Srwatson#include <sys/mac.h>
52101099Srwatson#include <sys/malloc.h>
53101099Srwatson#include <sys/mount.h>
54145412Strhodes#include <sys/mutex.h>
55101099Srwatson#include <sys/proc.h>
56101099Srwatson#include <sys/systm.h>
57101099Srwatson#include <sys/sysproto.h>
58101099Srwatson#include <sys/sysent.h>
59101099Srwatson#include <sys/vnode.h>
60101099Srwatson#include <sys/file.h>
61101099Srwatson#include <sys/socket.h>
62101099Srwatson#include <sys/socketvar.h>
63101099Srwatson#include <sys/sysctl.h>
64134132Strhodes#include <sys/syslog.h>
65101099Srwatson
66101099Srwatson#include <net/bpfdesc.h>
67101099Srwatson#include <net/if.h>
68101099Srwatson#include <net/if_types.h>
69101099Srwatson#include <net/if_var.h>
70101099Srwatson
71101099Srwatson#include <vm/vm.h>
72101099Srwatson
73101099Srwatson#include <sys/mac_policy.h>
74101099Srwatson
75101099Srwatson#include <security/mac_bsdextended/mac_bsdextended.h>
76101099Srwatson
77145412Strhodesstatic struct mtx mac_bsdextended_mtx;
78145412Strhodes
79101099SrwatsonSYSCTL_DECL(_security_mac);
80101099Srwatson
81101099SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0,
82101099Srwatson    "TrustedBSD extended BSD MAC policy controls");
83101099Srwatson
84101099Srwatsonstatic int	mac_bsdextended_enabled = 1;
85101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW,
86101099Srwatson    &mac_bsdextended_enabled, 0, "Enforce extended BSD policy");
87101099SrwatsonTUNABLE_INT("security.mac.bsdextended.enabled", &mac_bsdextended_enabled);
88101099Srwatson
89101099SrwatsonMALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule");
90101099Srwatson
91101099Srwatson#define	MAC_BSDEXTENDED_MAXRULES	250
92101099Srwatsonstatic struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES];
93101099Srwatsonstatic int rule_count = 0;
94101099Srwatsonstatic int rule_slots = 0;
95101099Srwatson
96101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD,
97101099Srwatson    &rule_count, 0, "Number of defined rules\n");
98101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD,
99101099Srwatson    &rule_slots, 0, "Number of used rule slots\n");
100101099Srwatson
101134132Strhodes/*
102145412Strhodes * This is just used for logging purposes, eventually we would like
103134132Strhodes * to log much more then failed requests.
104134132Strhodes */
105134132Strhodesstatic int mac_bsdextended_logging;
106134132StrhodesSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW,
107134132Strhodes    &mac_bsdextended_logging, 0, "Log failed authorization requests");
108134132Strhodes
109134132Strhodes/*
110134131Strhodes * This tunable is here for compatibility.  It will allow the user
111134131Strhodes * to switch between the new mode (first rule matches) and the old
112134131Strhodes * functionality (all rules match).
113134131Strhodes */
114101099Srwatsonstatic int
115134131Strhodesmac_bsdextended_firstmatch_enabled;
116134131StrhodesSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled,
117135039Strhodes	CTLFLAG_RW, &mac_bsdextended_firstmatch_enabled, 1,
118134131Strhodes	"Disable/enable match first rule functionality");
119134131Strhodes
120134131Strhodesstatic int
121101099Srwatsonmac_bsdextended_rule_valid(struct mac_bsdextended_rule *rule)
122101099Srwatson{
123101099Srwatson
124101099Srwatson	if ((rule->mbr_subject.mbi_flags | MBI_BITS) != MBI_BITS)
125101099Srwatson		return (EINVAL);
126101099Srwatson
127101099Srwatson	if ((rule->mbr_object.mbi_flags | MBI_BITS) != MBI_BITS)
128101099Srwatson		return (EINVAL);
129101099Srwatson
130136739Srwatson	if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM)
131101099Srwatson		return (EINVAL);
132101099Srwatson
133101099Srwatson	return (0);
134101099Srwatson}
135101099Srwatson
136101099Srwatsonstatic int
137101099Srwatsonsysctl_rule(SYSCTL_HANDLER_ARGS)
138101099Srwatson{
139101099Srwatson	struct mac_bsdextended_rule temprule, *ruleptr;
140101099Srwatson	u_int namelen;
141101099Srwatson	int error, index, *name;
142101099Srwatson
143145412Strhodes	error = 0;
144101099Srwatson	name = (int *)arg1;
145101099Srwatson	namelen = arg2;
146101099Srwatson
147101099Srwatson	/* printf("bsdextended sysctl handler (namelen %d)\n", namelen); */
148101099Srwatson
149101099Srwatson	if (namelen != 1)
150101099Srwatson		return (EINVAL);
151101099Srwatson
152101099Srwatson	index = name[0];
153145412Strhodes        if (index > MAC_BSDEXTENDED_MAXRULES)
154101099Srwatson		return (ENOENT);
155101099Srwatson
156145412Strhodes	ruleptr = NULL;
157145412Strhodes	if (req->newptr && req->newlen != 0) {
158145412Strhodes		error = SYSCTL_IN(req, &temprule, sizeof(temprule));
159101099Srwatson		if (error)
160101099Srwatson			return (error);
161145412Strhodes		MALLOC(ruleptr, struct mac_bsdextended_rule *,
162145412Strhodes		    sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK | M_ZERO);
163101099Srwatson	}
164101099Srwatson
165145412Strhodes	mtx_lock(&mac_bsdextended_mtx);
166145412Strhodes
167145412Strhodes	if (req->oldptr) {
168145412Strhodes		if (index < 0 || index > rule_slots + 1) {
169145412Strhodes			error = ENOENT;
170145412Strhodes			goto out;
171101099Srwatson		}
172145412Strhodes		if (rules[index] == NULL) {
173145412Strhodes			error = ENOENT;
174145412Strhodes			goto out;
175145412Strhodes		}
176145412Strhodes		temprule = *rules[index];
177145412Strhodes	}
178101099Srwatson
179145412Strhodes	if (req->newptr && req->newlen == 0) {
180145412Strhodes		/* printf("deletion\n"); */
181145412Strhodes		KASSERT(ruleptr == NULL, ("sysctl_rule: ruleptr != NULL"));
182145412Strhodes		ruleptr = rules[index];
183145412Strhodes		if (ruleptr == NULL) {
184145412Strhodes			error = ENOENT;
185145412Strhodes			goto out;
186145412Strhodes		}
187145412Strhodes		rule_count--;
188145412Strhodes		rules[index] = NULL;
189145412Strhodes	} else if (req->newptr) {
190101099Srwatson		error = mac_bsdextended_rule_valid(&temprule);
191101099Srwatson		if (error)
192145412Strhodes			goto out;
193101099Srwatson
194101099Srwatson		if (rules[index] == NULL) {
195101099Srwatson			/* printf("addition\n"); */
196101099Srwatson			*ruleptr = temprule;
197101099Srwatson			rules[index] = ruleptr;
198145412Strhodes			ruleptr = NULL;
199145412Strhodes			if (index + 1 > rule_slots)
200145412Strhodes				rule_slots = index + 1;
201101099Srwatson			rule_count++;
202101099Srwatson		} else {
203101099Srwatson			/* printf("replacement\n"); */
204101099Srwatson			*rules[index] = temprule;
205101099Srwatson		}
206101099Srwatson	}
207101099Srwatson
208145412Strhodesout:
209145412Strhodes	mtx_unlock(&mac_bsdextended_mtx);
210145412Strhodes	if (ruleptr != NULL)
211145412Strhodes		FREE(ruleptr, M_MACBSDEXTENDED);
212145412Strhodes	if (req->oldptr && error == 0) {
213145412Strhodes		error = SYSCTL_OUT(req, &temprule, sizeof(temprule));
214145412Strhodes		if (error)
215145412Strhodes			return (error);
216145412Strhodes	}
217145412Strhodes
218101099Srwatson	return (0);
219101099Srwatson}
220101099Srwatson
221101099SrwatsonSYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules,
222101099Srwatson    CTLFLAG_RW, sysctl_rule, "BSD extended MAC rules");
223101099Srwatson
224101099Srwatsonstatic void
225101099Srwatsonmac_bsdextended_init(struct mac_policy_conf *mpc)
226101099Srwatson{
227101099Srwatson
228101099Srwatson	/* Initialize ruleset lock. */
229145412Strhodes	mtx_init(&mac_bsdextended_mtx, "mac_bsdextended lock", NULL, MTX_DEF);
230145412Strhodes
231101099Srwatson	/* Register dynamic sysctl's for rules. */
232101099Srwatson}
233101099Srwatson
234101099Srwatsonstatic void
235101099Srwatsonmac_bsdextended_destroy(struct mac_policy_conf *mpc)
236101099Srwatson{
237101099Srwatson
238145412Strhodes	/* Destroy ruleset lock. */
239145412Strhodes	mtx_destroy(&mac_bsdextended_mtx);
240145412Strhodes
241101099Srwatson	/* Tear down sysctls. */
242101099Srwatson}
243101099Srwatson
244101099Srwatsonstatic int
245101099Srwatsonmac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
246106212Srwatson    struct ucred *cred, uid_t object_uid, gid_t object_gid, int acc_mode)
247101099Srwatson{
248101099Srwatson	int match;
249101099Srwatson
250101099Srwatson	/*
251101099Srwatson	 * Is there a subject match?
252101099Srwatson	 */
253145412Strhodes	mtx_assert(&mac_bsdextended_mtx, MA_OWNED);
254101099Srwatson	if (rule->mbr_subject.mbi_flags & MBI_UID_DEFINED) {
255101099Srwatson		match =  (rule->mbr_subject.mbi_uid == cred->cr_uid ||
256101099Srwatson		    rule->mbr_subject.mbi_uid == cred->cr_ruid ||
257101099Srwatson		    rule->mbr_subject.mbi_uid == cred->cr_svuid);
258101099Srwatson
259101099Srwatson		if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
260101099Srwatson			match = !match;
261101099Srwatson
262101099Srwatson		if (!match)
263101099Srwatson			return (0);
264101099Srwatson	}
265101099Srwatson
266101099Srwatson	if (rule->mbr_subject.mbi_flags & MBI_GID_DEFINED) {
267101099Srwatson		match = (groupmember(rule->mbr_subject.mbi_gid, cred) ||
268101099Srwatson		    rule->mbr_subject.mbi_gid == cred->cr_rgid ||
269101099Srwatson		    rule->mbr_subject.mbi_gid == cred->cr_svgid);
270101099Srwatson
271101099Srwatson		if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
272101099Srwatson			match = !match;
273101099Srwatson
274101099Srwatson		if (!match)
275101099Srwatson			return (0);
276101099Srwatson	}
277101099Srwatson
278101099Srwatson	/*
279101099Srwatson	 * Is there an object match?
280101099Srwatson	 */
281101099Srwatson	if (rule->mbr_object.mbi_flags & MBI_UID_DEFINED) {
282101099Srwatson		match = (rule->mbr_object.mbi_uid == object_uid);
283101099Srwatson
284101099Srwatson		if (rule->mbr_object.mbi_flags & MBI_NEGATED)
285101099Srwatson			match = !match;
286101099Srwatson
287101099Srwatson		if (!match)
288101099Srwatson			return (0);
289101099Srwatson	}
290101099Srwatson
291101099Srwatson	if (rule->mbr_object.mbi_flags & MBI_GID_DEFINED) {
292101099Srwatson		match = (rule->mbr_object.mbi_gid == object_gid);
293101099Srwatson
294101099Srwatson		if (rule->mbr_object.mbi_flags & MBI_NEGATED)
295101099Srwatson			match = !match;
296101099Srwatson
297101099Srwatson		if (!match)
298101099Srwatson			return (0);
299101099Srwatson	}
300101099Srwatson
301101099Srwatson	/*
302101099Srwatson	 * Is the access permitted?
303101099Srwatson	 */
304101099Srwatson	if ((rule->mbr_mode & acc_mode) != acc_mode) {
305134132Strhodes		if (mac_bsdextended_logging)
306134132Strhodes			log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d"
307134132Strhodes			    " on %d:%d failed. \n", cred->cr_ruid,
308134132Strhodes			    cred->cr_rgid, acc_mode, object_uid, object_gid);
309134132Strhodes		return (EACCES); /* Matching rule denies access */
310101099Srwatson	}
311145412Strhodes
312134131Strhodes	/*
313145412Strhodes	 * If the rule matched, permits access, and first match is enabled,
314145412Strhodes	 * return success.
315134131Strhodes	 */
316134131Strhodes	if (mac_bsdextended_firstmatch_enabled)
317134131Strhodes		return (EJUSTRETURN);
318134131Strhodes	else
319134131Strhodes		return(0);
320101099Srwatson}
321101099Srwatson
322101099Srwatsonstatic int
323101099Srwatsonmac_bsdextended_check(struct ucred *cred, uid_t object_uid, gid_t object_gid,
324106212Srwatson    int acc_mode)
325101099Srwatson{
326101099Srwatson	int error, i;
327101099Srwatson
328132563Srwatson	if (suser_cred(cred, 0) == 0)
329132563Srwatson		return (0);
330132563Srwatson
331145412Strhodes	mtx_lock(&mac_bsdextended_mtx);
332101099Srwatson	for (i = 0; i < rule_slots; i++) {
333101099Srwatson		if (rules[i] == NULL)
334101099Srwatson			continue;
335101099Srwatson
336108376Srwatson		/*
337145412Strhodes		 * Since we do not separately handle append, map append to
338108376Srwatson		 * write.
339108376Srwatson		 */
340136739Srwatson		if (acc_mode & MBI_APPEND) {
341136739Srwatson			acc_mode &= ~MBI_APPEND;
342136739Srwatson			acc_mode |= MBI_WRITE;
343108376Srwatson		}
344108376Srwatson
345101099Srwatson		error = mac_bsdextended_rulecheck(rules[i], cred, object_uid,
346101099Srwatson		    object_gid, acc_mode);
347134131Strhodes		if (error == EJUSTRETURN)
348134131Strhodes			break;
349145412Strhodes		if (error) {
350145412Strhodes			mtx_unlock(&mac_bsdextended_mtx);
351101099Srwatson			return (error);
352145412Strhodes		}
353101099Srwatson	}
354145412Strhodes	mtx_unlock(&mac_bsdextended_mtx);
355101099Srwatson	return (0);
356101099Srwatson}
357101099Srwatson
358101099Srwatsonstatic int
359112575Srwatsonmac_bsdextended_check_system_swapon(struct ucred *cred, struct vnode *vp,
360112575Srwatson    struct label *label)
361112575Srwatson{
362112575Srwatson	struct vattr vap;
363112575Srwatson	int error;
364112575Srwatson
365112575Srwatson	if (!mac_bsdextended_enabled)
366112575Srwatson		return (0);
367112575Srwatson
368112575Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
369112575Srwatson	if (error)
370112575Srwatson		return (error);
371136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
372136739Srwatson	    MBI_WRITE));
373112575Srwatson}
374112575Srwatson
375112575Srwatsonstatic int
376101099Srwatsonmac_bsdextended_check_vnode_access(struct ucred *cred, struct vnode *vp,
377106212Srwatson    struct label *label, int acc_mode)
378101099Srwatson{
379101099Srwatson	struct vattr vap;
380101099Srwatson	int error;
381101099Srwatson
382101099Srwatson	if (!mac_bsdextended_enabled)
383101099Srwatson		return (0);
384101099Srwatson
385101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
386101099Srwatson	if (error)
387101099Srwatson		return (error);
388106212Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
389101099Srwatson}
390101099Srwatson
391101099Srwatsonstatic int
392101099Srwatsonmac_bsdextended_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
393101099Srwatson    struct label *dlabel)
394101099Srwatson{
395101099Srwatson	struct vattr vap;
396101099Srwatson	int error;
397101099Srwatson
398101099Srwatson	if (!mac_bsdextended_enabled)
399101099Srwatson		return (0);
400101099Srwatson
401101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
402101099Srwatson	if (error)
403101099Srwatson		return (error);
404136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
405136739Srwatson	    MBI_EXEC));
406101099Srwatson}
407101099Srwatson
408101099Srwatsonstatic int
409101099Srwatsonmac_bsdextended_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
410101099Srwatson    struct label *dlabel)
411101099Srwatson{
412101099Srwatson	struct vattr vap;
413101099Srwatson	int error;
414101099Srwatson
415101099Srwatson	if (!mac_bsdextended_enabled)
416101099Srwatson		return (0);
417101099Srwatson
418101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
419101099Srwatson	if (error)
420101099Srwatson		return (error);
421136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
422136739Srwatson	    MBI_EXEC));
423101099Srwatson}
424101099Srwatson
425101099Srwatsonstatic int
426101099Srwatsonmac_bsdextended_check_create_vnode(struct ucred *cred, struct vnode *dvp,
427101099Srwatson    struct label *dlabel, struct componentname *cnp, struct vattr *vap)
428101099Srwatson{
429101099Srwatson	struct vattr dvap;
430101099Srwatson	int error;
431101099Srwatson
432101099Srwatson	if (!mac_bsdextended_enabled)
433101099Srwatson		return (0);
434101099Srwatson
435101099Srwatson	error = VOP_GETATTR(dvp, &dvap, cred, curthread);
436101099Srwatson	if (error)
437101099Srwatson		return (error);
438136739Srwatson	return (mac_bsdextended_check(cred, dvap.va_uid, dvap.va_gid,
439136739Srwatson	    MBI_WRITE));
440101099Srwatson}
441101099Srwatson
442101099Srwatsonstatic int
443101099Srwatsonmac_bsdextended_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
444101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
445101099Srwatson    struct componentname *cnp)
446101099Srwatson{
447101099Srwatson	struct vattr vap;
448101099Srwatson	int error;
449101099Srwatson
450101099Srwatson	if (!mac_bsdextended_enabled)
451101099Srwatson		return (0);
452101099Srwatson
453101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
454101099Srwatson	if (error)
455101099Srwatson		return (error);
456136739Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
457136739Srwatson	    MBI_WRITE);
458101099Srwatson	if (error)
459101099Srwatson		return (error);
460101099Srwatson
461101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
462101099Srwatson	if (error)
463101099Srwatson		return (error);
464136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
465136739Srwatson	    MBI_WRITE));
466101099Srwatson}
467101099Srwatson
468101099Srwatsonstatic int
469101099Srwatsonmac_bsdextended_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
470101099Srwatson    struct label *label, acl_type_t type)
471101099Srwatson{
472101099Srwatson	struct vattr vap;
473101099Srwatson	int error;
474101099Srwatson
475101099Srwatson	if (!mac_bsdextended_enabled)
476101099Srwatson		return (0);
477101099Srwatson
478101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
479117247Srwatson	if (error)
480101099Srwatson		return (error);
481136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
482136739Srwatson	    MBI_ADMIN));
483101099Srwatson}
484101099Srwatson
485101099Srwatsonstatic int
486119202Srwatsonmac_bsdextended_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
487119202Srwatson    struct label *label, int attrnamespace, const char *name)
488119202Srwatson{
489119202Srwatson	struct vattr vap;
490119202Srwatson	int error;
491119202Srwatson
492119202Srwatson	if (!mac_bsdextended_enabled)
493119202Srwatson		return (0);
494119202Srwatson
495119202Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
496119202Srwatson	if (error)
497119202Srwatson		return (error);
498136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
499136739Srwatson	    MBI_WRITE));
500119202Srwatson}
501119202Srwatson
502119202Srwatsonstatic int
503101099Srwatsonmac_bsdextended_check_vnode_exec(struct ucred *cred, struct vnode *vp,
504106648Srwatson    struct label *label, struct image_params *imgp,
505106648Srwatson    struct label *execlabel)
506101099Srwatson{
507101099Srwatson	struct vattr vap;
508101099Srwatson	int error;
509101099Srwatson
510101099Srwatson	if (!mac_bsdextended_enabled)
511101099Srwatson		return (0);
512101099Srwatson
513101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
514101099Srwatson	if (error)
515101099Srwatson		return (error);
516101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
517136739Srwatson	    MBI_READ|MBI_EXEC));
518101099Srwatson}
519101099Srwatson
520101099Srwatsonstatic int
521101099Srwatsonmac_bsdextended_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
522101099Srwatson    struct label *label, acl_type_t type)
523101099Srwatson{
524101099Srwatson	struct vattr vap;
525101099Srwatson	int error;
526101099Srwatson
527101099Srwatson	if (!mac_bsdextended_enabled)
528101099Srwatson		return (0);
529101099Srwatson
530101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
531101099Srwatson	if (error)
532101099Srwatson		return (error);
533136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
534136739Srwatson	    MBI_STAT));
535101099Srwatson}
536101099Srwatson
537101099Srwatsonstatic int
538101099Srwatsonmac_bsdextended_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
539101099Srwatson    struct label *label, int attrnamespace, const char *name, struct uio *uio)
540101099Srwatson{
541101099Srwatson	struct vattr vap;
542101099Srwatson	int error;
543101099Srwatson
544101099Srwatson	if (!mac_bsdextended_enabled)
545101099Srwatson		return (0);
546101099Srwatson
547101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
548101099Srwatson	if (error)
549101099Srwatson		return (error);
550136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
551136739Srwatson	    MBI_READ));
552101099Srwatson}
553101099Srwatson
554101099Srwatsonstatic int
555104530Srwatsonmac_bsdextended_check_vnode_link(struct ucred *cred, struct vnode *dvp,
556104530Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
557104530Srwatson    struct componentname *cnp)
558104530Srwatson{
559104530Srwatson	struct vattr vap;
560104530Srwatson	int error;
561104530Srwatson
562104530Srwatson	if (!mac_bsdextended_enabled)
563104530Srwatson		return (0);
564104530Srwatson
565104530Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
566104530Srwatson	if (error)
567104530Srwatson		return (error);
568136739Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
569136739Srwatson	    MBI_WRITE);
570106214Srwatson	if (error)
571106214Srwatson		return (error);
572104530Srwatson
573104530Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
574104530Srwatson	if (error)
575104530Srwatson		return (error);
576136739Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
577136739Srwatson	    MBI_WRITE);
578104530Srwatson	if (error)
579104530Srwatson		return (error);
580104530Srwatson	return (0);
581104530Srwatson}
582104530Srwatson
583104530Srwatsonstatic int
584119202Srwatsonmac_bsdextended_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
585119202Srwatson    struct label *label, int attrnamespace)
586119202Srwatson{
587119202Srwatson	struct vattr vap;
588119202Srwatson	int error;
589119202Srwatson
590119202Srwatson	if (!mac_bsdextended_enabled)
591119202Srwatson		return (0);
592119202Srwatson
593119202Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
594119202Srwatson	if (error)
595119202Srwatson		return (error);
596136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
597136739Srwatson	    MBI_READ));
598119202Srwatson}
599119202Srwatson
600119202Srwatsonstatic int
601101099Srwatsonmac_bsdextended_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
602101099Srwatson    struct label *dlabel, struct componentname *cnp)
603101099Srwatson{
604101099Srwatson	struct vattr vap;
605101099Srwatson	int error;
606117247Srwatson
607101099Srwatson	if (!mac_bsdextended_enabled)
608101099Srwatson		return (0);
609117247Srwatson
610101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
611101099Srwatson	if (error)
612101099Srwatson		return (error);
613136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
614136739Srwatson	    MBI_EXEC));
615101099Srwatson}
616101099Srwatson
617101099Srwatsonstatic int
618101099Srwatsonmac_bsdextended_check_vnode_open(struct ucred *cred, struct vnode *vp,
619106212Srwatson    struct label *filelabel, int acc_mode)
620101099Srwatson{
621101099Srwatson	struct vattr vap;
622101099Srwatson	int error;
623101099Srwatson
624101099Srwatson	if (!mac_bsdextended_enabled)
625101099Srwatson		return (0);
626101099Srwatson
627101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
628101099Srwatson	if (error)
629101099Srwatson		return (error);
630101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
631101099Srwatson}
632101099Srwatson
633101099Srwatsonstatic int
634101099Srwatsonmac_bsdextended_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
635101099Srwatson    struct label *dlabel)
636101099Srwatson{
637101099Srwatson	struct vattr vap;
638101099Srwatson	int error;
639101099Srwatson
640101099Srwatson	if (!mac_bsdextended_enabled)
641101099Srwatson		return (0);
642101099Srwatson
643101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
644101099Srwatson	if (error)
645101099Srwatson		return (error);
646136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
647136739Srwatson	    MBI_READ));
648101099Srwatson}
649101099Srwatson
650101099Srwatsonstatic int
651101099Srwatsonmac_bsdextended_check_vnode_readdlink(struct ucred *cred, struct vnode *vp,
652101099Srwatson    struct label *label)
653101099Srwatson{
654101099Srwatson	struct vattr vap;
655101099Srwatson	int error;
656101099Srwatson
657101099Srwatson	if (!mac_bsdextended_enabled)
658101099Srwatson		return (0);
659101099Srwatson
660101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
661101099Srwatson	if (error)
662101099Srwatson		return (error);
663136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
664136739Srwatson	    MBI_READ));
665101099Srwatson}
666101099Srwatson
667101099Srwatsonstatic int
668101099Srwatsonmac_bsdextended_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
669101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
670101099Srwatson    struct componentname *cnp)
671101099Srwatson{
672101099Srwatson	struct vattr vap;
673101099Srwatson	int error;
674101099Srwatson
675101099Srwatson	if (!mac_bsdextended_enabled)
676101099Srwatson		return (0);
677101099Srwatson
678101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
679101099Srwatson	if (error)
680101099Srwatson		return (error);
681136739Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
682136739Srwatson	    MBI_WRITE);
683101099Srwatson	if (error)
684101099Srwatson		return (error);
685101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
686101099Srwatson	if (error)
687101099Srwatson		return (error);
688136739Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
689136739Srwatson	    MBI_WRITE);
690101099Srwatson
691101099Srwatson	return (error);
692101099Srwatson}
693101099Srwatson
694101099Srwatsonstatic int
695101099Srwatsonmac_bsdextended_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
696101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
697101099Srwatson    struct componentname *cnp)
698101099Srwatson{
699101099Srwatson	struct vattr vap;
700101099Srwatson	int error;
701101099Srwatson
702101099Srwatson	if (!mac_bsdextended_enabled)
703101099Srwatson		return (0);
704101099Srwatson
705101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
706101099Srwatson	if (error)
707101099Srwatson		return (error);
708136739Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
709136739Srwatson	    MBI_WRITE);
710101099Srwatson	if (error)
711101099Srwatson		return (error);
712101099Srwatson
713101099Srwatson	if (vp != NULL) {
714101099Srwatson		error = VOP_GETATTR(vp, &vap, cred, curthread);
715101099Srwatson		if (error)
716101099Srwatson			return (error);
717101099Srwatson		error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
718136739Srwatson		    MBI_WRITE);
719101099Srwatson	}
720101099Srwatson
721101099Srwatson	return (error);
722101099Srwatson}
723101099Srwatson
724101099Srwatsonstatic int
725101099Srwatsonmac_bsdextended_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
726101099Srwatson    struct label *label)
727101099Srwatson{
728101099Srwatson	struct vattr vap;
729101099Srwatson	int error;
730101099Srwatson
731101099Srwatson	if (!mac_bsdextended_enabled)
732101099Srwatson		return (0);
733101099Srwatson
734101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
735101099Srwatson	if (error)
736101099Srwatson		return (error);
737136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
738136739Srwatson	    MBI_ADMIN));
739101099Srwatson}
740101099Srwatson
741101099Srwatsonstatic int
742101099Srwatsonmac_bsdextended_check_setacl_vnode(struct ucred *cred, struct vnode *vp,
743101099Srwatson    struct label *label, acl_type_t type, struct acl *acl)
744101099Srwatson{
745101099Srwatson	struct vattr vap;
746101099Srwatson	int error;
747101099Srwatson
748101099Srwatson	if (!mac_bsdextended_enabled)
749101099Srwatson		return (0);
750101099Srwatson
751101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
752101099Srwatson	if (error)
753101099Srwatson		return (error);
754136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
755136739Srwatson	    MBI_ADMIN));
756101099Srwatson}
757101099Srwatson
758101099Srwatsonstatic int
759101099Srwatsonmac_bsdextended_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
760101099Srwatson    struct label *label, int attrnamespace, const char *name, struct uio *uio)
761101099Srwatson{
762101099Srwatson	struct vattr vap;
763101099Srwatson	int error;
764101099Srwatson
765101099Srwatson	if (!mac_bsdextended_enabled)
766101099Srwatson		return (0);
767101099Srwatson
768101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
769101099Srwatson	if (error)
770101099Srwatson		return (error);
771136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
772136739Srwatson	    MBI_WRITE));
773101099Srwatson}
774101099Srwatson
775101099Srwatsonstatic int
776101099Srwatsonmac_bsdextended_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
777101099Srwatson    struct label *label, u_long flags)
778101099Srwatson{
779101099Srwatson	struct vattr vap;
780101099Srwatson	int error;
781101099Srwatson
782101099Srwatson	if (!mac_bsdextended_enabled)
783101099Srwatson		return (0);
784101099Srwatson
785101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
786101099Srwatson	if (error)
787101099Srwatson		return (error);
788136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
789136739Srwatson	    MBI_ADMIN));
790101099Srwatson}
791101099Srwatson
792101099Srwatsonstatic int
793101099Srwatsonmac_bsdextended_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
794101099Srwatson    struct label *label, mode_t mode)
795101099Srwatson{
796101099Srwatson	struct vattr vap;
797101099Srwatson	int error;
798101099Srwatson
799101099Srwatson	if (!mac_bsdextended_enabled)
800101099Srwatson		return (0);
801101099Srwatson
802101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
803101099Srwatson	if (error)
804101099Srwatson		return (error);
805136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
806136739Srwatson	    MBI_ADMIN));
807101099Srwatson}
808101099Srwatson
809101099Srwatsonstatic int
810101099Srwatsonmac_bsdextended_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
811101099Srwatson    struct label *label, uid_t uid, gid_t gid)
812101099Srwatson{
813101099Srwatson	struct vattr vap;
814101099Srwatson	int error;
815101099Srwatson
816101099Srwatson	if (!mac_bsdextended_enabled)
817101099Srwatson		return (0);
818101099Srwatson
819101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
820101099Srwatson	if (error)
821101099Srwatson		return (error);
822136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
823136739Srwatson	   MBI_ADMIN));
824101099Srwatson}
825101099Srwatson
826101099Srwatsonstatic int
827101099Srwatsonmac_bsdextended_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
828101099Srwatson    struct label *label, struct timespec atime, struct timespec utime)
829101099Srwatson{
830101099Srwatson	struct vattr vap;
831101099Srwatson	int error;
832101099Srwatson
833101099Srwatson	if (!mac_bsdextended_enabled)
834101099Srwatson		return (0);
835101099Srwatson
836101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
837101099Srwatson	if (error)
838101099Srwatson		return (error);
839136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
840136739Srwatson	    MBI_ADMIN));
841101099Srwatson}
842101099Srwatson
843101099Srwatsonstatic int
844102129Srwatsonmac_bsdextended_check_vnode_stat(struct ucred *active_cred,
845102129Srwatson    struct ucred *file_cred, struct vnode *vp, struct label *label)
846101099Srwatson{
847101099Srwatson	struct vattr vap;
848101099Srwatson	int error;
849101099Srwatson
850101099Srwatson	if (!mac_bsdextended_enabled)
851101099Srwatson		return (0);
852101099Srwatson
853102129Srwatson	error = VOP_GETATTR(vp, &vap, active_cred, curthread);
854101099Srwatson	if (error)
855101099Srwatson		return (error);
856102129Srwatson	return (mac_bsdextended_check(active_cred, vap.va_uid, vap.va_gid,
857136739Srwatson	    MBI_STAT));
858101099Srwatson}
859101099Srwatson
860106217Srwatsonstatic struct mac_policy_ops mac_bsdextended_ops =
861101099Srwatson{
862106217Srwatson	.mpo_destroy = mac_bsdextended_destroy,
863106217Srwatson	.mpo_init = mac_bsdextended_init,
864112575Srwatson	.mpo_check_system_swapon = mac_bsdextended_check_system_swapon,
865106217Srwatson	.mpo_check_vnode_access = mac_bsdextended_check_vnode_access,
866106217Srwatson	.mpo_check_vnode_chdir = mac_bsdextended_check_vnode_chdir,
867106217Srwatson	.mpo_check_vnode_chroot = mac_bsdextended_check_vnode_chroot,
868106217Srwatson	.mpo_check_vnode_create = mac_bsdextended_check_create_vnode,
869106217Srwatson	.mpo_check_vnode_delete = mac_bsdextended_check_vnode_delete,
870106217Srwatson	.mpo_check_vnode_deleteacl = mac_bsdextended_check_vnode_deleteacl,
871119202Srwatson	.mpo_check_vnode_deleteextattr = mac_bsdextended_check_vnode_deleteextattr,
872106217Srwatson	.mpo_check_vnode_exec = mac_bsdextended_check_vnode_exec,
873106217Srwatson	.mpo_check_vnode_getacl = mac_bsdextended_check_vnode_getacl,
874106217Srwatson	.mpo_check_vnode_getextattr = mac_bsdextended_check_vnode_getextattr,
875106217Srwatson	.mpo_check_vnode_link = mac_bsdextended_check_vnode_link,
876119202Srwatson	.mpo_check_vnode_listextattr = mac_bsdextended_check_vnode_listextattr,
877106217Srwatson	.mpo_check_vnode_lookup = mac_bsdextended_check_vnode_lookup,
878106217Srwatson	.mpo_check_vnode_open = mac_bsdextended_check_vnode_open,
879106217Srwatson	.mpo_check_vnode_readdir = mac_bsdextended_check_vnode_readdir,
880106217Srwatson	.mpo_check_vnode_readlink = mac_bsdextended_check_vnode_readdlink,
881106217Srwatson	.mpo_check_vnode_rename_from = mac_bsdextended_check_vnode_rename_from,
882106217Srwatson	.mpo_check_vnode_rename_to = mac_bsdextended_check_vnode_rename_to,
883106217Srwatson	.mpo_check_vnode_revoke = mac_bsdextended_check_vnode_revoke,
884106217Srwatson	.mpo_check_vnode_setacl = mac_bsdextended_check_setacl_vnode,
885106217Srwatson	.mpo_check_vnode_setextattr = mac_bsdextended_check_vnode_setextattr,
886106217Srwatson	.mpo_check_vnode_setflags = mac_bsdextended_check_vnode_setflags,
887106217Srwatson	.mpo_check_vnode_setmode = mac_bsdextended_check_vnode_setmode,
888106217Srwatson	.mpo_check_vnode_setowner = mac_bsdextended_check_vnode_setowner,
889106217Srwatson	.mpo_check_vnode_setutimes = mac_bsdextended_check_vnode_setutimes,
890106217Srwatson	.mpo_check_vnode_stat = mac_bsdextended_check_vnode_stat,
891101099Srwatson};
892101099Srwatson
893112717SrwatsonMAC_POLICY_SET(&mac_bsdextended_ops, mac_bsdextended,
894101099Srwatson    "TrustedBSD MAC/BSD Extended", MPC_LOADTIME_FLAG_UNLOADOK, NULL);
895