ugidfw_vnode.c revision 132563
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 132563 2004-07-23 01:53:28Z 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>
61101099Srwatson
62101099Srwatson#include <net/bpfdesc.h>
63101099Srwatson#include <net/if.h>
64101099Srwatson#include <net/if_types.h>
65101099Srwatson#include <net/if_var.h>
66101099Srwatson
67101099Srwatson#include <vm/vm.h>
68101099Srwatson
69101099Srwatson#include <sys/mac_policy.h>
70101099Srwatson
71101099Srwatson#include <security/mac_bsdextended/mac_bsdextended.h>
72101099Srwatson
73101099SrwatsonSYSCTL_DECL(_security_mac);
74101099Srwatson
75101099SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0,
76101099Srwatson    "TrustedBSD extended BSD MAC policy controls");
77101099Srwatson
78101099Srwatsonstatic int	mac_bsdextended_enabled = 1;
79101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW,
80101099Srwatson    &mac_bsdextended_enabled, 0, "Enforce extended BSD policy");
81101099SrwatsonTUNABLE_INT("security.mac.bsdextended.enabled", &mac_bsdextended_enabled);
82101099Srwatson
83101099SrwatsonMALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule");
84101099Srwatson
85101099Srwatson#define	MAC_BSDEXTENDED_MAXRULES	250
86101099Srwatsonstatic struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES];
87101099Srwatsonstatic int rule_count = 0;
88101099Srwatsonstatic int rule_slots = 0;
89101099Srwatson
90101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD,
91101099Srwatson    &rule_count, 0, "Number of defined rules\n");
92101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD,
93101099Srwatson    &rule_slots, 0, "Number of used rule slots\n");
94101099Srwatson
95101099Srwatsonstatic int mac_bsdextended_debugging;
96101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, debugging, CTLFLAG_RW,
97101099Srwatson    &mac_bsdextended_debugging, 0, "Enable debugging on failure");
98101099Srwatson
99101099Srwatsonstatic int
100101099Srwatsonmac_bsdextended_rule_valid(struct mac_bsdextended_rule *rule)
101101099Srwatson{
102101099Srwatson
103101099Srwatson	if ((rule->mbr_subject.mbi_flags | MBI_BITS) != MBI_BITS)
104101099Srwatson		return (EINVAL);
105101099Srwatson
106101099Srwatson	if ((rule->mbr_object.mbi_flags | MBI_BITS) != MBI_BITS)
107101099Srwatson		return (EINVAL);
108101099Srwatson
109101099Srwatson	if ((rule->mbr_mode | VALLPERM) != VALLPERM)
110101099Srwatson		return (EINVAL);
111101099Srwatson
112101099Srwatson	return (0);
113101099Srwatson}
114101099Srwatson
115101099Srwatsonstatic int
116101099Srwatsonsysctl_rule(SYSCTL_HANDLER_ARGS)
117101099Srwatson{
118101099Srwatson	struct mac_bsdextended_rule temprule, *ruleptr;
119101099Srwatson	u_int namelen;
120101099Srwatson	int error, index, *name;
121101099Srwatson
122101099Srwatson	name = (int *)arg1;
123101099Srwatson	namelen = arg2;
124101099Srwatson
125101099Srwatson	/* printf("bsdextended sysctl handler (namelen %d)\n", namelen); */
126101099Srwatson
127101099Srwatson	if (namelen != 1)
128101099Srwatson		return (EINVAL);
129101099Srwatson
130101099Srwatson	index = name[0];
131101099Srwatson	if (index < 0 || index > rule_slots + 1)
132101099Srwatson		return (ENOENT);
133101099Srwatson	if (rule_slots >= MAC_BSDEXTENDED_MAXRULES)
134101099Srwatson		return (ENOENT);
135101099Srwatson
136101099Srwatson	if (req->oldptr) {
137101099Srwatson		if (rules[index] == NULL)
138101099Srwatson			return (ENOENT);
139101099Srwatson
140101099Srwatson		error = SYSCTL_OUT(req, rules[index], sizeof(*rules[index]));
141101099Srwatson		if (error)
142101099Srwatson			return (error);
143101099Srwatson	}
144101099Srwatson
145101099Srwatson	if (req->newptr) {
146101099Srwatson		if (req->newlen == 0) {
147101099Srwatson			/* printf("deletion\n"); */
148101099Srwatson			ruleptr = rules[index];
149101099Srwatson			if (ruleptr == NULL)
150101099Srwatson				return (ENOENT);
151101099Srwatson			rule_count--;
152101099Srwatson			rules[index] = NULL;
153101099Srwatson			FREE(ruleptr, M_MACBSDEXTENDED);
154101099Srwatson			return(0);
155101099Srwatson		}
156101099Srwatson		error = SYSCTL_IN(req, &temprule, sizeof(temprule));
157101099Srwatson		if (error)
158101099Srwatson			return (error);
159101099Srwatson
160101099Srwatson		error = mac_bsdextended_rule_valid(&temprule);
161101099Srwatson		if (error)
162101099Srwatson			return (error);
163101099Srwatson
164101099Srwatson		if (rules[index] == NULL) {
165101099Srwatson			/* printf("addition\n"); */
166101099Srwatson			MALLOC(ruleptr, struct mac_bsdextended_rule *,
167111119Simp			    sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK |
168101099Srwatson			    M_ZERO);
169101099Srwatson			*ruleptr = temprule;
170101099Srwatson			rules[index] = ruleptr;
171101099Srwatson			if (index+1 > rule_slots)
172101099Srwatson				rule_slots = index+1;
173101099Srwatson			rule_count++;
174101099Srwatson		} else {
175101099Srwatson			/* printf("replacement\n"); */
176101099Srwatson			*rules[index] = temprule;
177101099Srwatson		}
178101099Srwatson	}
179101099Srwatson
180101099Srwatson	return (0);
181101099Srwatson}
182101099Srwatson
183101099SrwatsonSYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules,
184101099Srwatson    CTLFLAG_RW, sysctl_rule, "BSD extended MAC rules");
185101099Srwatson
186101099Srwatsonstatic void
187101099Srwatsonmac_bsdextended_init(struct mac_policy_conf *mpc)
188101099Srwatson{
189101099Srwatson
190101099Srwatson	/* Initialize ruleset lock. */
191101099Srwatson	/* Register dynamic sysctl's for rules. */
192101099Srwatson}
193101099Srwatson
194101099Srwatsonstatic void
195101099Srwatsonmac_bsdextended_destroy(struct mac_policy_conf *mpc)
196101099Srwatson{
197101099Srwatson
198101099Srwatson	/* Tear down sysctls. */
199101099Srwatson	/* Destroy ruleset lock. */
200101099Srwatson}
201101099Srwatson
202101099Srwatsonstatic int
203101099Srwatsonmac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
204106212Srwatson    struct ucred *cred, uid_t object_uid, gid_t object_gid, int acc_mode)
205101099Srwatson{
206101099Srwatson	int match;
207101099Srwatson
208101099Srwatson	/*
209101099Srwatson	 * Is there a subject match?
210101099Srwatson	 */
211101099Srwatson	if (rule->mbr_subject.mbi_flags & MBI_UID_DEFINED) {
212101099Srwatson		match =  (rule->mbr_subject.mbi_uid == cred->cr_uid ||
213101099Srwatson		    rule->mbr_subject.mbi_uid == cred->cr_ruid ||
214101099Srwatson		    rule->mbr_subject.mbi_uid == cred->cr_svuid);
215101099Srwatson
216101099Srwatson		if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
217101099Srwatson			match = !match;
218101099Srwatson
219101099Srwatson		if (!match)
220101099Srwatson			return (0);
221101099Srwatson	}
222101099Srwatson
223101099Srwatson	if (rule->mbr_subject.mbi_flags & MBI_GID_DEFINED) {
224101099Srwatson		match = (groupmember(rule->mbr_subject.mbi_gid, cred) ||
225101099Srwatson		    rule->mbr_subject.mbi_gid == cred->cr_rgid ||
226101099Srwatson		    rule->mbr_subject.mbi_gid == cred->cr_svgid);
227101099Srwatson
228101099Srwatson		if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
229101099Srwatson			match = !match;
230101099Srwatson
231101099Srwatson		if (!match)
232101099Srwatson			return (0);
233101099Srwatson	}
234101099Srwatson
235101099Srwatson	/*
236101099Srwatson	 * Is there an object match?
237101099Srwatson	 */
238101099Srwatson	if (rule->mbr_object.mbi_flags & MBI_UID_DEFINED) {
239101099Srwatson		match = (rule->mbr_object.mbi_uid == object_uid);
240101099Srwatson
241101099Srwatson		if (rule->mbr_object.mbi_flags & MBI_NEGATED)
242101099Srwatson			match = !match;
243101099Srwatson
244101099Srwatson		if (!match)
245101099Srwatson			return (0);
246101099Srwatson	}
247101099Srwatson
248101099Srwatson	if (rule->mbr_object.mbi_flags & MBI_GID_DEFINED) {
249101099Srwatson		match = (rule->mbr_object.mbi_gid == object_gid);
250101099Srwatson
251101099Srwatson		if (rule->mbr_object.mbi_flags & MBI_NEGATED)
252101099Srwatson			match = !match;
253101099Srwatson
254101099Srwatson		if (!match)
255101099Srwatson			return (0);
256101099Srwatson	}
257101099Srwatson
258101099Srwatson	/*
259101099Srwatson	 * Is the access permitted?
260101099Srwatson	 */
261101099Srwatson	if ((rule->mbr_mode & acc_mode) != acc_mode) {
262101099Srwatson		if (mac_bsdextended_debugging)
263101099Srwatson			printf("mac_bsdextended: %d:%d request %d on %d:%d"
264101099Srwatson			    " fails\n", cred->cr_ruid, cred->cr_rgid,
265101099Srwatson			    acc_mode, object_uid, object_gid);
266101099Srwatson		return (EACCES);
267101099Srwatson	}
268101099Srwatson
269101099Srwatson	return (0);
270101099Srwatson}
271101099Srwatson
272101099Srwatsonstatic int
273101099Srwatsonmac_bsdextended_check(struct ucred *cred, uid_t object_uid, gid_t object_gid,
274106212Srwatson    int acc_mode)
275101099Srwatson{
276101099Srwatson	int error, i;
277101099Srwatson
278132563Srwatson	if (suser_cred(cred, 0) == 0)
279132563Srwatson		return (0);
280132563Srwatson
281101099Srwatson	for (i = 0; i < rule_slots; i++) {
282101099Srwatson		if (rules[i] == NULL)
283101099Srwatson			continue;
284101099Srwatson
285108376Srwatson		/*
286108376Srwatson		 * Since we don't separately handle append, map append to
287108376Srwatson		 * write.
288108376Srwatson		 */
289108376Srwatson		if (acc_mode & VAPPEND) {
290108376Srwatson			acc_mode &= ~VAPPEND;
291108376Srwatson			acc_mode |= VWRITE;
292108376Srwatson		}
293108376Srwatson
294101099Srwatson		error = mac_bsdextended_rulecheck(rules[i], cred, object_uid,
295101099Srwatson		    object_gid, acc_mode);
296101099Srwatson		if (error)
297101099Srwatson			return (error);
298101099Srwatson	}
299101099Srwatson
300101099Srwatson	return (0);
301101099Srwatson}
302101099Srwatson
303101099Srwatsonstatic int
304112575Srwatsonmac_bsdextended_check_system_swapon(struct ucred *cred, struct vnode *vp,
305112575Srwatson    struct label *label)
306112575Srwatson{
307112575Srwatson	struct vattr vap;
308112575Srwatson	int error;
309112575Srwatson
310112575Srwatson	if (!mac_bsdextended_enabled)
311112575Srwatson		return (0);
312112575Srwatson
313112575Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
314112575Srwatson	if (error)
315112575Srwatson		return (error);
316112575Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
317112575Srwatson}
318112575Srwatson
319112575Srwatsonstatic int
320101099Srwatsonmac_bsdextended_check_vnode_access(struct ucred *cred, struct vnode *vp,
321106212Srwatson    struct label *label, int acc_mode)
322101099Srwatson{
323101099Srwatson	struct vattr vap;
324101099Srwatson	int error;
325101099Srwatson
326101099Srwatson	if (!mac_bsdextended_enabled)
327101099Srwatson		return (0);
328101099Srwatson
329101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
330101099Srwatson	if (error)
331101099Srwatson		return (error);
332106212Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
333101099Srwatson}
334101099Srwatson
335101099Srwatsonstatic int
336101099Srwatsonmac_bsdextended_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
337101099Srwatson    struct label *dlabel)
338101099Srwatson{
339101099Srwatson	struct vattr vap;
340101099Srwatson	int error;
341101099Srwatson
342101099Srwatson	if (!mac_bsdextended_enabled)
343101099Srwatson		return (0);
344101099Srwatson
345101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
346101099Srwatson	if (error)
347101099Srwatson		return (error);
348101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VEXEC));
349101099Srwatson}
350101099Srwatson
351101099Srwatsonstatic int
352101099Srwatsonmac_bsdextended_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
353101099Srwatson    struct label *dlabel)
354101099Srwatson{
355101099Srwatson	struct vattr vap;
356101099Srwatson	int error;
357101099Srwatson
358101099Srwatson	if (!mac_bsdextended_enabled)
359101099Srwatson		return (0);
360101099Srwatson
361101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
362101099Srwatson	if (error)
363101099Srwatson		return (error);
364101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VEXEC));
365101099Srwatson}
366101099Srwatson
367101099Srwatsonstatic int
368101099Srwatsonmac_bsdextended_check_create_vnode(struct ucred *cred, struct vnode *dvp,
369101099Srwatson    struct label *dlabel, struct componentname *cnp, struct vattr *vap)
370101099Srwatson{
371101099Srwatson	struct vattr dvap;
372101099Srwatson	int error;
373101099Srwatson
374101099Srwatson	if (!mac_bsdextended_enabled)
375101099Srwatson		return (0);
376101099Srwatson
377101099Srwatson	error = VOP_GETATTR(dvp, &dvap, cred, curthread);
378101099Srwatson	if (error)
379101099Srwatson		return (error);
380101099Srwatson	return (mac_bsdextended_check(cred, dvap.va_uid, dvap.va_gid, VWRITE));
381101099Srwatson}
382101099Srwatson
383101099Srwatsonstatic int
384101099Srwatsonmac_bsdextended_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
385101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
386101099Srwatson    struct componentname *cnp)
387101099Srwatson{
388101099Srwatson	struct vattr vap;
389101099Srwatson	int error;
390101099Srwatson
391101099Srwatson	if (!mac_bsdextended_enabled)
392101099Srwatson		return (0);
393101099Srwatson
394101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
395101099Srwatson	if (error)
396101099Srwatson		return (error);
397101099Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
398101099Srwatson	if (error)
399101099Srwatson		return (error);
400101099Srwatson
401101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
402101099Srwatson	if (error)
403101099Srwatson		return (error);
404101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
405101099Srwatson}
406101099Srwatson
407101099Srwatsonstatic int
408101099Srwatsonmac_bsdextended_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
409101099Srwatson    struct label *label, acl_type_t type)
410101099Srwatson{
411101099Srwatson	struct vattr vap;
412101099Srwatson	int error;
413101099Srwatson
414101099Srwatson	if (!mac_bsdextended_enabled)
415101099Srwatson		return (0);
416101099Srwatson
417101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
418117247Srwatson	if (error)
419101099Srwatson		return (error);
420101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
421101099Srwatson}
422101099Srwatson
423101099Srwatsonstatic int
424119202Srwatsonmac_bsdextended_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
425119202Srwatson    struct label *label, int attrnamespace, const char *name)
426119202Srwatson{
427119202Srwatson	struct vattr vap;
428119202Srwatson	int error;
429119202Srwatson
430119202Srwatson	if (!mac_bsdextended_enabled)
431119202Srwatson		return (0);
432119202Srwatson
433119202Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
434119202Srwatson	if (error)
435119202Srwatson		return (error);
436119202Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
437119202Srwatson}
438119202Srwatson
439119202Srwatsonstatic int
440101099Srwatsonmac_bsdextended_check_vnode_exec(struct ucred *cred, struct vnode *vp,
441106648Srwatson    struct label *label, struct image_params *imgp,
442106648Srwatson    struct label *execlabel)
443101099Srwatson{
444101099Srwatson	struct vattr vap;
445101099Srwatson	int error;
446101099Srwatson
447101099Srwatson	if (!mac_bsdextended_enabled)
448101099Srwatson		return (0);
449101099Srwatson
450101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
451101099Srwatson	if (error)
452101099Srwatson		return (error);
453101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
454101099Srwatson	    VREAD|VEXEC));
455101099Srwatson}
456101099Srwatson
457101099Srwatsonstatic int
458101099Srwatsonmac_bsdextended_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
459101099Srwatson    struct label *label, acl_type_t type)
460101099Srwatson{
461101099Srwatson	struct vattr vap;
462101099Srwatson	int error;
463101099Srwatson
464101099Srwatson	if (!mac_bsdextended_enabled)
465101099Srwatson		return (0);
466101099Srwatson
467101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
468101099Srwatson	if (error)
469101099Srwatson		return (error);
470101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VSTAT));
471101099Srwatson}
472101099Srwatson
473101099Srwatsonstatic int
474101099Srwatsonmac_bsdextended_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
475101099Srwatson    struct label *label, int attrnamespace, const char *name, struct uio *uio)
476101099Srwatson{
477101099Srwatson	struct vattr vap;
478101099Srwatson	int error;
479101099Srwatson
480101099Srwatson	if (!mac_bsdextended_enabled)
481101099Srwatson		return (0);
482101099Srwatson
483101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
484101099Srwatson	if (error)
485101099Srwatson		return (error);
486101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
487101099Srwatson}
488101099Srwatson
489101099Srwatsonstatic int
490104530Srwatsonmac_bsdextended_check_vnode_link(struct ucred *cred, struct vnode *dvp,
491104530Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
492104530Srwatson    struct componentname *cnp)
493104530Srwatson{
494104530Srwatson	struct vattr vap;
495104530Srwatson	int error;
496104530Srwatson
497104530Srwatson	if (!mac_bsdextended_enabled)
498104530Srwatson		return (0);
499104530Srwatson
500104530Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
501104530Srwatson	if (error)
502104530Srwatson		return (error);
503104530Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
504106214Srwatson	if (error)
505106214Srwatson		return (error);
506104530Srwatson
507104530Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
508104530Srwatson	if (error)
509104530Srwatson		return (error);
510104530Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
511104530Srwatson	if (error)
512104530Srwatson		return (error);
513104530Srwatson	return (0);
514104530Srwatson}
515104530Srwatson
516104530Srwatsonstatic int
517119202Srwatsonmac_bsdextended_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
518119202Srwatson    struct label *label, int attrnamespace)
519119202Srwatson{
520119202Srwatson	struct vattr vap;
521119202Srwatson	int error;
522119202Srwatson
523119202Srwatson	if (!mac_bsdextended_enabled)
524119202Srwatson		return (0);
525119202Srwatson
526119202Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
527119202Srwatson	if (error)
528119202Srwatson		return (error);
529119202Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
530119202Srwatson}
531119202Srwatson
532119202Srwatsonstatic int
533101099Srwatsonmac_bsdextended_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
534101099Srwatson    struct label *dlabel, struct componentname *cnp)
535101099Srwatson{
536101099Srwatson	struct vattr vap;
537101099Srwatson	int error;
538117247Srwatson
539101099Srwatson	if (!mac_bsdextended_enabled)
540101099Srwatson		return (0);
541117247Srwatson
542101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
543101099Srwatson	if (error)
544101099Srwatson		return (error);
545101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VEXEC));
546101099Srwatson}
547101099Srwatson
548101099Srwatsonstatic int
549101099Srwatsonmac_bsdextended_check_vnode_open(struct ucred *cred, struct vnode *vp,
550106212Srwatson    struct label *filelabel, int acc_mode)
551101099Srwatson{
552101099Srwatson	struct vattr vap;
553101099Srwatson	int error;
554101099Srwatson
555101099Srwatson	if (!mac_bsdextended_enabled)
556101099Srwatson		return (0);
557101099Srwatson
558101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
559101099Srwatson	if (error)
560101099Srwatson		return (error);
561101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
562101099Srwatson}
563101099Srwatson
564101099Srwatsonstatic int
565101099Srwatsonmac_bsdextended_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
566101099Srwatson    struct label *dlabel)
567101099Srwatson{
568101099Srwatson	struct vattr vap;
569101099Srwatson	int error;
570101099Srwatson
571101099Srwatson	if (!mac_bsdextended_enabled)
572101099Srwatson		return (0);
573101099Srwatson
574101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
575101099Srwatson	if (error)
576101099Srwatson		return (error);
577101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
578101099Srwatson}
579101099Srwatson
580101099Srwatsonstatic int
581101099Srwatsonmac_bsdextended_check_vnode_readdlink(struct ucred *cred, struct vnode *vp,
582101099Srwatson    struct label *label)
583101099Srwatson{
584101099Srwatson	struct vattr vap;
585101099Srwatson	int error;
586101099Srwatson
587101099Srwatson	if (!mac_bsdextended_enabled)
588101099Srwatson		return (0);
589101099Srwatson
590101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
591101099Srwatson	if (error)
592101099Srwatson		return (error);
593101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
594101099Srwatson}
595101099Srwatson
596101099Srwatsonstatic int
597101099Srwatsonmac_bsdextended_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
598101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
599101099Srwatson    struct componentname *cnp)
600101099Srwatson{
601101099Srwatson	struct vattr vap;
602101099Srwatson	int error;
603101099Srwatson
604101099Srwatson	if (!mac_bsdextended_enabled)
605101099Srwatson		return (0);
606101099Srwatson
607101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
608101099Srwatson	if (error)
609101099Srwatson		return (error);
610101099Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
611101099Srwatson	if (error)
612101099Srwatson		return (error);
613101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
614101099Srwatson	if (error)
615101099Srwatson		return (error);
616101099Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
617101099Srwatson
618101099Srwatson	return (error);
619101099Srwatson}
620101099Srwatson
621101099Srwatsonstatic int
622101099Srwatsonmac_bsdextended_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
623101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
624101099Srwatson    struct componentname *cnp)
625101099Srwatson{
626101099Srwatson	struct vattr vap;
627101099Srwatson	int error;
628101099Srwatson
629101099Srwatson	if (!mac_bsdextended_enabled)
630101099Srwatson		return (0);
631101099Srwatson
632101099Srwatson	error = VOP_GETATTR(dvp, &vap, cred, curthread);
633101099Srwatson	if (error)
634101099Srwatson		return (error);
635101099Srwatson	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
636101099Srwatson	if (error)
637101099Srwatson		return (error);
638101099Srwatson
639101099Srwatson	if (vp != NULL) {
640101099Srwatson		error = VOP_GETATTR(vp, &vap, cred, curthread);
641101099Srwatson		if (error)
642101099Srwatson			return (error);
643101099Srwatson		error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
644101099Srwatson		    VWRITE);
645101099Srwatson	}
646101099Srwatson
647101099Srwatson	return (error);
648101099Srwatson}
649101099Srwatson
650101099Srwatsonstatic int
651101099Srwatsonmac_bsdextended_check_vnode_revoke(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);
663101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
664101099Srwatson}
665101099Srwatson
666101099Srwatsonstatic int
667101099Srwatsonmac_bsdextended_check_setacl_vnode(struct ucred *cred, struct vnode *vp,
668101099Srwatson    struct label *label, acl_type_t type, struct acl *acl)
669101099Srwatson{
670101099Srwatson	struct vattr vap;
671101099Srwatson	int error;
672101099Srwatson
673101099Srwatson	if (!mac_bsdextended_enabled)
674101099Srwatson		return (0);
675101099Srwatson
676101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
677101099Srwatson	if (error)
678101099Srwatson		return (error);
679101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
680101099Srwatson}
681101099Srwatson
682101099Srwatsonstatic int
683101099Srwatsonmac_bsdextended_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
684101099Srwatson    struct label *label, int attrnamespace, const char *name, struct uio *uio)
685101099Srwatson{
686101099Srwatson	struct vattr vap;
687101099Srwatson	int error;
688101099Srwatson
689101099Srwatson	if (!mac_bsdextended_enabled)
690101099Srwatson		return (0);
691101099Srwatson
692101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
693101099Srwatson	if (error)
694101099Srwatson		return (error);
695101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
696101099Srwatson}
697101099Srwatson
698101099Srwatsonstatic int
699101099Srwatsonmac_bsdextended_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
700101099Srwatson    struct label *label, u_long flags)
701101099Srwatson{
702101099Srwatson	struct vattr vap;
703101099Srwatson	int error;
704101099Srwatson
705101099Srwatson	if (!mac_bsdextended_enabled)
706101099Srwatson		return (0);
707101099Srwatson
708101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
709101099Srwatson	if (error)
710101099Srwatson		return (error);
711101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
712101099Srwatson}
713101099Srwatson
714101099Srwatsonstatic int
715101099Srwatsonmac_bsdextended_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
716101099Srwatson    struct label *label, mode_t mode)
717101099Srwatson{
718101099Srwatson	struct vattr vap;
719101099Srwatson	int error;
720101099Srwatson
721101099Srwatson	if (!mac_bsdextended_enabled)
722101099Srwatson		return (0);
723101099Srwatson
724101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
725101099Srwatson	if (error)
726101099Srwatson		return (error);
727101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
728101099Srwatson}
729101099Srwatson
730101099Srwatsonstatic int
731101099Srwatsonmac_bsdextended_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
732101099Srwatson    struct label *label, uid_t uid, gid_t gid)
733101099Srwatson{
734101099Srwatson	struct vattr vap;
735101099Srwatson	int error;
736101099Srwatson
737101099Srwatson	if (!mac_bsdextended_enabled)
738101099Srwatson		return (0);
739101099Srwatson
740101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
741101099Srwatson	if (error)
742101099Srwatson		return (error);
743101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
744101099Srwatson}
745101099Srwatson
746101099Srwatsonstatic int
747101099Srwatsonmac_bsdextended_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
748101099Srwatson    struct label *label, struct timespec atime, struct timespec utime)
749101099Srwatson{
750101099Srwatson	struct vattr vap;
751101099Srwatson	int error;
752101099Srwatson
753101099Srwatson	if (!mac_bsdextended_enabled)
754101099Srwatson		return (0);
755101099Srwatson
756101099Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
757101099Srwatson	if (error)
758101099Srwatson		return (error);
759101099Srwatson	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
760101099Srwatson}
761101099Srwatson
762101099Srwatsonstatic int
763102129Srwatsonmac_bsdextended_check_vnode_stat(struct ucred *active_cred,
764102129Srwatson    struct ucred *file_cred, struct vnode *vp, struct label *label)
765101099Srwatson{
766101099Srwatson	struct vattr vap;
767101099Srwatson	int error;
768101099Srwatson
769101099Srwatson	if (!mac_bsdextended_enabled)
770101099Srwatson		return (0);
771101099Srwatson
772102129Srwatson	error = VOP_GETATTR(vp, &vap, active_cred, curthread);
773101099Srwatson	if (error)
774101099Srwatson		return (error);
775102129Srwatson	return (mac_bsdextended_check(active_cred, vap.va_uid, vap.va_gid,
776102129Srwatson	    VSTAT));
777101099Srwatson}
778101099Srwatson
779106217Srwatsonstatic struct mac_policy_ops mac_bsdextended_ops =
780101099Srwatson{
781106217Srwatson	.mpo_destroy = mac_bsdextended_destroy,
782106217Srwatson	.mpo_init = mac_bsdextended_init,
783112575Srwatson	.mpo_check_system_swapon = mac_bsdextended_check_system_swapon,
784106217Srwatson	.mpo_check_vnode_access = mac_bsdextended_check_vnode_access,
785106217Srwatson	.mpo_check_vnode_chdir = mac_bsdextended_check_vnode_chdir,
786106217Srwatson	.mpo_check_vnode_chroot = mac_bsdextended_check_vnode_chroot,
787106217Srwatson	.mpo_check_vnode_create = mac_bsdextended_check_create_vnode,
788106217Srwatson	.mpo_check_vnode_delete = mac_bsdextended_check_vnode_delete,
789106217Srwatson	.mpo_check_vnode_deleteacl = mac_bsdextended_check_vnode_deleteacl,
790119202Srwatson	.mpo_check_vnode_deleteextattr = mac_bsdextended_check_vnode_deleteextattr,
791106217Srwatson	.mpo_check_vnode_exec = mac_bsdextended_check_vnode_exec,
792106217Srwatson	.mpo_check_vnode_getacl = mac_bsdextended_check_vnode_getacl,
793106217Srwatson	.mpo_check_vnode_getextattr = mac_bsdextended_check_vnode_getextattr,
794106217Srwatson	.mpo_check_vnode_link = mac_bsdextended_check_vnode_link,
795119202Srwatson	.mpo_check_vnode_listextattr = mac_bsdextended_check_vnode_listextattr,
796106217Srwatson	.mpo_check_vnode_lookup = mac_bsdextended_check_vnode_lookup,
797106217Srwatson	.mpo_check_vnode_open = mac_bsdextended_check_vnode_open,
798106217Srwatson	.mpo_check_vnode_readdir = mac_bsdextended_check_vnode_readdir,
799106217Srwatson	.mpo_check_vnode_readlink = mac_bsdextended_check_vnode_readdlink,
800106217Srwatson	.mpo_check_vnode_rename_from = mac_bsdextended_check_vnode_rename_from,
801106217Srwatson	.mpo_check_vnode_rename_to = mac_bsdextended_check_vnode_rename_to,
802106217Srwatson	.mpo_check_vnode_revoke = mac_bsdextended_check_vnode_revoke,
803106217Srwatson	.mpo_check_vnode_setacl = mac_bsdextended_check_setacl_vnode,
804106217Srwatson	.mpo_check_vnode_setextattr = mac_bsdextended_check_vnode_setextattr,
805106217Srwatson	.mpo_check_vnode_setflags = mac_bsdextended_check_vnode_setflags,
806106217Srwatson	.mpo_check_vnode_setmode = mac_bsdextended_check_vnode_setmode,
807106217Srwatson	.mpo_check_vnode_setowner = mac_bsdextended_check_vnode_setowner,
808106217Srwatson	.mpo_check_vnode_setutimes = mac_bsdextended_check_vnode_setutimes,
809106217Srwatson	.mpo_check_vnode_stat = mac_bsdextended_check_vnode_stat,
810101099Srwatson};
811101099Srwatson
812112717SrwatsonMAC_POLICY_SET(&mac_bsdextended_ops, mac_bsdextended,
813101099Srwatson    "TrustedBSD MAC/BSD Extended", MPC_LOADTIME_FLAG_UNLOADOK, NULL);
814