ugidfw_system.c revision 135039
1101099Srwatson/*-
2126097Srwatson * Copyright (c) 1999-2002 Robert N. M. Watson
3126097Srwatson * Copyright (c) 2001-2003 Networks Associates Technology, Inc.
4101099Srwatson * All rights reserved.
5101099Srwatson *
6101099Srwatson * This software was developed by Robert Watson for the TrustedBSD Project.
7101099Srwatson *
8106393Srwatson * This software was developed for the FreeBSD Project in part by Network
9106393Srwatson * Associates Laboratories, the Security Research Division of Network
10106393Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
11106393Srwatson * as part of the DARPA CHATS research program.
12101099Srwatson *
13101099Srwatson * Redistribution and use in source and binary forms, with or without
14101099Srwatson * modification, are permitted provided that the following conditions
15101099Srwatson * are met:
16101099Srwatson * 1. Redistributions of source code must retain the above copyright
17101099Srwatson *    notice, this list of conditions and the following disclaimer.
18101099Srwatson * 2. Redistributions in binary form must reproduce the above copyright
19101099Srwatson *    notice, this list of conditions and the following disclaimer in the
20101099Srwatson *    documentation and/or other materials provided with the distribution.
21101099Srwatson *
22101099Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23101099Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24101099Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25101099Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26101099Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27101099Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28101099Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29101099Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30101099Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31101099Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32101099Srwatson * SUCH DAMAGE.
33101099Srwatson *
34101099Srwatson * $FreeBSD: head/sys/security/mac_bsdextended/mac_bsdextended.c 135039 2004-09-10 15:14:50Z trhodes $
35101099Srwatson */
36101099Srwatson/*
37101099Srwatson * Developed by the TrustedBSD Project.
38101099Srwatson * "BSD Extended" MAC policy, allowing the administrator to impose
39101099Srwatson * mandatory rules regarding users and some system objects.
40101099Srwatson *
41101099Srwatson * XXX: Much locking support required here.
42101099Srwatson */
43101099Srwatson
44101099Srwatson#include <sys/types.h>
45101099Srwatson#include <sys/param.h>
46101099Srwatson#include <sys/acl.h>
47101099Srwatson#include <sys/conf.h>
48101099Srwatson#include <sys/kernel.h>
49101099Srwatson#include <sys/mac.h>
50101099Srwatson#include <sys/malloc.h>
51101099Srwatson#include <sys/mount.h>
52101099Srwatson#include <sys/proc.h>
53101099Srwatson#include <sys/systm.h>
54101099Srwatson#include <sys/sysproto.h>
55101099Srwatson#include <sys/sysent.h>
56101099Srwatson#include <sys/vnode.h>
57101099Srwatson#include <sys/file.h>
58101099Srwatson#include <sys/socket.h>
59101099Srwatson#include <sys/socketvar.h>
60101099Srwatson#include <sys/sysctl.h>
61134132Strhodes#include <sys/syslog.h>
62101099Srwatson
63101099Srwatson#include <net/bpfdesc.h>
64101099Srwatson#include <net/if.h>
65101099Srwatson#include <net/if_types.h>
66101099Srwatson#include <net/if_var.h>
67101099Srwatson
68101099Srwatson#include <vm/vm.h>
69101099Srwatson
70101099Srwatson#include <sys/mac_policy.h>
71101099Srwatson
72101099Srwatson#include <security/mac_bsdextended/mac_bsdextended.h>
73101099Srwatson
74101099SrwatsonSYSCTL_DECL(_security_mac);
75101099Srwatson
76101099SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0,
77101099Srwatson    "TrustedBSD extended BSD MAC policy controls");
78101099Srwatson
79101099Srwatsonstatic int	mac_bsdextended_enabled = 1;
80101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW,
81101099Srwatson    &mac_bsdextended_enabled, 0, "Enforce extended BSD policy");
82101099SrwatsonTUNABLE_INT("security.mac.bsdextended.enabled", &mac_bsdextended_enabled);
83101099Srwatson
84101099SrwatsonMALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule");
85101099Srwatson
86101099Srwatson#define	MAC_BSDEXTENDED_MAXRULES	250
87101099Srwatsonstatic struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES];
88101099Srwatsonstatic int rule_count = 0;
89101099Srwatsonstatic int rule_slots = 0;
90101099Srwatson
91101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD,
92101099Srwatson    &rule_count, 0, "Number of defined rules\n");
93101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD,
94101099Srwatson    &rule_slots, 0, "Number of used rule slots\n");
95101099Srwatson
96134132Strhodes/*
97134132Strhodes * This is just used for logging purposes as eventually we would like
98134132Strhodes * to log much more then failed requests.
99134132Strhodes */
100134132Strhodesstatic int mac_bsdextended_logging;
101134132StrhodesSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW,
102134132Strhodes    &mac_bsdextended_logging, 0, "Log failed authorization requests");
103134132Strhodes
104134132Strhodes/*
105134131Strhodes * This tunable is here for compatibility.  It will allow the user
106134131Strhodes * to switch between the new mode (first rule matches) and the old
107134131Strhodes * functionality (all rules match).
108134131Strhodes */
109101099Srwatsonstatic int
110134131Strhodesmac_bsdextended_firstmatch_enabled;
111134131StrhodesSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled,
112135039Strhodes	CTLFLAG_RW, &mac_bsdextended_firstmatch_enabled, 1,
113134131Strhodes	"Disable/enable match first rule functionality");
114134131Strhodes
115134131Strhodesstatic int
116101099Srwatsonmac_bsdextended_rule_valid(struct mac_bsdextended_rule *rule)
117101099Srwatson{
118101099Srwatson
119101099Srwatson	if ((rule->mbr_subject.mbi_flags | MBI_BITS) != MBI_BITS)
120101099Srwatson		return (EINVAL);
121101099Srwatson
122101099Srwatson	if ((rule->mbr_object.mbi_flags | MBI_BITS) != MBI_BITS)
123101099Srwatson		return (EINVAL);
124101099Srwatson
125101099Srwatson	if ((rule->mbr_mode | VALLPERM) != VALLPERM)
126101099Srwatson		return (EINVAL);
127101099Srwatson
128101099Srwatson	return (0);
129101099Srwatson}
130101099Srwatson
131101099Srwatsonstatic int
132101099Srwatsonsysctl_rule(SYSCTL_HANDLER_ARGS)
133101099Srwatson{
134101099Srwatson	struct mac_bsdextended_rule temprule, *ruleptr;
135101099Srwatson	u_int namelen;
136101099Srwatson	int error, index, *name;
137101099Srwatson
138101099Srwatson	name = (int *)arg1;
139101099Srwatson	namelen = arg2;
140101099Srwatson
141101099Srwatson	/* printf("bsdextended sysctl handler (namelen %d)\n", namelen); */
142101099Srwatson
143101099Srwatson	if (namelen != 1)
144101099Srwatson		return (EINVAL);
145101099Srwatson
146101099Srwatson	index = name[0];
147101099Srwatson	if (index < 0 || index > rule_slots + 1)
148101099Srwatson		return (ENOENT);
149101099Srwatson	if (rule_slots >= MAC_BSDEXTENDED_MAXRULES)
150101099Srwatson		return (ENOENT);
151101099Srwatson
152101099Srwatson	if (req->oldptr) {
153101099Srwatson		if (rules[index] == NULL)
154101099Srwatson			return (ENOENT);
155101099Srwatson
156101099Srwatson		error = SYSCTL_OUT(req, rules[index], sizeof(*rules[index]));
157101099Srwatson		if (error)
158101099Srwatson			return (error);
159101099Srwatson	}
160101099Srwatson
161101099Srwatson	if (req->newptr) {
162101099Srwatson		if (req->newlen == 0) {
163101099Srwatson			/* printf("deletion\n"); */
164101099Srwatson			ruleptr = rules[index];
165101099Srwatson			if (ruleptr == NULL)
166101099Srwatson				return (ENOENT);
167101099Srwatson			rule_count--;
168101099Srwatson			rules[index] = NULL;
169101099Srwatson			FREE(ruleptr, M_MACBSDEXTENDED);
170101099Srwatson			return(0);
171101099Srwatson		}
172101099Srwatson		error = SYSCTL_IN(req, &temprule, sizeof(temprule));
173101099Srwatson		if (error)
174101099Srwatson			return (error);
175101099Srwatson
176101099Srwatson		error = mac_bsdextended_rule_valid(&temprule);
177101099Srwatson		if (error)
178101099Srwatson			return (error);
179101099Srwatson
180101099Srwatson		if (rules[index] == NULL) {
181101099Srwatson			/* printf("addition\n"); */
182101099Srwatson			MALLOC(ruleptr, struct mac_bsdextended_rule *,
183111119Simp			    sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK |
184101099Srwatson			    M_ZERO);
185101099Srwatson			*ruleptr = temprule;
186101099Srwatson			rules[index] = ruleptr;
187101099Srwatson			if (index+1 > rule_slots)
188101099Srwatson				rule_slots = index+1;
189101099Srwatson			rule_count++;
190101099Srwatson		} else {
191101099Srwatson			/* printf("replacement\n"); */
192101099Srwatson			*rules[index] = temprule;
193101099Srwatson		}
194101099Srwatson	}
195101099Srwatson
196101099Srwatson	return (0);
197101099Srwatson}
198101099Srwatson
199101099SrwatsonSYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules,
200101099Srwatson    CTLFLAG_RW, sysctl_rule, "BSD extended MAC rules");
201101099Srwatson
202101099Srwatsonstatic void
203101099Srwatsonmac_bsdextended_init(struct mac_policy_conf *mpc)
204101099Srwatson{
205101099Srwatson
206101099Srwatson	/* Initialize ruleset lock. */
207101099Srwatson	/* Register dynamic sysctl's for rules. */
208101099Srwatson}
209101099Srwatson
210101099Srwatsonstatic void
211101099Srwatsonmac_bsdextended_destroy(struct mac_policy_conf *mpc)
212101099Srwatson{
213101099Srwatson
214101099Srwatson	/* Tear down sysctls. */
215101099Srwatson	/* Destroy ruleset lock. */
216101099Srwatson}
217101099Srwatson
218101099Srwatsonstatic int
219101099Srwatsonmac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
220106212Srwatson    struct ucred *cred, uid_t object_uid, gid_t object_gid, int acc_mode)
221101099Srwatson{
222101099Srwatson	int match;
223101099Srwatson
224101099Srwatson	/*
225101099Srwatson	 * Is there a subject match?
226101099Srwatson	 */
227101099Srwatson	if (rule->mbr_subject.mbi_flags & MBI_UID_DEFINED) {
228101099Srwatson		match =  (rule->mbr_subject.mbi_uid == cred->cr_uid ||
229101099Srwatson		    rule->mbr_subject.mbi_uid == cred->cr_ruid ||
230101099Srwatson		    rule->mbr_subject.mbi_uid == cred->cr_svuid);
231101099Srwatson
232101099Srwatson		if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
233101099Srwatson			match = !match;
234101099Srwatson
235101099Srwatson		if (!match)
236101099Srwatson			return (0);
237101099Srwatson	}
238101099Srwatson
239101099Srwatson	if (rule->mbr_subject.mbi_flags & MBI_GID_DEFINED) {
240101099Srwatson		match = (groupmember(rule->mbr_subject.mbi_gid, cred) ||
241101099Srwatson		    rule->mbr_subject.mbi_gid == cred->cr_rgid ||
242101099Srwatson		    rule->mbr_subject.mbi_gid == cred->cr_svgid);
243101099Srwatson
244101099Srwatson		if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
245101099Srwatson			match = !match;
246101099Srwatson
247101099Srwatson		if (!match)
248101099Srwatson			return (0);
249101099Srwatson	}
250101099Srwatson
251101099Srwatson	/*
252101099Srwatson	 * Is there an object match?
253101099Srwatson	 */
254101099Srwatson	if (rule->mbr_object.mbi_flags & MBI_UID_DEFINED) {
255101099Srwatson		match = (rule->mbr_object.mbi_uid == object_uid);
256101099Srwatson
257101099Srwatson		if (rule->mbr_object.mbi_flags & MBI_NEGATED)
258101099Srwatson			match = !match;
259101099Srwatson
260101099Srwatson		if (!match)
261101099Srwatson			return (0);
262101099Srwatson	}
263101099Srwatson
264101099Srwatson	if (rule->mbr_object.mbi_flags & MBI_GID_DEFINED) {
265101099Srwatson		match = (rule->mbr_object.mbi_gid == object_gid);
266101099Srwatson
267101099Srwatson		if (rule->mbr_object.mbi_flags & MBI_NEGATED)
268101099Srwatson			match = !match;
269101099Srwatson
270101099Srwatson		if (!match)
271101099Srwatson			return (0);
272101099Srwatson	}
273101099Srwatson
274101099Srwatson	/*
275101099Srwatson	 * Is the access permitted?
276101099Srwatson	 */
277101099Srwatson	if ((rule->mbr_mode & acc_mode) != acc_mode) {
278134132Strhodes		if (mac_bsdextended_logging)
279134132Strhodes			log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d"
280134132Strhodes			    " on %d:%d failed. \n", cred->cr_ruid,
281134132Strhodes			    cred->cr_rgid, acc_mode, object_uid, object_gid);
282134132Strhodes		return (EACCES); /* Matching rule denies access */
283101099Srwatson	}
284134131Strhodes	/*
285134131Strhodes	 * If the rule matched and allowed access and first match is
286134131Strhodes	 * enabled, then return success.
287134131Strhodes	 */
288134131Strhodes	if (mac_bsdextended_firstmatch_enabled)
289134131Strhodes		return (EJUSTRETURN);
290134131Strhodes	else
291134131Strhodes		return(0);
292101099Srwatson}
293101099Srwatson
294101099Srwatsonstatic int
295101099Srwatsonmac_bsdextended_check(struct ucred *cred, uid_t object_uid, gid_t object_gid,
296106212Srwatson    int acc_mode)
297101099Srwatson{
298101099Srwatson	int error, i;
299101099Srwatson
300132563Srwatson	if (suser_cred(cred, 0) == 0)
301132563Srwatson		return (0);
302132563Srwatson
303101099Srwatson	for (i = 0; i < rule_slots; i++) {
304101099Srwatson		if (rules[i] == NULL)
305101099Srwatson			continue;
306101099Srwatson
307108376Srwatson		/*
308108376Srwatson		 * Since we don't separately handle append, map append to
309108376Srwatson		 * write.
310108376Srwatson		 */
311108376Srwatson		if (acc_mode & VAPPEND) {
312108376Srwatson			acc_mode &= ~VAPPEND;
313108376Srwatson			acc_mode |= VWRITE;
314108376Srwatson		}
315108376Srwatson
316101099Srwatson		error = mac_bsdextended_rulecheck(rules[i], cred, object_uid,
317101099Srwatson		    object_gid, acc_mode);
318134131Strhodes		if (error == EJUSTRETURN)
319134131Strhodes			break;
320101099Srwatson		if (error)
321101099Srwatson			return (error);
322101099Srwatson	}
323101099Srwatson
324101099Srwatson	return (0);
325101099Srwatson}
326101099Srwatson
327101099Srwatsonstatic int
328112575Srwatsonmac_bsdextended_check_system_swapon(struct ucred *cred, struct vnode *vp,
329112575Srwatson    struct label *label)
330112575Srwatson{
331112575Srwatson	struct vattr vap;
332112575Srwatson	int error;
333112575Srwatson
334112575Srwatson	if (!mac_bsdextended_enabled)
335112575Srwatson		return (0);
336112575Srwatson
337112575Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
338112575Srwatson	if (error)
339112575Srwatson		return (error);
340112575Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
341112575Srwatson}
342112575Srwatson
343112575Srwatsonstatic int
344101099Srwatsonmac_bsdextended_check_vnode_access(struct ucred *cred, struct vnode *vp,
345106212Srwatson    struct label *label, int acc_mode)
346101099Srwatson{
347101099Srwatson	struct vattr vap;
348101099Srwatson	int error;
349101099Srwatson
350101099Srwatson	if (!mac_bsdextended_enabled)
351101099Srwatson		return (0);
352101099Srwatson
353101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
354101099Srwatson	if (error)
355101099Srwatson		return (error);
356106212Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
357101099Srwatson}
358101099Srwatson
359101099Srwatsonstatic int
360101099Srwatsonmac_bsdextended_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
361101099Srwatson    struct label *dlabel)
362101099Srwatson{
363101099Srwatson	struct vattr vap;
364101099Srwatson	int error;
365101099Srwatson
366101099Srwatson	if (!mac_bsdextended_enabled)
367101099Srwatson		return (0);
368101099Srwatson
369101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
370101099Srwatson	if (error)
371101099Srwatson		return (error);
372101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VEXEC));
373101099Srwatson}
374101099Srwatson
375101099Srwatsonstatic int
376101099Srwatsonmac_bsdextended_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
377101099Srwatson    struct label *dlabel)
378101099Srwatson{
379101099Srwatson	struct vattr vap;
380101099Srwatson	int error;
381101099Srwatson
382101099Srwatson	if (!mac_bsdextended_enabled)
383101099Srwatson		return (0);
384101099Srwatson
385101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
386101099Srwatson	if (error)
387101099Srwatson		return (error);
388101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VEXEC));
389101099Srwatson}
390101099Srwatson
391101099Srwatsonstatic int
392101099Srwatsonmac_bsdextended_check_create_vnode(struct ucred *cred, struct vnode *dvp,
393101099Srwatson    struct label *dlabel, struct componentname *cnp, struct vattr *vap)
394101099Srwatson{
395101099Srwatson	struct vattr dvap;
396101099Srwatson	int error;
397101099Srwatson
398101099Srwatson	if (!mac_bsdextended_enabled)
399101099Srwatson		return (0);
400101099Srwatson
401101099Srwatson	error = VOP_GETATTR(dvp, &dvap, cred, curthread);
402101099Srwatson	if (error)
403101099Srwatson		return (error);
404101099Srwatson	return (mac_bsdextended_check(cred, dvap.va_uid, dvap.va_gid, VWRITE));
405101099Srwatson}
406101099Srwatson
407101099Srwatsonstatic int
408101099Srwatsonmac_bsdextended_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
409101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
410101099Srwatson    struct componentname *cnp)
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);
421101099Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
422101099Srwatson	if (error)
423101099Srwatson		return (error);
424101099Srwatson
425101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
426101099Srwatson	if (error)
427101099Srwatson		return (error);
428101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
429101099Srwatson}
430101099Srwatson
431101099Srwatsonstatic int
432101099Srwatsonmac_bsdextended_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
433101099Srwatson    struct label *label, acl_type_t type)
434101099Srwatson{
435101099Srwatson	struct vattr vap;
436101099Srwatson	int error;
437101099Srwatson
438101099Srwatson	if (!mac_bsdextended_enabled)
439101099Srwatson		return (0);
440101099Srwatson
441101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
442117247Srwatson	if (error)
443101099Srwatson		return (error);
444101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
445101099Srwatson}
446101099Srwatson
447101099Srwatsonstatic int
448119202Srwatsonmac_bsdextended_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
449119202Srwatson    struct label *label, int attrnamespace, const char *name)
450119202Srwatson{
451119202Srwatson	struct vattr vap;
452119202Srwatson	int error;
453119202Srwatson
454119202Srwatson	if (!mac_bsdextended_enabled)
455119202Srwatson		return (0);
456119202Srwatson
457119202Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
458119202Srwatson	if (error)
459119202Srwatson		return (error);
460119202Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
461119202Srwatson}
462119202Srwatson
463119202Srwatsonstatic int
464101099Srwatsonmac_bsdextended_check_vnode_exec(struct ucred *cred, struct vnode *vp,
465106648Srwatson    struct label *label, struct image_params *imgp,
466106648Srwatson    struct label *execlabel)
467101099Srwatson{
468101099Srwatson	struct vattr vap;
469101099Srwatson	int error;
470101099Srwatson
471101099Srwatson	if (!mac_bsdextended_enabled)
472101099Srwatson		return (0);
473101099Srwatson
474101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
475101099Srwatson	if (error)
476101099Srwatson		return (error);
477101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
478101099Srwatson	    VREAD|VEXEC));
479101099Srwatson}
480101099Srwatson
481101099Srwatsonstatic int
482101099Srwatsonmac_bsdextended_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
483101099Srwatson    struct label *label, acl_type_t type)
484101099Srwatson{
485101099Srwatson	struct vattr vap;
486101099Srwatson	int error;
487101099Srwatson
488101099Srwatson	if (!mac_bsdextended_enabled)
489101099Srwatson		return (0);
490101099Srwatson
491101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
492101099Srwatson	if (error)
493101099Srwatson		return (error);
494101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VSTAT));
495101099Srwatson}
496101099Srwatson
497101099Srwatsonstatic int
498101099Srwatsonmac_bsdextended_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
499101099Srwatson    struct label *label, int attrnamespace, const char *name, struct uio *uio)
500101099Srwatson{
501101099Srwatson	struct vattr vap;
502101099Srwatson	int error;
503101099Srwatson
504101099Srwatson	if (!mac_bsdextended_enabled)
505101099Srwatson		return (0);
506101099Srwatson
507101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
508101099Srwatson	if (error)
509101099Srwatson		return (error);
510101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
511101099Srwatson}
512101099Srwatson
513101099Srwatsonstatic int
514104530Srwatsonmac_bsdextended_check_vnode_link(struct ucred *cred, struct vnode *dvp,
515104530Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
516104530Srwatson    struct componentname *cnp)
517104530Srwatson{
518104530Srwatson	struct vattr vap;
519104530Srwatson	int error;
520104530Srwatson
521104530Srwatson	if (!mac_bsdextended_enabled)
522104530Srwatson		return (0);
523104530Srwatson
524104530Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
525104530Srwatson	if (error)
526104530Srwatson		return (error);
527104530Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
528106214Srwatson	if (error)
529106214Srwatson		return (error);
530104530Srwatson
531104530Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
532104530Srwatson	if (error)
533104530Srwatson		return (error);
534104530Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
535104530Srwatson	if (error)
536104530Srwatson		return (error);
537104530Srwatson	return (0);
538104530Srwatson}
539104530Srwatson
540104530Srwatsonstatic int
541119202Srwatsonmac_bsdextended_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
542119202Srwatson    struct label *label, int attrnamespace)
543119202Srwatson{
544119202Srwatson	struct vattr vap;
545119202Srwatson	int error;
546119202Srwatson
547119202Srwatson	if (!mac_bsdextended_enabled)
548119202Srwatson		return (0);
549119202Srwatson
550119202Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
551119202Srwatson	if (error)
552119202Srwatson		return (error);
553119202Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
554119202Srwatson}
555119202Srwatson
556119202Srwatsonstatic int
557101099Srwatsonmac_bsdextended_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
558101099Srwatson    struct label *dlabel, struct componentname *cnp)
559101099Srwatson{
560101099Srwatson	struct vattr vap;
561101099Srwatson	int error;
562117247Srwatson
563101099Srwatson	if (!mac_bsdextended_enabled)
564101099Srwatson		return (0);
565117247Srwatson
566101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
567101099Srwatson	if (error)
568101099Srwatson		return (error);
569101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VEXEC));
570101099Srwatson}
571101099Srwatson
572101099Srwatsonstatic int
573101099Srwatsonmac_bsdextended_check_vnode_open(struct ucred *cred, struct vnode *vp,
574106212Srwatson    struct label *filelabel, int acc_mode)
575101099Srwatson{
576101099Srwatson	struct vattr vap;
577101099Srwatson	int error;
578101099Srwatson
579101099Srwatson	if (!mac_bsdextended_enabled)
580101099Srwatson		return (0);
581101099Srwatson
582101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
583101099Srwatson	if (error)
584101099Srwatson		return (error);
585101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
586101099Srwatson}
587101099Srwatson
588101099Srwatsonstatic int
589101099Srwatsonmac_bsdextended_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
590101099Srwatson    struct label *dlabel)
591101099Srwatson{
592101099Srwatson	struct vattr vap;
593101099Srwatson	int error;
594101099Srwatson
595101099Srwatson	if (!mac_bsdextended_enabled)
596101099Srwatson		return (0);
597101099Srwatson
598101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
599101099Srwatson	if (error)
600101099Srwatson		return (error);
601101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
602101099Srwatson}
603101099Srwatson
604101099Srwatsonstatic int
605101099Srwatsonmac_bsdextended_check_vnode_readdlink(struct ucred *cred, struct vnode *vp,
606101099Srwatson    struct label *label)
607101099Srwatson{
608101099Srwatson	struct vattr vap;
609101099Srwatson	int error;
610101099Srwatson
611101099Srwatson	if (!mac_bsdextended_enabled)
612101099Srwatson		return (0);
613101099Srwatson
614101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
615101099Srwatson	if (error)
616101099Srwatson		return (error);
617101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
618101099Srwatson}
619101099Srwatson
620101099Srwatsonstatic int
621101099Srwatsonmac_bsdextended_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
622101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
623101099Srwatson    struct componentname *cnp)
624101099Srwatson{
625101099Srwatson	struct vattr vap;
626101099Srwatson	int error;
627101099Srwatson
628101099Srwatson	if (!mac_bsdextended_enabled)
629101099Srwatson		return (0);
630101099Srwatson
631101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
632101099Srwatson	if (error)
633101099Srwatson		return (error);
634101099Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
635101099Srwatson	if (error)
636101099Srwatson		return (error);
637101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
638101099Srwatson	if (error)
639101099Srwatson		return (error);
640101099Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
641101099Srwatson
642101099Srwatson	return (error);
643101099Srwatson}
644101099Srwatson
645101099Srwatsonstatic int
646101099Srwatsonmac_bsdextended_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
647101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
648101099Srwatson    struct componentname *cnp)
649101099Srwatson{
650101099Srwatson	struct vattr vap;
651101099Srwatson	int error;
652101099Srwatson
653101099Srwatson	if (!mac_bsdextended_enabled)
654101099Srwatson		return (0);
655101099Srwatson
656101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
657101099Srwatson	if (error)
658101099Srwatson		return (error);
659101099Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
660101099Srwatson	if (error)
661101099Srwatson		return (error);
662101099Srwatson
663101099Srwatson	if (vp != NULL) {
664101099Srwatson		error = VOP_GETATTR(vp, &vap, cred, curthread);
665101099Srwatson		if (error)
666101099Srwatson			return (error);
667101099Srwatson		error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
668101099Srwatson		    VWRITE);
669101099Srwatson	}
670101099Srwatson
671101099Srwatson	return (error);
672101099Srwatson}
673101099Srwatson
674101099Srwatsonstatic int
675101099Srwatsonmac_bsdextended_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
676101099Srwatson    struct label *label)
677101099Srwatson{
678101099Srwatson	struct vattr vap;
679101099Srwatson	int error;
680101099Srwatson
681101099Srwatson	if (!mac_bsdextended_enabled)
682101099Srwatson		return (0);
683101099Srwatson
684101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
685101099Srwatson	if (error)
686101099Srwatson		return (error);
687101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
688101099Srwatson}
689101099Srwatson
690101099Srwatsonstatic int
691101099Srwatsonmac_bsdextended_check_setacl_vnode(struct ucred *cred, struct vnode *vp,
692101099Srwatson    struct label *label, acl_type_t type, struct acl *acl)
693101099Srwatson{
694101099Srwatson	struct vattr vap;
695101099Srwatson	int error;
696101099Srwatson
697101099Srwatson	if (!mac_bsdextended_enabled)
698101099Srwatson		return (0);
699101099Srwatson
700101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
701101099Srwatson	if (error)
702101099Srwatson		return (error);
703101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
704101099Srwatson}
705101099Srwatson
706101099Srwatsonstatic int
707101099Srwatsonmac_bsdextended_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
708101099Srwatson    struct label *label, int attrnamespace, const char *name, struct uio *uio)
709101099Srwatson{
710101099Srwatson	struct vattr vap;
711101099Srwatson	int error;
712101099Srwatson
713101099Srwatson	if (!mac_bsdextended_enabled)
714101099Srwatson		return (0);
715101099Srwatson
716101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
717101099Srwatson	if (error)
718101099Srwatson		return (error);
719101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
720101099Srwatson}
721101099Srwatson
722101099Srwatsonstatic int
723101099Srwatsonmac_bsdextended_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
724101099Srwatson    struct label *label, u_long flags)
725101099Srwatson{
726101099Srwatson	struct vattr vap;
727101099Srwatson	int error;
728101099Srwatson
729101099Srwatson	if (!mac_bsdextended_enabled)
730101099Srwatson		return (0);
731101099Srwatson
732101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
733101099Srwatson	if (error)
734101099Srwatson		return (error);
735101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
736101099Srwatson}
737101099Srwatson
738101099Srwatsonstatic int
739101099Srwatsonmac_bsdextended_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
740101099Srwatson    struct label *label, mode_t mode)
741101099Srwatson{
742101099Srwatson	struct vattr vap;
743101099Srwatson	int error;
744101099Srwatson
745101099Srwatson	if (!mac_bsdextended_enabled)
746101099Srwatson		return (0);
747101099Srwatson
748101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
749101099Srwatson	if (error)
750101099Srwatson		return (error);
751101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
752101099Srwatson}
753101099Srwatson
754101099Srwatsonstatic int
755101099Srwatsonmac_bsdextended_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
756101099Srwatson    struct label *label, uid_t uid, gid_t gid)
757101099Srwatson{
758101099Srwatson	struct vattr vap;
759101099Srwatson	int error;
760101099Srwatson
761101099Srwatson	if (!mac_bsdextended_enabled)
762101099Srwatson		return (0);
763101099Srwatson
764101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
765101099Srwatson	if (error)
766101099Srwatson		return (error);
767101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
768101099Srwatson}
769101099Srwatson
770101099Srwatsonstatic int
771101099Srwatsonmac_bsdextended_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
772101099Srwatson    struct label *label, struct timespec atime, struct timespec utime)
773101099Srwatson{
774101099Srwatson	struct vattr vap;
775101099Srwatson	int error;
776101099Srwatson
777101099Srwatson	if (!mac_bsdextended_enabled)
778101099Srwatson		return (0);
779101099Srwatson
780101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
781101099Srwatson	if (error)
782101099Srwatson		return (error);
783101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
784101099Srwatson}
785101099Srwatson
786101099Srwatsonstatic int
787102129Srwatsonmac_bsdextended_check_vnode_stat(struct ucred *active_cred,
788102129Srwatson    struct ucred *file_cred, struct vnode *vp, struct label *label)
789101099Srwatson{
790101099Srwatson	struct vattr vap;
791101099Srwatson	int error;
792101099Srwatson
793101099Srwatson	if (!mac_bsdextended_enabled)
794101099Srwatson		return (0);
795101099Srwatson
796102129Srwatson	error = VOP_GETATTR(vp, &vap, active_cred, curthread);
797101099Srwatson	if (error)
798101099Srwatson		return (error);
799102129Srwatson	return (mac_bsdextended_check(active_cred, vap.va_uid, vap.va_gid,
800102129Srwatson	    VSTAT));
801101099Srwatson}
802101099Srwatson
803106217Srwatsonstatic struct mac_policy_ops mac_bsdextended_ops =
804101099Srwatson{
805106217Srwatson	.mpo_destroy = mac_bsdextended_destroy,
806106217Srwatson	.mpo_init = mac_bsdextended_init,
807112575Srwatson	.mpo_check_system_swapon = mac_bsdextended_check_system_swapon,
808106217Srwatson	.mpo_check_vnode_access = mac_bsdextended_check_vnode_access,
809106217Srwatson	.mpo_check_vnode_chdir = mac_bsdextended_check_vnode_chdir,
810106217Srwatson	.mpo_check_vnode_chroot = mac_bsdextended_check_vnode_chroot,
811106217Srwatson	.mpo_check_vnode_create = mac_bsdextended_check_create_vnode,
812106217Srwatson	.mpo_check_vnode_delete = mac_bsdextended_check_vnode_delete,
813106217Srwatson	.mpo_check_vnode_deleteacl = mac_bsdextended_check_vnode_deleteacl,
814119202Srwatson	.mpo_check_vnode_deleteextattr = mac_bsdextended_check_vnode_deleteextattr,
815106217Srwatson	.mpo_check_vnode_exec = mac_bsdextended_check_vnode_exec,
816106217Srwatson	.mpo_check_vnode_getacl = mac_bsdextended_check_vnode_getacl,
817106217Srwatson	.mpo_check_vnode_getextattr = mac_bsdextended_check_vnode_getextattr,
818106217Srwatson	.mpo_check_vnode_link = mac_bsdextended_check_vnode_link,
819119202Srwatson	.mpo_check_vnode_listextattr = mac_bsdextended_check_vnode_listextattr,
820106217Srwatson	.mpo_check_vnode_lookup = mac_bsdextended_check_vnode_lookup,
821106217Srwatson	.mpo_check_vnode_open = mac_bsdextended_check_vnode_open,
822106217Srwatson	.mpo_check_vnode_readdir = mac_bsdextended_check_vnode_readdir,
823106217Srwatson	.mpo_check_vnode_readlink = mac_bsdextended_check_vnode_readdlink,
824106217Srwatson	.mpo_check_vnode_rename_from = mac_bsdextended_check_vnode_rename_from,
825106217Srwatson	.mpo_check_vnode_rename_to = mac_bsdextended_check_vnode_rename_to,
826106217Srwatson	.mpo_check_vnode_revoke = mac_bsdextended_check_vnode_revoke,
827106217Srwatson	.mpo_check_vnode_setacl = mac_bsdextended_check_setacl_vnode,
828106217Srwatson	.mpo_check_vnode_setextattr = mac_bsdextended_check_vnode_setextattr,
829106217Srwatson	.mpo_check_vnode_setflags = mac_bsdextended_check_vnode_setflags,
830106217Srwatson	.mpo_check_vnode_setmode = mac_bsdextended_check_vnode_setmode,
831106217Srwatson	.mpo_check_vnode_setowner = mac_bsdextended_check_vnode_setowner,
832106217Srwatson	.mpo_check_vnode_setutimes = mac_bsdextended_check_vnode_setutimes,
833106217Srwatson	.mpo_check_vnode_stat = mac_bsdextended_check_vnode_stat,
834101099Srwatson};
835101099Srwatson
836112717SrwatsonMAC_POLICY_SET(&mac_bsdextended_ops, mac_bsdextended,
837101099Srwatson    "TrustedBSD MAC/BSD Extended", MPC_LOADTIME_FLAG_UNLOADOK, NULL);
838