ugidfw_system.c revision 136739
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 136739 2004-10-21 11:19:02Z rwatson $
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
125136739Srwatson	if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM)
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		 */
311136739Srwatson		if (acc_mode & MBI_APPEND) {
312136739Srwatson			acc_mode &= ~MBI_APPEND;
313136739Srwatson			acc_mode |= MBI_WRITE;
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);
340136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
341136739Srwatson	    MBI_WRITE));
342112575Srwatson}
343112575Srwatson
344112575Srwatsonstatic int
345101099Srwatsonmac_bsdextended_check_vnode_access(struct ucred *cred, struct vnode *vp,
346106212Srwatson    struct label *label, int acc_mode)
347101099Srwatson{
348101099Srwatson	struct vattr vap;
349101099Srwatson	int error;
350101099Srwatson
351101099Srwatson	if (!mac_bsdextended_enabled)
352101099Srwatson		return (0);
353101099Srwatson
354101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
355101099Srwatson	if (error)
356101099Srwatson		return (error);
357106212Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
358101099Srwatson}
359101099Srwatson
360101099Srwatsonstatic int
361101099Srwatsonmac_bsdextended_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
362101099Srwatson    struct label *dlabel)
363101099Srwatson{
364101099Srwatson	struct vattr vap;
365101099Srwatson	int error;
366101099Srwatson
367101099Srwatson	if (!mac_bsdextended_enabled)
368101099Srwatson		return (0);
369101099Srwatson
370101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
371101099Srwatson	if (error)
372101099Srwatson		return (error);
373136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
374136739Srwatson	    MBI_EXEC));
375101099Srwatson}
376101099Srwatson
377101099Srwatsonstatic int
378101099Srwatsonmac_bsdextended_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
379101099Srwatson    struct label *dlabel)
380101099Srwatson{
381101099Srwatson	struct vattr vap;
382101099Srwatson	int error;
383101099Srwatson
384101099Srwatson	if (!mac_bsdextended_enabled)
385101099Srwatson		return (0);
386101099Srwatson
387101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
388101099Srwatson	if (error)
389101099Srwatson		return (error);
390136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
391136739Srwatson	    MBI_EXEC));
392101099Srwatson}
393101099Srwatson
394101099Srwatsonstatic int
395101099Srwatsonmac_bsdextended_check_create_vnode(struct ucred *cred, struct vnode *dvp,
396101099Srwatson    struct label *dlabel, struct componentname *cnp, struct vattr *vap)
397101099Srwatson{
398101099Srwatson	struct vattr dvap;
399101099Srwatson	int error;
400101099Srwatson
401101099Srwatson	if (!mac_bsdextended_enabled)
402101099Srwatson		return (0);
403101099Srwatson
404101099Srwatson	error = VOP_GETATTR(dvp, &dvap, cred, curthread);
405101099Srwatson	if (error)
406101099Srwatson		return (error);
407136739Srwatson	return (mac_bsdextended_check(cred, dvap.va_uid, dvap.va_gid,
408136739Srwatson	    MBI_WRITE));
409101099Srwatson}
410101099Srwatson
411101099Srwatsonstatic int
412101099Srwatsonmac_bsdextended_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
413101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
414101099Srwatson    struct componentname *cnp)
415101099Srwatson{
416101099Srwatson	struct vattr vap;
417101099Srwatson	int error;
418101099Srwatson
419101099Srwatson	if (!mac_bsdextended_enabled)
420101099Srwatson		return (0);
421101099Srwatson
422101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
423101099Srwatson	if (error)
424101099Srwatson		return (error);
425136739Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
426136739Srwatson	    MBI_WRITE);
427101099Srwatson	if (error)
428101099Srwatson		return (error);
429101099Srwatson
430101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
431101099Srwatson	if (error)
432101099Srwatson		return (error);
433136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
434136739Srwatson	    MBI_WRITE));
435101099Srwatson}
436101099Srwatson
437101099Srwatsonstatic int
438101099Srwatsonmac_bsdextended_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
439101099Srwatson    struct label *label, acl_type_t type)
440101099Srwatson{
441101099Srwatson	struct vattr vap;
442101099Srwatson	int error;
443101099Srwatson
444101099Srwatson	if (!mac_bsdextended_enabled)
445101099Srwatson		return (0);
446101099Srwatson
447101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
448117247Srwatson	if (error)
449101099Srwatson		return (error);
450136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
451136739Srwatson	    MBI_ADMIN));
452101099Srwatson}
453101099Srwatson
454101099Srwatsonstatic int
455119202Srwatsonmac_bsdextended_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
456119202Srwatson    struct label *label, int attrnamespace, const char *name)
457119202Srwatson{
458119202Srwatson	struct vattr vap;
459119202Srwatson	int error;
460119202Srwatson
461119202Srwatson	if (!mac_bsdextended_enabled)
462119202Srwatson		return (0);
463119202Srwatson
464119202Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
465119202Srwatson	if (error)
466119202Srwatson		return (error);
467136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
468136739Srwatson	    MBI_WRITE));
469119202Srwatson}
470119202Srwatson
471119202Srwatsonstatic int
472101099Srwatsonmac_bsdextended_check_vnode_exec(struct ucred *cred, struct vnode *vp,
473106648Srwatson    struct label *label, struct image_params *imgp,
474106648Srwatson    struct label *execlabel)
475101099Srwatson{
476101099Srwatson	struct vattr vap;
477101099Srwatson	int error;
478101099Srwatson
479101099Srwatson	if (!mac_bsdextended_enabled)
480101099Srwatson		return (0);
481101099Srwatson
482101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
483101099Srwatson	if (error)
484101099Srwatson		return (error);
485101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
486136739Srwatson	    MBI_READ|MBI_EXEC));
487101099Srwatson}
488101099Srwatson
489101099Srwatsonstatic int
490101099Srwatsonmac_bsdextended_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
491101099Srwatson    struct label *label, acl_type_t type)
492101099Srwatson{
493101099Srwatson	struct vattr vap;
494101099Srwatson	int error;
495101099Srwatson
496101099Srwatson	if (!mac_bsdextended_enabled)
497101099Srwatson		return (0);
498101099Srwatson
499101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
500101099Srwatson	if (error)
501101099Srwatson		return (error);
502136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
503136739Srwatson	    MBI_STAT));
504101099Srwatson}
505101099Srwatson
506101099Srwatsonstatic int
507101099Srwatsonmac_bsdextended_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
508101099Srwatson    struct label *label, int attrnamespace, const char *name, struct uio *uio)
509101099Srwatson{
510101099Srwatson	struct vattr vap;
511101099Srwatson	int error;
512101099Srwatson
513101099Srwatson	if (!mac_bsdextended_enabled)
514101099Srwatson		return (0);
515101099Srwatson
516101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
517101099Srwatson	if (error)
518101099Srwatson		return (error);
519136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
520136739Srwatson	    MBI_READ));
521101099Srwatson}
522101099Srwatson
523101099Srwatsonstatic int
524104530Srwatsonmac_bsdextended_check_vnode_link(struct ucred *cred, struct vnode *dvp,
525104530Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
526104530Srwatson    struct componentname *cnp)
527104530Srwatson{
528104530Srwatson	struct vattr vap;
529104530Srwatson	int error;
530104530Srwatson
531104530Srwatson	if (!mac_bsdextended_enabled)
532104530Srwatson		return (0);
533104530Srwatson
534104530Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
535104530Srwatson	if (error)
536104530Srwatson		return (error);
537136739Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
538136739Srwatson	    MBI_WRITE);
539106214Srwatson	if (error)
540106214Srwatson		return (error);
541104530Srwatson
542104530Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
543104530Srwatson	if (error)
544104530Srwatson		return (error);
545136739Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
546136739Srwatson	    MBI_WRITE);
547104530Srwatson	if (error)
548104530Srwatson		return (error);
549104530Srwatson	return (0);
550104530Srwatson}
551104530Srwatson
552104530Srwatsonstatic int
553119202Srwatsonmac_bsdextended_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
554119202Srwatson    struct label *label, int attrnamespace)
555119202Srwatson{
556119202Srwatson	struct vattr vap;
557119202Srwatson	int error;
558119202Srwatson
559119202Srwatson	if (!mac_bsdextended_enabled)
560119202Srwatson		return (0);
561119202Srwatson
562119202Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
563119202Srwatson	if (error)
564119202Srwatson		return (error);
565136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
566136739Srwatson	    MBI_READ));
567119202Srwatson}
568119202Srwatson
569119202Srwatsonstatic int
570101099Srwatsonmac_bsdextended_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
571101099Srwatson    struct label *dlabel, struct componentname *cnp)
572101099Srwatson{
573101099Srwatson	struct vattr vap;
574101099Srwatson	int error;
575117247Srwatson
576101099Srwatson	if (!mac_bsdextended_enabled)
577101099Srwatson		return (0);
578117247Srwatson
579101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
580101099Srwatson	if (error)
581101099Srwatson		return (error);
582136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
583136739Srwatson	    MBI_EXEC));
584101099Srwatson}
585101099Srwatson
586101099Srwatsonstatic int
587101099Srwatsonmac_bsdextended_check_vnode_open(struct ucred *cred, struct vnode *vp,
588106212Srwatson    struct label *filelabel, int acc_mode)
589101099Srwatson{
590101099Srwatson	struct vattr vap;
591101099Srwatson	int error;
592101099Srwatson
593101099Srwatson	if (!mac_bsdextended_enabled)
594101099Srwatson		return (0);
595101099Srwatson
596101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
597101099Srwatson	if (error)
598101099Srwatson		return (error);
599101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
600101099Srwatson}
601101099Srwatson
602101099Srwatsonstatic int
603101099Srwatsonmac_bsdextended_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
604101099Srwatson    struct label *dlabel)
605101099Srwatson{
606101099Srwatson	struct vattr vap;
607101099Srwatson	int error;
608101099Srwatson
609101099Srwatson	if (!mac_bsdextended_enabled)
610101099Srwatson		return (0);
611101099Srwatson
612101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
613101099Srwatson	if (error)
614101099Srwatson		return (error);
615136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
616136739Srwatson	    MBI_READ));
617101099Srwatson}
618101099Srwatson
619101099Srwatsonstatic int
620101099Srwatsonmac_bsdextended_check_vnode_readdlink(struct ucred *cred, struct vnode *vp,
621101099Srwatson    struct label *label)
622101099Srwatson{
623101099Srwatson	struct vattr vap;
624101099Srwatson	int error;
625101099Srwatson
626101099Srwatson	if (!mac_bsdextended_enabled)
627101099Srwatson		return (0);
628101099Srwatson
629101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
630101099Srwatson	if (error)
631101099Srwatson		return (error);
632136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
633136739Srwatson	    MBI_READ));
634101099Srwatson}
635101099Srwatson
636101099Srwatsonstatic int
637101099Srwatsonmac_bsdextended_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
638101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
639101099Srwatson    struct componentname *cnp)
640101099Srwatson{
641101099Srwatson	struct vattr vap;
642101099Srwatson	int error;
643101099Srwatson
644101099Srwatson	if (!mac_bsdextended_enabled)
645101099Srwatson		return (0);
646101099Srwatson
647101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
648101099Srwatson	if (error)
649101099Srwatson		return (error);
650136739Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
651136739Srwatson	    MBI_WRITE);
652101099Srwatson	if (error)
653101099Srwatson		return (error);
654101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
655101099Srwatson	if (error)
656101099Srwatson		return (error);
657136739Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
658136739Srwatson	    MBI_WRITE);
659101099Srwatson
660101099Srwatson	return (error);
661101099Srwatson}
662101099Srwatson
663101099Srwatsonstatic int
664101099Srwatsonmac_bsdextended_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
665101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
666101099Srwatson    struct componentname *cnp)
667101099Srwatson{
668101099Srwatson	struct vattr vap;
669101099Srwatson	int error;
670101099Srwatson
671101099Srwatson	if (!mac_bsdextended_enabled)
672101099Srwatson		return (0);
673101099Srwatson
674101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
675101099Srwatson	if (error)
676101099Srwatson		return (error);
677136739Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
678136739Srwatson	    MBI_WRITE);
679101099Srwatson	if (error)
680101099Srwatson		return (error);
681101099Srwatson
682101099Srwatson	if (vp != NULL) {
683101099Srwatson		error = VOP_GETATTR(vp, &vap, cred, curthread);
684101099Srwatson		if (error)
685101099Srwatson			return (error);
686101099Srwatson		error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
687136739Srwatson		    MBI_WRITE);
688101099Srwatson	}
689101099Srwatson
690101099Srwatson	return (error);
691101099Srwatson}
692101099Srwatson
693101099Srwatsonstatic int
694101099Srwatsonmac_bsdextended_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
695101099Srwatson    struct label *label)
696101099Srwatson{
697101099Srwatson	struct vattr vap;
698101099Srwatson	int error;
699101099Srwatson
700101099Srwatson	if (!mac_bsdextended_enabled)
701101099Srwatson		return (0);
702101099Srwatson
703101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
704101099Srwatson	if (error)
705101099Srwatson		return (error);
706136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
707136739Srwatson	    MBI_ADMIN));
708101099Srwatson}
709101099Srwatson
710101099Srwatsonstatic int
711101099Srwatsonmac_bsdextended_check_setacl_vnode(struct ucred *cred, struct vnode *vp,
712101099Srwatson    struct label *label, acl_type_t type, struct acl *acl)
713101099Srwatson{
714101099Srwatson	struct vattr vap;
715101099Srwatson	int error;
716101099Srwatson
717101099Srwatson	if (!mac_bsdextended_enabled)
718101099Srwatson		return (0);
719101099Srwatson
720101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
721101099Srwatson	if (error)
722101099Srwatson		return (error);
723136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
724136739Srwatson	    MBI_ADMIN));
725101099Srwatson}
726101099Srwatson
727101099Srwatsonstatic int
728101099Srwatsonmac_bsdextended_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
729101099Srwatson    struct label *label, int attrnamespace, const char *name, struct uio *uio)
730101099Srwatson{
731101099Srwatson	struct vattr vap;
732101099Srwatson	int error;
733101099Srwatson
734101099Srwatson	if (!mac_bsdextended_enabled)
735101099Srwatson		return (0);
736101099Srwatson
737101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
738101099Srwatson	if (error)
739101099Srwatson		return (error);
740136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
741136739Srwatson	    MBI_WRITE));
742101099Srwatson}
743101099Srwatson
744101099Srwatsonstatic int
745101099Srwatsonmac_bsdextended_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
746101099Srwatson    struct label *label, u_long flags)
747101099Srwatson{
748101099Srwatson	struct vattr vap;
749101099Srwatson	int error;
750101099Srwatson
751101099Srwatson	if (!mac_bsdextended_enabled)
752101099Srwatson		return (0);
753101099Srwatson
754101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
755101099Srwatson	if (error)
756101099Srwatson		return (error);
757136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
758136739Srwatson	    MBI_ADMIN));
759101099Srwatson}
760101099Srwatson
761101099Srwatsonstatic int
762101099Srwatsonmac_bsdextended_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
763101099Srwatson    struct label *label, mode_t mode)
764101099Srwatson{
765101099Srwatson	struct vattr vap;
766101099Srwatson	int error;
767101099Srwatson
768101099Srwatson	if (!mac_bsdextended_enabled)
769101099Srwatson		return (0);
770101099Srwatson
771101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
772101099Srwatson	if (error)
773101099Srwatson		return (error);
774136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
775136739Srwatson	    MBI_ADMIN));
776101099Srwatson}
777101099Srwatson
778101099Srwatsonstatic int
779101099Srwatsonmac_bsdextended_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
780101099Srwatson    struct label *label, uid_t uid, gid_t gid)
781101099Srwatson{
782101099Srwatson	struct vattr vap;
783101099Srwatson	int error;
784101099Srwatson
785101099Srwatson	if (!mac_bsdextended_enabled)
786101099Srwatson		return (0);
787101099Srwatson
788101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
789101099Srwatson	if (error)
790101099Srwatson		return (error);
791136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
792136739Srwatson	   MBI_ADMIN));
793101099Srwatson}
794101099Srwatson
795101099Srwatsonstatic int
796101099Srwatsonmac_bsdextended_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
797101099Srwatson    struct label *label, struct timespec atime, struct timespec utime)
798101099Srwatson{
799101099Srwatson	struct vattr vap;
800101099Srwatson	int error;
801101099Srwatson
802101099Srwatson	if (!mac_bsdextended_enabled)
803101099Srwatson		return (0);
804101099Srwatson
805101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
806101099Srwatson	if (error)
807101099Srwatson		return (error);
808136739Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
809136739Srwatson	    MBI_ADMIN));
810101099Srwatson}
811101099Srwatson
812101099Srwatsonstatic int
813102129Srwatsonmac_bsdextended_check_vnode_stat(struct ucred *active_cred,
814102129Srwatson    struct ucred *file_cred, struct vnode *vp, struct label *label)
815101099Srwatson{
816101099Srwatson	struct vattr vap;
817101099Srwatson	int error;
818101099Srwatson
819101099Srwatson	if (!mac_bsdextended_enabled)
820101099Srwatson		return (0);
821101099Srwatson
822102129Srwatson	error = VOP_GETATTR(vp, &vap, active_cred, curthread);
823101099Srwatson	if (error)
824101099Srwatson		return (error);
825102129Srwatson	return (mac_bsdextended_check(active_cred, vap.va_uid, vap.va_gid,
826136739Srwatson	    MBI_STAT));
827101099Srwatson}
828101099Srwatson
829106217Srwatsonstatic struct mac_policy_ops mac_bsdextended_ops =
830101099Srwatson{
831106217Srwatson	.mpo_destroy = mac_bsdextended_destroy,
832106217Srwatson	.mpo_init = mac_bsdextended_init,
833112575Srwatson	.mpo_check_system_swapon = mac_bsdextended_check_system_swapon,
834106217Srwatson	.mpo_check_vnode_access = mac_bsdextended_check_vnode_access,
835106217Srwatson	.mpo_check_vnode_chdir = mac_bsdextended_check_vnode_chdir,
836106217Srwatson	.mpo_check_vnode_chroot = mac_bsdextended_check_vnode_chroot,
837106217Srwatson	.mpo_check_vnode_create = mac_bsdextended_check_create_vnode,
838106217Srwatson	.mpo_check_vnode_delete = mac_bsdextended_check_vnode_delete,
839106217Srwatson	.mpo_check_vnode_deleteacl = mac_bsdextended_check_vnode_deleteacl,
840119202Srwatson	.mpo_check_vnode_deleteextattr = mac_bsdextended_check_vnode_deleteextattr,
841106217Srwatson	.mpo_check_vnode_exec = mac_bsdextended_check_vnode_exec,
842106217Srwatson	.mpo_check_vnode_getacl = mac_bsdextended_check_vnode_getacl,
843106217Srwatson	.mpo_check_vnode_getextattr = mac_bsdextended_check_vnode_getextattr,
844106217Srwatson	.mpo_check_vnode_link = mac_bsdextended_check_vnode_link,
845119202Srwatson	.mpo_check_vnode_listextattr = mac_bsdextended_check_vnode_listextattr,
846106217Srwatson	.mpo_check_vnode_lookup = mac_bsdextended_check_vnode_lookup,
847106217Srwatson	.mpo_check_vnode_open = mac_bsdextended_check_vnode_open,
848106217Srwatson	.mpo_check_vnode_readdir = mac_bsdextended_check_vnode_readdir,
849106217Srwatson	.mpo_check_vnode_readlink = mac_bsdextended_check_vnode_readdlink,
850106217Srwatson	.mpo_check_vnode_rename_from = mac_bsdextended_check_vnode_rename_from,
851106217Srwatson	.mpo_check_vnode_rename_to = mac_bsdextended_check_vnode_rename_to,
852106217Srwatson	.mpo_check_vnode_revoke = mac_bsdextended_check_vnode_revoke,
853106217Srwatson	.mpo_check_vnode_setacl = mac_bsdextended_check_setacl_vnode,
854106217Srwatson	.mpo_check_vnode_setextattr = mac_bsdextended_check_vnode_setextattr,
855106217Srwatson	.mpo_check_vnode_setflags = mac_bsdextended_check_vnode_setflags,
856106217Srwatson	.mpo_check_vnode_setmode = mac_bsdextended_check_vnode_setmode,
857106217Srwatson	.mpo_check_vnode_setowner = mac_bsdextended_check_vnode_setowner,
858106217Srwatson	.mpo_check_vnode_setutimes = mac_bsdextended_check_vnode_setutimes,
859106217Srwatson	.mpo_check_vnode_stat = mac_bsdextended_check_vnode_stat,
860101099Srwatson};
861101099Srwatson
862112717SrwatsonMAC_POLICY_SET(&mac_bsdextended_ops, mac_bsdextended,
863101099Srwatson    "TrustedBSD MAC/BSD Extended", MPC_LOADTIME_FLAG_UNLOADOK, NULL);
864