ugidfw_vnode.c revision 171253
1101099Srwatson/*-
2166905Srwatson * Copyright (c) 1999-2002, 2007 Robert N. M. Watson
3145412Strhodes * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
4171253Srwatson * Copyright (c) 2005 Tom Rhodes
5101099Srwatson * All rights reserved.
6101099Srwatson *
7101099Srwatson * This software was developed by Robert Watson for the TrustedBSD Project.
8145412Strhodes * It was later enhanced by Tom Rhodes for the TrustedBSD Project.
9101099Srwatson *
10106393Srwatson * This software was developed for the FreeBSD Project in part by Network
11106393Srwatson * Associates Laboratories, the Security Research Division of Network
12106393Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13106393Srwatson * as part of the DARPA CHATS research program.
14101099Srwatson *
15101099Srwatson * Redistribution and use in source and binary forms, with or without
16101099Srwatson * modification, are permitted provided that the following conditions
17101099Srwatson * are met:
18101099Srwatson * 1. Redistributions of source code must retain the above copyright
19101099Srwatson *    notice, this list of conditions and the following disclaimer.
20101099Srwatson * 2. Redistributions in binary form must reproduce the above copyright
21101099Srwatson *    notice, this list of conditions and the following disclaimer in the
22101099Srwatson *    documentation and/or other materials provided with the distribution.
23101099Srwatson *
24101099Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25101099Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26101099Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27101099Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28101099Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29101099Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30101099Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31101099Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32101099Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33101099Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34101099Srwatson * SUCH DAMAGE.
35101099Srwatson *
36101099Srwatson * $FreeBSD: head/sys/security/mac_bsdextended/mac_bsdextended.c 171253 2007-07-05 13:16:04Z rwatson $
37101099Srwatson */
38136774Srwatson
39101099Srwatson/*
40101099Srwatson * Developed by the TrustedBSD Project.
41171253Srwatson *
42171253Srwatson * "BSD Extended" MAC policy, allowing the administrator to impose mandatory
43171253Srwatson * firewall-like rules regarding users and file system objects.
44101099Srwatson */
45101099Srwatson
46101099Srwatson#include <sys/param.h>
47101099Srwatson#include <sys/acl.h>
48101099Srwatson#include <sys/kernel.h>
49157986Sdwmalone#include <sys/jail.h>
50145412Strhodes#include <sys/lock.h>
51101099Srwatson#include <sys/malloc.h>
52166905Srwatson#include <sys/module.h>
53101099Srwatson#include <sys/mount.h>
54145412Strhodes#include <sys/mutex.h>
55170689Srwatson#include <sys/priv.h>
56101099Srwatson#include <sys/systm.h>
57101099Srwatson#include <sys/vnode.h>
58101099Srwatson#include <sys/sysctl.h>
59134132Strhodes#include <sys/syslog.h>
60101099Srwatson
61165469Srwatson#include <security/mac/mac_policy.h>
62101099Srwatson#include <security/mac_bsdextended/mac_bsdextended.h>
63101099Srwatson
64145412Strhodesstatic struct mtx mac_bsdextended_mtx;
65145412Strhodes
66101099SrwatsonSYSCTL_DECL(_security_mac);
67101099Srwatson
68101099SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0,
69101099Srwatson    "TrustedBSD extended BSD MAC policy controls");
70101099Srwatson
71101099Srwatsonstatic int	mac_bsdextended_enabled = 1;
72101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW,
73101099Srwatson    &mac_bsdextended_enabled, 0, "Enforce extended BSD policy");
74101099SrwatsonTUNABLE_INT("security.mac.bsdextended.enabled", &mac_bsdextended_enabled);
75101099Srwatson
76101099SrwatsonMALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule");
77101099Srwatson
78101099Srwatson#define	MAC_BSDEXTENDED_MAXRULES	250
79101099Srwatsonstatic struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES];
80101099Srwatsonstatic int rule_count = 0;
81101099Srwatsonstatic int rule_slots = 0;
82157986Sdwmalonestatic int rule_version = MB_VERSION;
83101099Srwatson
84101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD,
85101099Srwatson    &rule_count, 0, "Number of defined rules\n");
86101099SrwatsonSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD,
87101099Srwatson    &rule_slots, 0, "Number of used rule slots\n");
88157986SdwmaloneSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_version, CTLFLAG_RD,
89157986Sdwmalone    &rule_version, 0, "Version number for API\n");
90101099Srwatson
91134132Strhodes/*
92171253Srwatson * This is just used for logging purposes, eventually we would like to log
93171253Srwatson * much more then failed requests.
94134132Strhodes */
95134132Strhodesstatic int mac_bsdextended_logging;
96134132StrhodesSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW,
97134132Strhodes    &mac_bsdextended_logging, 0, "Log failed authorization requests");
98134132Strhodes
99134132Strhodes/*
100171253Srwatson * This tunable is here for compatibility.  It will allow the user to switch
101171253Srwatson * between the new mode (first rule matches) and the old functionality (all
102171253Srwatson * rules match).
103134131Strhodes */
104101099Srwatsonstatic int
105134131Strhodesmac_bsdextended_firstmatch_enabled;
106134131StrhodesSYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled,
107171253Srwatson    CTLFLAG_RW, &mac_bsdextended_firstmatch_enabled, 1,
108171253Srwatson    "Disable/enable match first rule functionality");
109134131Strhodes
110134131Strhodesstatic int
111101099Srwatsonmac_bsdextended_rule_valid(struct mac_bsdextended_rule *rule)
112101099Srwatson{
113101099Srwatson
114157986Sdwmalone	if ((rule->mbr_subject.mbs_flags | MBS_ALL_FLAGS) != MBS_ALL_FLAGS)
115101099Srwatson		return (EINVAL);
116157986Sdwmalone	if ((rule->mbr_subject.mbs_neg | MBS_ALL_FLAGS) != MBS_ALL_FLAGS)
117101099Srwatson		return (EINVAL);
118157986Sdwmalone	if ((rule->mbr_object.mbo_flags | MBO_ALL_FLAGS) != MBO_ALL_FLAGS)
119157986Sdwmalone		return (EINVAL);
120157986Sdwmalone	if ((rule->mbr_object.mbo_neg | MBO_ALL_FLAGS) != MBO_ALL_FLAGS)
121157986Sdwmalone		return (EINVAL);
122157986Sdwmalone	if ((rule->mbr_object.mbo_neg | MBO_TYPE_DEFINED) &&
123157986Sdwmalone	    (rule->mbr_object.mbo_type | MBO_ALL_TYPE) != MBO_ALL_TYPE)
124157986Sdwmalone		return (EINVAL);
125136739Srwatson	if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM)
126101099Srwatson		return (EINVAL);
127101099Srwatson	return (0);
128101099Srwatson}
129101099Srwatson
130101099Srwatsonstatic int
131101099Srwatsonsysctl_rule(SYSCTL_HANDLER_ARGS)
132101099Srwatson{
133101099Srwatson	struct mac_bsdextended_rule temprule, *ruleptr;
134101099Srwatson	u_int namelen;
135101099Srwatson	int error, index, *name;
136101099Srwatson
137145412Strhodes	error = 0;
138101099Srwatson	name = (int *)arg1;
139101099Srwatson	namelen = arg2;
140101099Srwatson	if (namelen != 1)
141101099Srwatson		return (EINVAL);
142101099Srwatson	index = name[0];
143154386Scsjp        if (index >= MAC_BSDEXTENDED_MAXRULES)
144101099Srwatson		return (ENOENT);
145101099Srwatson
146145412Strhodes	ruleptr = NULL;
147145412Strhodes	if (req->newptr && req->newlen != 0) {
148145412Strhodes		error = SYSCTL_IN(req, &temprule, sizeof(temprule));
149101099Srwatson		if (error)
150101099Srwatson			return (error);
151145412Strhodes		MALLOC(ruleptr, struct mac_bsdextended_rule *,
152145412Strhodes		    sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK | M_ZERO);
153101099Srwatson	}
154101099Srwatson
155145412Strhodes	mtx_lock(&mac_bsdextended_mtx);
156145412Strhodes	if (req->oldptr) {
157145412Strhodes		if (index < 0 || index > rule_slots + 1) {
158145412Strhodes			error = ENOENT;
159145412Strhodes			goto out;
160101099Srwatson		}
161145412Strhodes		if (rules[index] == NULL) {
162145412Strhodes			error = ENOENT;
163145412Strhodes			goto out;
164145412Strhodes		}
165145412Strhodes		temprule = *rules[index];
166145412Strhodes	}
167145412Strhodes	if (req->newptr && req->newlen == 0) {
168145412Strhodes		KASSERT(ruleptr == NULL, ("sysctl_rule: ruleptr != NULL"));
169145412Strhodes		ruleptr = rules[index];
170145412Strhodes		if (ruleptr == NULL) {
171145412Strhodes			error = ENOENT;
172145412Strhodes			goto out;
173145412Strhodes		}
174145412Strhodes		rule_count--;
175145412Strhodes		rules[index] = NULL;
176145412Strhodes	} else if (req->newptr) {
177101099Srwatson		error = mac_bsdextended_rule_valid(&temprule);
178101099Srwatson		if (error)
179145412Strhodes			goto out;
180101099Srwatson		if (rules[index] == NULL) {
181101099Srwatson			*ruleptr = temprule;
182101099Srwatson			rules[index] = ruleptr;
183145412Strhodes			ruleptr = NULL;
184145412Strhodes			if (index + 1 > rule_slots)
185145412Strhodes				rule_slots = index + 1;
186101099Srwatson			rule_count++;
187171253Srwatson		} else
188101099Srwatson			*rules[index] = temprule;
189101099Srwatson	}
190145412Strhodesout:
191145412Strhodes	mtx_unlock(&mac_bsdextended_mtx);
192145412Strhodes	if (ruleptr != NULL)
193145412Strhodes		FREE(ruleptr, M_MACBSDEXTENDED);
194148482Strhodes	if (req->oldptr && error == 0)
195145412Strhodes		error = SYSCTL_OUT(req, &temprule, sizeof(temprule));
196148482Strhodes	return (error);
197101099Srwatson}
198101099Srwatson
199171253SrwatsonSYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules, CTLFLAG_RW,
200171253Srwatson    sysctl_rule, "BSD extended MAC rules");
201101099Srwatson
202101099Srwatsonstatic void
203101099Srwatsonmac_bsdextended_init(struct mac_policy_conf *mpc)
204101099Srwatson{
205101099Srwatson
206145412Strhodes	mtx_init(&mac_bsdextended_mtx, "mac_bsdextended lock", NULL, MTX_DEF);
207101099Srwatson}
208101099Srwatson
209101099Srwatsonstatic void
210101099Srwatsonmac_bsdextended_destroy(struct mac_policy_conf *mpc)
211101099Srwatson{
212101099Srwatson
213145412Strhodes	mtx_destroy(&mac_bsdextended_mtx);
214101099Srwatson}
215101099Srwatson
216101099Srwatsonstatic int
217101099Srwatsonmac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
218157986Sdwmalone    struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode)
219101099Srwatson{
220101099Srwatson	int match;
221157986Sdwmalone	int i;
222101099Srwatson
223101099Srwatson	/*
224101099Srwatson	 * Is there a subject match?
225101099Srwatson	 */
226145412Strhodes	mtx_assert(&mac_bsdextended_mtx, MA_OWNED);
227157986Sdwmalone	if (rule->mbr_subject.mbs_flags & MBS_UID_DEFINED) {
228157986Sdwmalone		match =  ((cred->cr_uid <= rule->mbr_subject.mbs_uid_max &&
229157986Sdwmalone		    cred->cr_uid >= rule->mbr_subject.mbs_uid_min) ||
230157986Sdwmalone		    (cred->cr_ruid <= rule->mbr_subject.mbs_uid_max &&
231157986Sdwmalone		    cred->cr_ruid >= rule->mbr_subject.mbs_uid_min) ||
232157986Sdwmalone		    (cred->cr_svuid <= rule->mbr_subject.mbs_uid_max &&
233157986Sdwmalone		    cred->cr_svuid >= rule->mbr_subject.mbs_uid_min));
234157986Sdwmalone		if (rule->mbr_subject.mbs_neg & MBS_UID_DEFINED)
235101099Srwatson			match = !match;
236101099Srwatson		if (!match)
237101099Srwatson			return (0);
238101099Srwatson	}
239101099Srwatson
240157986Sdwmalone	if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) {
241157986Sdwmalone		match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max &&
242157986Sdwmalone		    cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) ||
243157986Sdwmalone		    (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max &&
244157986Sdwmalone		    cred->cr_svgid >= rule->mbr_subject.mbs_gid_min));
245157986Sdwmalone		if (!match) {
246171253Srwatson			for (i = 0; i < cred->cr_ngroups; i++) {
247157986Sdwmalone				if (cred->cr_groups[i]
248157986Sdwmalone				    <= rule->mbr_subject.mbs_gid_max &&
249157986Sdwmalone				    cred->cr_groups[i]
250157986Sdwmalone				    >= rule->mbr_subject.mbs_gid_min) {
251157986Sdwmalone					match = 1;
252157986Sdwmalone					break;
253157986Sdwmalone				}
254171253Srwatson			}
255157986Sdwmalone		}
256157986Sdwmalone		if (rule->mbr_subject.mbs_neg & MBS_GID_DEFINED)
257101099Srwatson			match = !match;
258101099Srwatson		if (!match)
259101099Srwatson			return (0);
260101099Srwatson	}
261101099Srwatson
262157986Sdwmalone	if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) {
263157986Sdwmalone		match = (cred->cr_prison != NULL &&
264157986Sdwmalone		    cred->cr_prison->pr_id == rule->mbr_subject.mbs_prison);
265157986Sdwmalone		if (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED)
266157986Sdwmalone			match = !match;
267157986Sdwmalone		if (!match)
268157986Sdwmalone			return (0);
269157986Sdwmalone	}
270157986Sdwmalone
271101099Srwatson	/*
272101099Srwatson	 * Is there an object match?
273101099Srwatson	 */
274157986Sdwmalone	if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) {
275157986Sdwmalone		match = (vap->va_uid <= rule->mbr_object.mbo_uid_max &&
276157986Sdwmalone		    vap->va_uid >= rule->mbr_object.mbo_uid_min);
277157986Sdwmalone		if (rule->mbr_object.mbo_neg & MBO_UID_DEFINED)
278101099Srwatson			match = !match;
279101099Srwatson		if (!match)
280101099Srwatson			return (0);
281101099Srwatson	}
282101099Srwatson
283157986Sdwmalone	if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) {
284157986Sdwmalone		match = (vap->va_gid <= rule->mbr_object.mbo_gid_max &&
285157986Sdwmalone		    vap->va_gid >= rule->mbr_object.mbo_gid_min);
286157986Sdwmalone		if (rule->mbr_object.mbo_neg & MBO_GID_DEFINED)
287101099Srwatson			match = !match;
288101099Srwatson		if (!match)
289101099Srwatson			return (0);
290101099Srwatson	}
291101099Srwatson
292157986Sdwmalone	if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) {
293157986Sdwmalone		match = (bcmp(&(vp->v_mount->mnt_stat.f_fsid),
294157986Sdwmalone		    &(rule->mbr_object.mbo_fsid),
295157986Sdwmalone		    sizeof(rule->mbr_object.mbo_fsid)) == 0);
296157986Sdwmalone		if (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED)
297157986Sdwmalone			match = !match;
298157986Sdwmalone		if (!match)
299171253Srwatson			return (0);
300157986Sdwmalone	}
301157986Sdwmalone
302157986Sdwmalone	if (rule->mbr_object.mbo_flags & MBO_SUID) {
303157986Sdwmalone		match = (vap->va_mode & VSUID);
304157986Sdwmalone		if (rule->mbr_object.mbo_neg & MBO_SUID)
305157986Sdwmalone			match = !match;
306157986Sdwmalone		if (!match)
307171253Srwatson			return (0);
308157986Sdwmalone	}
309157986Sdwmalone
310157986Sdwmalone	if (rule->mbr_object.mbo_flags & MBO_SGID) {
311157986Sdwmalone		match = (vap->va_mode & VSGID);
312157986Sdwmalone		if (rule->mbr_object.mbo_neg & MBO_SGID)
313157986Sdwmalone			match = !match;
314157986Sdwmalone		if (!match)
315171253Srwatson			return (0);
316157986Sdwmalone	}
317157986Sdwmalone
318157986Sdwmalone	if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) {
319157986Sdwmalone		match = (vap->va_uid == cred->cr_uid ||
320157986Sdwmalone		    vap->va_uid == cred->cr_ruid ||
321157986Sdwmalone		    vap->va_uid == cred->cr_svuid);
322157986Sdwmalone		if (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT)
323157986Sdwmalone			match = !match;
324157986Sdwmalone		if (!match)
325171253Srwatson			return (0);
326157986Sdwmalone	}
327157986Sdwmalone
328157986Sdwmalone	if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) {
329157986Sdwmalone		match = (groupmember(vap->va_gid, cred) ||
330157986Sdwmalone		    vap->va_gid == cred->cr_rgid ||
331157986Sdwmalone		    vap->va_gid == cred->cr_svgid);
332157986Sdwmalone		if (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT)
333157986Sdwmalone			match = !match;
334157986Sdwmalone		if (!match)
335171253Srwatson			return (0);
336157986Sdwmalone	}
337157986Sdwmalone
338157986Sdwmalone	if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) {
339157986Sdwmalone		switch (vap->va_type) {
340157986Sdwmalone		case VREG:
341157986Sdwmalone			match = (rule->mbr_object.mbo_type & MBO_TYPE_REG);
342157986Sdwmalone			break;
343157986Sdwmalone		case VDIR:
344157986Sdwmalone			match = (rule->mbr_object.mbo_type & MBO_TYPE_DIR);
345157986Sdwmalone			break;
346157986Sdwmalone		case VBLK:
347157986Sdwmalone			match = (rule->mbr_object.mbo_type & MBO_TYPE_BLK);
348157986Sdwmalone			break;
349157986Sdwmalone		case VCHR:
350157986Sdwmalone			match = (rule->mbr_object.mbo_type & MBO_TYPE_CHR);
351157986Sdwmalone			break;
352157986Sdwmalone		case VLNK:
353157986Sdwmalone			match = (rule->mbr_object.mbo_type & MBO_TYPE_LNK);
354157986Sdwmalone			break;
355157986Sdwmalone		case VSOCK:
356157986Sdwmalone			match = (rule->mbr_object.mbo_type & MBO_TYPE_SOCK);
357157986Sdwmalone			break;
358157986Sdwmalone		case VFIFO:
359157986Sdwmalone			match = (rule->mbr_object.mbo_type & MBO_TYPE_FIFO);
360157986Sdwmalone			break;
361157986Sdwmalone		default:
362157986Sdwmalone			match = 0;
363157986Sdwmalone		}
364157986Sdwmalone		if (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED)
365157986Sdwmalone			match = !match;
366157986Sdwmalone		if (!match)
367171253Srwatson			return (0);
368157986Sdwmalone	}
369157986Sdwmalone
370101099Srwatson	/*
371101099Srwatson	 * Is the access permitted?
372101099Srwatson	 */
373101099Srwatson	if ((rule->mbr_mode & acc_mode) != acc_mode) {
374134132Strhodes		if (mac_bsdextended_logging)
375134132Strhodes			log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d"
376134132Strhodes			    " on %d:%d failed. \n", cred->cr_ruid,
377171253Srwatson			    cred->cr_rgid, acc_mode, vap->va_uid,
378171253Srwatson			    vap->va_gid);
379171253Srwatson		return (EACCES);
380101099Srwatson	}
381145412Strhodes
382134131Strhodes	/*
383145412Strhodes	 * If the rule matched, permits access, and first match is enabled,
384145412Strhodes	 * return success.
385134131Strhodes	 */
386134131Strhodes	if (mac_bsdextended_firstmatch_enabled)
387134131Strhodes		return (EJUSTRETURN);
388134131Strhodes	else
389171253Srwatson		return (0);
390101099Srwatson}
391101099Srwatson
392101099Srwatsonstatic int
393157986Sdwmalonemac_bsdextended_check(struct ucred *cred, struct vnode *vp, struct vattr *vap,
394106212Srwatson    int acc_mode)
395101099Srwatson{
396101099Srwatson	int error, i;
397101099Srwatson
398164033Srwatson	/*
399171253Srwatson	 * XXXRW: More specific privilege selection needed.
400164033Srwatson	 */
401132563Srwatson	if (suser_cred(cred, 0) == 0)
402132563Srwatson		return (0);
403132563Srwatson
404166843Srwatson	/*
405166843Srwatson	 * Since we do not separately handle append, map append to write.
406166843Srwatson	 */
407166843Srwatson	if (acc_mode & MBI_APPEND) {
408166843Srwatson		acc_mode &= ~MBI_APPEND;
409166843Srwatson		acc_mode |= MBI_WRITE;
410166843Srwatson	}
411145412Strhodes	mtx_lock(&mac_bsdextended_mtx);
412101099Srwatson	for (i = 0; i < rule_slots; i++) {
413101099Srwatson		if (rules[i] == NULL)
414101099Srwatson			continue;
415157986Sdwmalone		error = mac_bsdextended_rulecheck(rules[i], cred,
416157986Sdwmalone		    vp, vap, acc_mode);
417134131Strhodes		if (error == EJUSTRETURN)
418134131Strhodes			break;
419145412Strhodes		if (error) {
420145412Strhodes			mtx_unlock(&mac_bsdextended_mtx);
421101099Srwatson			return (error);
422145412Strhodes		}
423101099Srwatson	}
424145412Strhodes	mtx_unlock(&mac_bsdextended_mtx);
425101099Srwatson	return (0);
426101099Srwatson}
427101099Srwatson
428101099Srwatsonstatic int
429156300Sdwmalonemac_bsdextended_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode)
430112575Srwatson{
431156300Sdwmalone	int error;
432112575Srwatson	struct vattr vap;
433112575Srwatson
434112575Srwatson	if (!mac_bsdextended_enabled)
435112575Srwatson		return (0);
436112575Srwatson	error = VOP_GETATTR(vp, &vap, cred, curthread);
437112575Srwatson	if (error)
438112575Srwatson		return (error);
439157986Sdwmalone	return (mac_bsdextended_check(cred, vp, &vap, acc_mode));
440112575Srwatson}
441112575Srwatson
442112575Srwatsonstatic int
443168933Srwatsonmac_bsdextended_check_system_acct(struct ucred *cred, struct vnode *vp,
444168976Srwatson    struct label *vplabel)
445168933Srwatson{
446168933Srwatson
447168933Srwatson	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
448168933Srwatson}
449168933Srwatson
450168933Srwatsonstatic int
451168933Srwatsonmac_bsdextended_check_system_auditctl(struct ucred *cred, struct vnode *vp,
452168976Srwatson    struct label *vplabel)
453168933Srwatson{
454168933Srwatson
455168933Srwatson	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
456168933Srwatson}
457168933Srwatson
458168933Srwatsonstatic int
459168933Srwatsonmac_bsdextended_check_system_swapoff(struct ucred *cred, struct vnode *vp,
460168976Srwatson    struct label *vplabel)
461168933Srwatson{
462168933Srwatson
463168933Srwatson	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
464168933Srwatson}
465168933Srwatson
466168933Srwatsonstatic int
467156300Sdwmalonemac_bsdextended_check_system_swapon(struct ucred *cred, struct vnode *vp,
468168976Srwatson    struct label *vplabel)
469156300Sdwmalone{
470156300Sdwmalone
471156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
472156300Sdwmalone}
473156300Sdwmalone
474156300Sdwmalonestatic int
475101099Srwatsonmac_bsdextended_check_vnode_access(struct ucred *cred, struct vnode *vp,
476168976Srwatson    struct label *vplabel, int acc_mode)
477101099Srwatson{
478101099Srwatson
479156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, acc_mode));
480101099Srwatson}
481101099Srwatson
482101099Srwatsonstatic int
483101099Srwatsonmac_bsdextended_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
484168976Srwatson    struct label *dvplabel)
485101099Srwatson{
486101099Srwatson
487156300Sdwmalone	return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC));
488101099Srwatson}
489101099Srwatson
490101099Srwatsonstatic int
491101099Srwatsonmac_bsdextended_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
492168976Srwatson    struct label *dvplabel)
493101099Srwatson{
494101099Srwatson
495156300Sdwmalone	return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC));
496101099Srwatson}
497101099Srwatson
498101099Srwatsonstatic int
499101099Srwatsonmac_bsdextended_check_create_vnode(struct ucred *cred, struct vnode *dvp,
500168976Srwatson    struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
501101099Srwatson{
502101099Srwatson
503156300Sdwmalone	return (mac_bsdextended_check_vp(cred, dvp, MBI_WRITE));
504101099Srwatson}
505101099Srwatson
506101099Srwatsonstatic int
507101099Srwatsonmac_bsdextended_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
508168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
509101099Srwatson    struct componentname *cnp)
510101099Srwatson{
511101099Srwatson	int error;
512101099Srwatson
513156300Sdwmalone	error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE);
514101099Srwatson	if (error)
515101099Srwatson		return (error);
516156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
517101099Srwatson}
518101099Srwatson
519101099Srwatsonstatic int
520101099Srwatsonmac_bsdextended_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
521168976Srwatson    struct label *vplabel, acl_type_t type)
522101099Srwatson{
523101099Srwatson
524156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
525101099Srwatson}
526101099Srwatson
527101099Srwatsonstatic int
528168976Srwatsonmac_bsdextended_check_vnode_deleteextattr(struct ucred *cred,
529168976Srwatson    struct vnode *vp, struct label *vplabel, int attrnamespace,
530168976Srwatson    const char *name)
531119202Srwatson{
532119202Srwatson
533156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
534119202Srwatson}
535119202Srwatson
536119202Srwatsonstatic int
537101099Srwatsonmac_bsdextended_check_vnode_exec(struct ucred *cred, struct vnode *vp,
538168976Srwatson    struct label *vplabel, struct image_params *imgp,
539106648Srwatson    struct label *execlabel)
540101099Srwatson{
541101099Srwatson
542156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_READ|MBI_EXEC));
543101099Srwatson}
544101099Srwatson
545101099Srwatsonstatic int
546101099Srwatsonmac_bsdextended_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
547168976Srwatson    struct label *vplabel, acl_type_t type)
548101099Srwatson{
549101099Srwatson
550156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_STAT));
551101099Srwatson}
552101099Srwatson
553101099Srwatsonstatic int
554101099Srwatsonmac_bsdextended_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
555168976Srwatson    struct label *vplabel, int attrnamespace, const char *name,
556168976Srwatson    struct uio *uio)
557101099Srwatson{
558101099Srwatson
559156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_READ));
560101099Srwatson}
561101099Srwatson
562101099Srwatsonstatic int
563104530Srwatsonmac_bsdextended_check_vnode_link(struct ucred *cred, struct vnode *dvp,
564168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *label,
565104530Srwatson    struct componentname *cnp)
566104530Srwatson{
567104530Srwatson	int error;
568104530Srwatson
569156300Sdwmalone	error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE);
570104530Srwatson	if (error)
571104530Srwatson		return (error);
572156300Sdwmalone	error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE);
573104530Srwatson	if (error)
574104530Srwatson		return (error);
575104530Srwatson	return (0);
576104530Srwatson}
577104530Srwatson
578104530Srwatsonstatic int
579119202Srwatsonmac_bsdextended_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
580168976Srwatson    struct label *vplabel, int attrnamespace)
581119202Srwatson{
582119202Srwatson
583156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_READ));
584119202Srwatson}
585119202Srwatson
586119202Srwatsonstatic int
587101099Srwatsonmac_bsdextended_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
588168976Srwatson    struct label *dvplabel, struct componentname *cnp)
589101099Srwatson{
590117247Srwatson
591156300Sdwmalone	return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC));
592101099Srwatson}
593101099Srwatson
594101099Srwatsonstatic int
595101099Srwatsonmac_bsdextended_check_vnode_open(struct ucred *cred, struct vnode *vp,
596168976Srwatson    struct label *vplabel, int acc_mode)
597101099Srwatson{
598101099Srwatson
599156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, acc_mode));
600101099Srwatson}
601101099Srwatson
602101099Srwatsonstatic int
603101099Srwatsonmac_bsdextended_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
604168976Srwatson    struct label *dvplabel)
605101099Srwatson{
606101099Srwatson
607156300Sdwmalone	return (mac_bsdextended_check_vp(cred, dvp, MBI_READ));
608101099Srwatson}
609101099Srwatson
610101099Srwatsonstatic int
611101099Srwatsonmac_bsdextended_check_vnode_readdlink(struct ucred *cred, struct vnode *vp,
612168976Srwatson    struct label *vplabel)
613101099Srwatson{
614101099Srwatson
615156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_READ));
616101099Srwatson}
617101099Srwatson
618101099Srwatsonstatic int
619101099Srwatsonmac_bsdextended_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
620168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
621101099Srwatson    struct componentname *cnp)
622101099Srwatson{
623101099Srwatson	int error;
624101099Srwatson
625156300Sdwmalone	error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE);
626101099Srwatson	if (error)
627101099Srwatson		return (error);
628171253Srwatson	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
629101099Srwatson}
630101099Srwatson
631101099Srwatsonstatic int
632101099Srwatsonmac_bsdextended_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
633168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
634168976Srwatson    int samedir, struct componentname *cnp)
635101099Srwatson{
636101099Srwatson	int error;
637101099Srwatson
638156300Sdwmalone	error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE);
639101099Srwatson	if (error)
640101099Srwatson		return (error);
641156300Sdwmalone	if (vp != NULL)
642156300Sdwmalone		error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE);
643101099Srwatson	return (error);
644101099Srwatson}
645101099Srwatson
646101099Srwatsonstatic int
647101099Srwatsonmac_bsdextended_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
648168976Srwatson    struct label *vplabel)
649101099Srwatson{
650101099Srwatson
651156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
652101099Srwatson}
653101099Srwatson
654101099Srwatsonstatic int
655101099Srwatsonmac_bsdextended_check_setacl_vnode(struct ucred *cred, struct vnode *vp,
656168976Srwatson    struct label *vplabel, acl_type_t type, struct acl *acl)
657101099Srwatson{
658101099Srwatson
659156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
660101099Srwatson}
661101099Srwatson
662101099Srwatsonstatic int
663101099Srwatsonmac_bsdextended_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
664168976Srwatson    struct label *vplabel, int attrnamespace, const char *name,
665168976Srwatson    struct uio *uio)
666101099Srwatson{
667101099Srwatson
668156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
669101099Srwatson}
670101099Srwatson
671101099Srwatsonstatic int
672101099Srwatsonmac_bsdextended_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
673168976Srwatson    struct label *vplabel, u_long flags)
674101099Srwatson{
675101099Srwatson
676156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
677101099Srwatson}
678101099Srwatson
679101099Srwatsonstatic int
680101099Srwatsonmac_bsdextended_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
681168976Srwatson    struct label *vplabel, mode_t mode)
682101099Srwatson{
683101099Srwatson
684156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
685101099Srwatson}
686101099Srwatson
687101099Srwatsonstatic int
688101099Srwatsonmac_bsdextended_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
689168976Srwatson    struct label *vplabel, uid_t uid, gid_t gid)
690101099Srwatson{
691101099Srwatson
692156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
693101099Srwatson}
694101099Srwatson
695101099Srwatsonstatic int
696101099Srwatsonmac_bsdextended_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
697168976Srwatson    struct label *vplabel, struct timespec atime, struct timespec utime)
698101099Srwatson{
699101099Srwatson
700156300Sdwmalone	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
701101099Srwatson}
702101099Srwatson
703101099Srwatsonstatic int
704102129Srwatsonmac_bsdextended_check_vnode_stat(struct ucred *active_cred,
705168976Srwatson    struct ucred *file_cred, struct vnode *vp, struct label *vplabel)
706101099Srwatson{
707101099Srwatson
708156300Sdwmalone	return (mac_bsdextended_check_vp(active_cred, vp, MBI_STAT));
709101099Srwatson}
710101099Srwatson
711106217Srwatsonstatic struct mac_policy_ops mac_bsdextended_ops =
712101099Srwatson{
713106217Srwatson	.mpo_destroy = mac_bsdextended_destroy,
714106217Srwatson	.mpo_init = mac_bsdextended_init,
715168933Srwatson	.mpo_check_system_acct = mac_bsdextended_check_system_acct,
716168933Srwatson	.mpo_check_system_auditctl = mac_bsdextended_check_system_auditctl,
717168933Srwatson	.mpo_check_system_swapoff = mac_bsdextended_check_system_swapoff,
718112575Srwatson	.mpo_check_system_swapon = mac_bsdextended_check_system_swapon,
719106217Srwatson	.mpo_check_vnode_access = mac_bsdextended_check_vnode_access,
720106217Srwatson	.mpo_check_vnode_chdir = mac_bsdextended_check_vnode_chdir,
721106217Srwatson	.mpo_check_vnode_chroot = mac_bsdextended_check_vnode_chroot,
722106217Srwatson	.mpo_check_vnode_create = mac_bsdextended_check_create_vnode,
723106217Srwatson	.mpo_check_vnode_delete = mac_bsdextended_check_vnode_delete,
724106217Srwatson	.mpo_check_vnode_deleteacl = mac_bsdextended_check_vnode_deleteacl,
725119202Srwatson	.mpo_check_vnode_deleteextattr = mac_bsdextended_check_vnode_deleteextattr,
726106217Srwatson	.mpo_check_vnode_exec = mac_bsdextended_check_vnode_exec,
727106217Srwatson	.mpo_check_vnode_getacl = mac_bsdextended_check_vnode_getacl,
728106217Srwatson	.mpo_check_vnode_getextattr = mac_bsdextended_check_vnode_getextattr,
729106217Srwatson	.mpo_check_vnode_link = mac_bsdextended_check_vnode_link,
730119202Srwatson	.mpo_check_vnode_listextattr = mac_bsdextended_check_vnode_listextattr,
731106217Srwatson	.mpo_check_vnode_lookup = mac_bsdextended_check_vnode_lookup,
732106217Srwatson	.mpo_check_vnode_open = mac_bsdextended_check_vnode_open,
733106217Srwatson	.mpo_check_vnode_readdir = mac_bsdextended_check_vnode_readdir,
734106217Srwatson	.mpo_check_vnode_readlink = mac_bsdextended_check_vnode_readdlink,
735106217Srwatson	.mpo_check_vnode_rename_from = mac_bsdextended_check_vnode_rename_from,
736106217Srwatson	.mpo_check_vnode_rename_to = mac_bsdextended_check_vnode_rename_to,
737106217Srwatson	.mpo_check_vnode_revoke = mac_bsdextended_check_vnode_revoke,
738106217Srwatson	.mpo_check_vnode_setacl = mac_bsdextended_check_setacl_vnode,
739106217Srwatson	.mpo_check_vnode_setextattr = mac_bsdextended_check_vnode_setextattr,
740106217Srwatson	.mpo_check_vnode_setflags = mac_bsdextended_check_vnode_setflags,
741106217Srwatson	.mpo_check_vnode_setmode = mac_bsdextended_check_vnode_setmode,
742106217Srwatson	.mpo_check_vnode_setowner = mac_bsdextended_check_vnode_setowner,
743106217Srwatson	.mpo_check_vnode_setutimes = mac_bsdextended_check_vnode_setutimes,
744106217Srwatson	.mpo_check_vnode_stat = mac_bsdextended_check_vnode_stat,
745101099Srwatson};
746101099Srwatson
747112717SrwatsonMAC_POLICY_SET(&mac_bsdextended_ops, mac_bsdextended,
748101099Srwatson    "TrustedBSD MAC/BSD Extended", MPC_LOADTIME_FLAG_UNLOADOK, NULL);
749