mac_vfs.c revision 162467
1112918Sjeff/*-
2112918Sjeff * Copyright (c) 1999-2002 Robert N. M. Watson
3112918Sjeff * Copyright (c) 2001 Ilmar S. Habibulin
4112918Sjeff * Copyright (c) 2001-2005 McAfee, Inc.
5112918Sjeff * Copyright (c) 2005 SPARTA, Inc.
6112918Sjeff * All rights reserved.
7112918Sjeff *
8112918Sjeff * This software was developed by Robert Watson and Ilmar Habibulin for the
9112918Sjeff * TrustedBSD Project.
10112918Sjeff *
11112918Sjeff * This software was developed for the FreeBSD Project in part by McAfee
12112918Sjeff * Research, the Security Research Division of McAfee, Inc. under
13112918Sjeff * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
14112918Sjeff * CHATS research program.
15112918Sjeff *
16112918Sjeff * This software was enhanced by SPARTA ISSO under SPAWAR contract
17112918Sjeff * N66001-04-C-6019 ("SEFOS").
18112918Sjeff *
19112918Sjeff * Redistribution and use in source and binary forms, with or without
20112918Sjeff * modification, are permitted provided that the following conditions
21112918Sjeff * are met:
22112918Sjeff * 1. Redistributions of source code must retain the above copyright
23112918Sjeff *    notice, this list of conditions and the following disclaimer.
24112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright
25112918Sjeff *    notice, this list of conditions and the following disclaimer in the
26112918Sjeff *    documentation and/or other materials provided with the distribution.
27112918Sjeff *
28112918Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
29112918Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30112918Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31112918Sjeff * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
32112918Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33112918Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34112918Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35112918Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36112918Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37112918Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38112918Sjeff * SUCH DAMAGE.
39112918Sjeff */
40112918Sjeff
41112918Sjeff#include <sys/cdefs.h>
42112918Sjeff__FBSDID("$FreeBSD: head/sys/security/mac/mac_vfs.c 162467 2006-09-20 13:33:41Z rwatson $");
43112918Sjeff
44112918Sjeff#include "opt_mac.h"
45112918Sjeff
46112918Sjeff#include <sys/param.h>
47112918Sjeff#include <sys/condvar.h>
48112918Sjeff#include <sys/extattr.h>
49112918Sjeff#include <sys/imgact.h>
50112918Sjeff#include <sys/kernel.h>
51112918Sjeff#include <sys/lock.h>
52112918Sjeff#include <sys/malloc.h>
53112918Sjeff#include <sys/mutex.h>
54112918Sjeff#include <sys/mac.h>
55112918Sjeff#include <sys/proc.h>
56112918Sjeff#include <sys/sbuf.h>
57112918Sjeff#include <sys/systm.h>
58112918Sjeff#include <sys/vnode.h>
59112918Sjeff#include <sys/mount.h>
60112918Sjeff#include <sys/file.h>
61112918Sjeff#include <sys/namei.h>
62112918Sjeff#include <sys/sysctl.h>
63112918Sjeff
64112918Sjeff#include <vm/vm.h>
65112918Sjeff#include <vm/pmap.h>
66112918Sjeff#include <vm/vm_map.h>
67112918Sjeff#include <vm/vm_object.h>
68112918Sjeff
69112918Sjeff#include <sys/mac_policy.h>
70112918Sjeff
71112918Sjeff#include <fs/devfs/devfs.h>
72135301Smtm
73112918Sjeff#include <security/mac/mac_internal.h>
74112918Sjeff
75112918Sjeff/*
76112918Sjeff * Warn about EA transactions only the first time they happen.
77112918Sjeff * Weak coherency, no locking.
78112918Sjeff */
79112918Sjeffstatic int	ea_warn_once = 0;
80112918Sjeff
81112918Sjeffstatic int	mac_enforce_fs = 1;
82112918SjeffSYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
83112918Sjeff    &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
84135301SmtmTUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
85112918Sjeff
86112918Sjeffstatic int	mac_setlabel_vnode_extattr(struct ucred *cred,
87112918Sjeff		    struct vnode *vp, struct label *intlabel);
88112918Sjeff
89112918Sjeffstatic struct label *
90112918Sjeffmac_devfsdirent_label_alloc(void)
91112918Sjeff{
92112918Sjeff	struct label *label;
93112918Sjeff
94112918Sjeff	label = mac_labelzone_alloc(M_WAITOK);
95131181Smtm	MAC_PERFORM(init_devfsdirent_label, label);
96131181Smtm	return (label);
97115260Smtm}
98115260Smtm
99115260Smtmvoid
100115260Smtmmac_init_devfsdirent(struct devfs_dirent *de)
101123348Smtm{
102115260Smtm
103115260Smtm	de->de_label = mac_devfsdirent_label_alloc();
104115260Smtm}
105123347Smtm
106115260Smtmstatic struct label *
107115260Smtmmac_mount_label_alloc(void)
108135301Smtm{
109135301Smtm	struct label *label;
110135301Smtm
111135301Smtm	label = mac_labelzone_alloc(M_WAITOK);
112135301Smtm	MAC_PERFORM(init_mount_label, label);
113135301Smtm	return (label);
114135301Smtm}
115135301Smtm
116135301Smtmstatic struct label *
117135301Smtmmac_mount_fs_label_alloc(void)
118135301Smtm{
119135301Smtm	struct label *label;
120135301Smtm
121112918Sjeff	label = mac_labelzone_alloc(M_WAITOK);
122112918Sjeff	MAC_PERFORM(init_mount_fs_label, label);
123112918Sjeff	return (label);
124112918Sjeff}
125112918Sjeff
126112918Sjeffvoid
127112918Sjeffmac_init_mount(struct mount *mp)
128112918Sjeff{
129112918Sjeff
130112918Sjeff	mp->mnt_mntlabel = mac_mount_label_alloc();
131112918Sjeff	mp->mnt_fslabel = mac_mount_fs_label_alloc();
132112918Sjeff}
133112918Sjeff
134112918Sjeffstruct label *
135112918Sjeffmac_vnode_label_alloc(void)
136123347Smtm{
137112918Sjeff	struct label *label;
138112918Sjeff
139123347Smtm	label = mac_labelzone_alloc(M_WAITOK);
140112918Sjeff	MAC_PERFORM(init_vnode_label, label);
141112918Sjeff	return (label);
142112918Sjeff}
143112918Sjeff
144112918Sjeffvoid
145112918Sjeffmac_init_vnode(struct vnode *vp)
146112918Sjeff{
147112918Sjeff
148112918Sjeff	vp->v_label = mac_vnode_label_alloc();
149135301Smtm}
150135301Smtm
151135301Smtmstatic void
152135301Smtmmac_devfsdirent_label_free(struct label *label)
153135301Smtm{
154135301Smtm
155135301Smtm	MAC_PERFORM(destroy_devfsdirent_label, label);
156135301Smtm	mac_labelzone_free(label);
157135301Smtm}
158135301Smtm
159135301Smtmvoid
160135301Smtmmac_destroy_devfsdirent(struct devfs_dirent *de)
161135301Smtm{
162135301Smtm
163123347Smtm	mac_devfsdirent_label_free(de->de_label);
164112918Sjeff	de->de_label = NULL;
165112918Sjeff}
166123347Smtm
167112918Sjeffstatic void
168112918Sjeffmac_mount_label_free(struct label *label)
169112918Sjeff{
170112918Sjeff
171112918Sjeff	MAC_PERFORM(destroy_mount_label, label);
172112918Sjeff	mac_labelzone_free(label);
173112918Sjeff}
174112918Sjeff
175112918Sjeffstatic void
176112918Sjeffmac_mount_fs_label_free(struct label *label)
177123347Smtm{
178112918Sjeff
179112918Sjeff	MAC_PERFORM(destroy_mount_fs_label, label);
180123347Smtm	mac_labelzone_free(label);
181112918Sjeff}
182112918Sjeff
183112918Sjeffvoid
184112918Sjeffmac_destroy_mount(struct mount *mp)
185112918Sjeff{
186112918Sjeff
187112918Sjeff	mac_mount_fs_label_free(mp->mnt_fslabel);
188112918Sjeff	mp->mnt_fslabel = NULL;
189112918Sjeff	mac_mount_label_free(mp->mnt_mntlabel);
190112918Sjeff	mp->mnt_mntlabel = NULL;
191112918Sjeff}
192112918Sjeff
193112918Sjeffvoid
194112918Sjeffmac_vnode_label_free(struct label *label)
195112918Sjeff{
196112918Sjeff
197112918Sjeff	MAC_PERFORM(destroy_vnode_label, label);
198112918Sjeff	mac_labelzone_free(label);
199112918Sjeff}
200112918Sjeff
201112918Sjeffvoid
202112918Sjeffmac_destroy_vnode(struct vnode *vp)
203112918Sjeff{
204112918Sjeff
205112918Sjeff	mac_vnode_label_free(vp->v_label);
206112918Sjeff	vp->v_label = NULL;
207112918Sjeff}
208131181Smtm
209131181Smtmvoid
210131181Smtmmac_copy_vnode_label(struct label *src, struct label *dest)
211131181Smtm{
212131181Smtm
213131181Smtm	MAC_PERFORM(copy_vnode_label, src, dest);
214131181Smtm}
215131181Smtm
216131181Smtmint
217131181Smtmmac_externalize_vnode_label(struct label *label, char *elements,
218131181Smtm    char *outbuf, size_t outbuflen)
219131181Smtm{
220131181Smtm	int error;
221131181Smtm
222131181Smtm	MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
223131181Smtm
224131181Smtm	return (error);
225131181Smtm}
226131181Smtm
227131181Smtmint
228131181Smtmmac_internalize_vnode_label(struct label *label, char *string)
229131181Smtm{
230131181Smtm	int error;
231131181Smtm
232131181Smtm	MAC_INTERNALIZE(vnode, label, string);
233131181Smtm
234131181Smtm	return (error);
235131181Smtm}
236131181Smtm
237131181Smtmvoid
238131181Smtmmac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
239131181Smtm    struct vnode *vp)
240131181Smtm{
241131181Smtm
242131181Smtm	MAC_PERFORM(update_devfsdirent, mp, de, de->de_label, vp,
243131181Smtm	    vp->v_label);
244131181Smtm}
245131181Smtm
246131181Smtmvoid
247131181Smtmmac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
248131181Smtm    struct vnode *vp)
249131181Smtm{
250131181Smtm
251131181Smtm	MAC_PERFORM(associate_vnode_devfs, mp, mp->mnt_fslabel, de,
252131181Smtm	    de->de_label, vp, vp->v_label);
253131181Smtm}
254131181Smtm
255131181Smtmint
256131181Smtmmac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
257131181Smtm{
258131181Smtm	int error;
259131181Smtm
260131181Smtm	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
261131181Smtm
262131181Smtm	MAC_CHECK(associate_vnode_extattr, mp, mp->mnt_fslabel, vp,
263131181Smtm	    vp->v_label);
264123347Smtm
265112918Sjeff	return (error);
266112918Sjeff}
267123347Smtm
268112918Sjeffvoid
269112918Sjeffmac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
270112918Sjeff{
271112918Sjeff
272112918Sjeff	MAC_PERFORM(associate_vnode_singlelabel, mp, mp->mnt_fslabel, vp,
273112918Sjeff	    vp->v_label);
274112918Sjeff}
275112918Sjeff
276112918Sjeffint
277112918Sjeffmac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
278135301Smtm    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
279135301Smtm{
280135301Smtm	int error;
281135301Smtm
282135301Smtm	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
283135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
284135301Smtm
285135301Smtm	error = VOP_OPENEXTATTR(vp, cred, curthread);
286135301Smtm	if (error == EOPNOTSUPP) {
287135301Smtm		/* XXX: Optionally abort if transactions not supported. */
288135301Smtm		if (ea_warn_once == 0) {
289135301Smtm			printf("Warning: transactions not supported "
290135301Smtm			    "in EA write.\n");
291135301Smtm			ea_warn_once = 1;
292135301Smtm		}
293135301Smtm	} else if (error)
294135301Smtm		return (error);
295135301Smtm
296135301Smtm	MAC_CHECK(create_vnode_extattr, cred, mp, mp->mnt_fslabel,
297135301Smtm	    dvp, dvp->v_label, vp, vp->v_label, cnp);
298135301Smtm
299135301Smtm	if (error) {
300135301Smtm		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
301135301Smtm		return (error);
302135301Smtm	}
303135301Smtm
304123347Smtm	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
305112918Sjeff
306112918Sjeff	if (error == EOPNOTSUPP)
307123347Smtm		error = 0;				/* XXX */
308112918Sjeff
309112918Sjeff	return (error);
310112918Sjeff}
311112918Sjeff
312112918Sjeffstatic int
313112918Sjeffmac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
314112918Sjeff    struct label *intlabel)
315112918Sjeff{
316112918Sjeff	int error;
317112918Sjeff
318112918Sjeff	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
319112918Sjeff
320112918Sjeff	error = VOP_OPENEXTATTR(vp, cred, curthread);
321112918Sjeff	if (error == EOPNOTSUPP) {
322112918Sjeff		/* XXX: Optionally abort if transactions not supported. */
323112918Sjeff		if (ea_warn_once == 0) {
324112918Sjeff			printf("Warning: transactions not supported "
325112918Sjeff			    "in EA write.\n");
326112918Sjeff			ea_warn_once = 1;
327112918Sjeff		}
328112918Sjeff	} else if (error)
329112918Sjeff		return (error);
330112918Sjeff
331112918Sjeff	MAC_CHECK(setlabel_vnode_extattr, cred, vp, vp->v_label, intlabel);
332112918Sjeff
333123347Smtm	if (error) {
334112918Sjeff		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
335112918Sjeff		return (error);
336123347Smtm	}
337112918Sjeff
338112918Sjeff	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
339112918Sjeff
340112918Sjeff	if (error == EOPNOTSUPP)
341112918Sjeff		error = 0;				/* XXX */
342112918Sjeff
343112918Sjeff	return (error);
344112918Sjeff}
345112918Sjeff
346112918Sjeffvoid
347112918Sjeffmac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
348112918Sjeff    struct label *interpvnodelabel, struct image_params *imgp)
349112918Sjeff{
350112918Sjeff
351112918Sjeff	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
352112918Sjeff
353112918Sjeff	if (!mac_enforce_process && !mac_enforce_fs)
354112918Sjeff		return;
355112918Sjeff
356112918Sjeff	MAC_PERFORM(execve_transition, old, new, vp, vp->v_label,
357112918Sjeff	    interpvnodelabel, imgp, imgp->execlabel);
358135301Smtm}
359135301Smtm
360135301Smtmint
361135301Smtmmac_execve_will_transition(struct ucred *old, struct vnode *vp,
362135301Smtm    struct label *interpvnodelabel, struct image_params *imgp)
363135301Smtm{
364135301Smtm	int result;
365135301Smtm
366135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
367135301Smtm
368135301Smtm	if (!mac_enforce_process && !mac_enforce_fs)
369135301Smtm		return (0);
370135301Smtm
371135301Smtm	result = 0;
372135301Smtm	MAC_BOOLEAN(execve_will_transition, ||, old, vp, vp->v_label,
373135301Smtm	    interpvnodelabel, imgp, imgp->execlabel);
374123347Smtm
375112918Sjeff	return (result);
376112918Sjeff}
377123347Smtm
378112918Sjeffint
379112918Sjeffmac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
380112918Sjeff{
381112918Sjeff	int error;
382112918Sjeff
383112918Sjeff	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
384112918Sjeff
385112918Sjeff	if (!mac_enforce_fs)
386112918Sjeff		return (0);
387112918Sjeff
388135301Smtm	MAC_CHECK(check_vnode_access, cred, vp, vp->v_label, acc_mode);
389135301Smtm	return (error);
390135301Smtm}
391135301Smtm
392135301Smtmint
393135301Smtmmac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
394135301Smtm{
395135301Smtm	int error;
396135301Smtm
397135301Smtm	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
398135301Smtm
399135301Smtm	if (!mac_enforce_fs)
400135301Smtm		return (0);
401135301Smtm
402135301Smtm	MAC_CHECK(check_vnode_chdir, cred, dvp, dvp->v_label);
403135301Smtm	return (error);
404135301Smtm}
405135301Smtm
406112918Sjeffint
407112918Sjeffmac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
408112918Sjeff{
409112918Sjeff	int error;
410112918Sjeff
411112918Sjeff	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
412112918Sjeff
413112918Sjeff	if (!mac_enforce_fs)
414112918Sjeff		return (0);
415112918Sjeff
416112918Sjeff	MAC_CHECK(check_vnode_chroot, cred, dvp, dvp->v_label);
417112918Sjeff	return (error);
418112918Sjeff}
419112918Sjeff
420112918Sjeffint
421135301Smtmmac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
422112918Sjeff    struct componentname *cnp, struct vattr *vap)
423135301Smtm{
424135301Smtm	int error;
425135301Smtm
426135301Smtm	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
427135301Smtm
428135301Smtm	if (!mac_enforce_fs)
429135301Smtm		return (0);
430135301Smtm
431135301Smtm	MAC_CHECK(check_vnode_create, cred, dvp, dvp->v_label, cnp, vap);
432135301Smtm	return (error);
433135301Smtm}
434135301Smtm
435135301Smtmint
436135301Smtmmac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
437135301Smtm    struct componentname *cnp)
438135301Smtm{
439127486Smtm	int error;
440127486Smtm
441127486Smtm	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
442127486Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
443127486Smtm
444127486Smtm	if (!mac_enforce_fs)
445127486Smtm		return (0);
446127486Smtm
447127486Smtm	MAC_CHECK(check_vnode_delete, cred, dvp, dvp->v_label, vp,
448127486Smtm	    vp->v_label, cnp);
449127486Smtm	return (error);
450127486Smtm}
451127486Smtm
452127486Smtmint
453127486Smtmmac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
454123347Smtm    acl_type_t type)
455112918Sjeff{
456112918Sjeff	int error;
457123347Smtm
458112918Sjeff	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
459112918Sjeff
460112918Sjeff	if (!mac_enforce_fs)
461112918Sjeff		return (0);
462112918Sjeff
463112918Sjeff	MAC_CHECK(check_vnode_deleteacl, cred, vp, vp->v_label, type);
464112918Sjeff	return (error);
465112918Sjeff}
466112918Sjeff
467112918Sjeffint
468123347Smtmmac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
469112918Sjeff    int attrnamespace, const char *name)
470112918Sjeff{
471123347Smtm	int error;
472112918Sjeff
473112918Sjeff	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr");
474112918Sjeff
475112918Sjeff	if (!mac_enforce_fs)
476112918Sjeff		return (0);
477112918Sjeff
478112918Sjeff	MAC_CHECK(check_vnode_deleteextattr, cred, vp, vp->v_label,
479112918Sjeff	    attrnamespace, name);
480112918Sjeff	return (error);
481112918Sjeff}
482135301Smtm
483135301Smtmint
484135301Smtmmac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
485135301Smtm    struct image_params *imgp)
486135301Smtm{
487135301Smtm	int error;
488135301Smtm
489135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
490135301Smtm
491135301Smtm	if (!mac_enforce_process && !mac_enforce_fs)
492135301Smtm		return (0);
493135301Smtm
494135301Smtm	MAC_CHECK(check_vnode_exec, cred, vp, vp->v_label, imgp,
495135301Smtm	    imgp->execlabel);
496135301Smtm
497135301Smtm	return (error);
498135301Smtm}
499135301Smtm
500135301Smtmint
501135301Smtmmac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
502135301Smtm{
503135301Smtm	int error;
504135301Smtm
505135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
506135301Smtm
507135301Smtm	if (!mac_enforce_fs)
508135301Smtm		return (0);
509135301Smtm
510135301Smtm	MAC_CHECK(check_vnode_getacl, cred, vp, vp->v_label, type);
511135301Smtm	return (error);
512135301Smtm}
513135301Smtm
514135301Smtmint
515135301Smtmmac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
516135301Smtm    int attrnamespace, const char *name, struct uio *uio)
517135301Smtm{
518135301Smtm	int error;
519135301Smtm
520135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
521135301Smtm
522135301Smtm	if (!mac_enforce_fs)
523135301Smtm		return (0);
524135301Smtm
525135301Smtm	MAC_CHECK(check_vnode_getextattr, cred, vp, vp->v_label,
526135301Smtm	    attrnamespace, name, uio);
527135301Smtm	return (error);
528123347Smtm}
529112918Sjeff
530112918Sjeffint
531123347Smtmmac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
532112918Sjeff    struct vnode *vp, struct componentname *cnp)
533112918Sjeff{
534112918Sjeff	int error;
535112918Sjeff
536112918Sjeff	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
537112918Sjeff	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
538112918Sjeff
539112918Sjeff	if (!mac_enforce_fs)
540112918Sjeff		return (0);
541112918Sjeff
542112918Sjeff	MAC_CHECK(check_vnode_link, cred, dvp, dvp->v_label, vp,
543135301Smtm	    vp->v_label, cnp);
544135301Smtm	return (error);
545135301Smtm}
546135301Smtm
547135301Smtmint
548135301Smtmmac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
549135301Smtm    int attrnamespace)
550135301Smtm{
551135301Smtm	int error;
552135301Smtm
553135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr");
554135301Smtm
555135301Smtm	if (!mac_enforce_fs)
556135301Smtm		return (0);
557135301Smtm
558135301Smtm	MAC_CHECK(check_vnode_listextattr, cred, vp, vp->v_label,
559135301Smtm	    attrnamespace);
560135301Smtm	return (error);
561135301Smtm}
562135301Smtm
563135301Smtmint
564135301Smtmmac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
565135301Smtm    struct componentname *cnp)
566135301Smtm{
567135301Smtm	int error;
568135301Smtm
569135301Smtm	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
570135301Smtm
571135301Smtm	if (!mac_enforce_fs)
572135301Smtm		return (0);
573135301Smtm
574135301Smtm	MAC_CHECK(check_vnode_lookup, cred, dvp, dvp->v_label, cnp);
575135301Smtm	return (error);
576135301Smtm}
577135301Smtm
578135301Smtmint
579135301Smtmmac_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
580135301Smtm    int prot, int flags)
581135301Smtm{
582135301Smtm	int error;
583135301Smtm
584135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
585135301Smtm
586135301Smtm	if (!mac_enforce_fs || !mac_enforce_vm)
587135301Smtm		return (0);
588135301Smtm
589135301Smtm	MAC_CHECK(check_vnode_mmap, cred, vp, vp->v_label, prot, flags);
590135301Smtm	return (error);
591135301Smtm}
592135301Smtm
593135301Smtmvoid
594135301Smtmmac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
595135301Smtm{
596135301Smtm	int result = *prot;
597135301Smtm
598135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
599135301Smtm
600135301Smtm	if (!mac_enforce_fs || !mac_enforce_vm)
601135301Smtm		return;
602135301Smtm
603135301Smtm	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, vp->v_label,
604135301Smtm	    &result);
605135301Smtm
606135301Smtm	*prot = result;
607135301Smtm}
608135301Smtm
609135301Smtmint
610135301Smtmmac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
611135301Smtm{
612135301Smtm	int error;
613135301Smtm
614135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
615135301Smtm
616135301Smtm	if (!mac_enforce_fs || !mac_enforce_vm)
617135301Smtm		return (0);
618135301Smtm
619135301Smtm	MAC_CHECK(check_vnode_mprotect, cred, vp, vp->v_label, prot);
620135301Smtm	return (error);
621135301Smtm}
622135301Smtm
623135301Smtmint
624135301Smtmmac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
625135301Smtm{
626135301Smtm	int error;
627135301Smtm
628135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
629135301Smtm
630135301Smtm	if (!mac_enforce_fs)
631135301Smtm		return (0);
632135301Smtm
633135301Smtm	MAC_CHECK(check_vnode_open, cred, vp, vp->v_label, acc_mode);
634135301Smtm	return (error);
635135301Smtm}
636135301Smtm
637135301Smtmint
638135301Smtmmac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
639135301Smtm    struct vnode *vp)
640135301Smtm{
641135301Smtm	int error;
642135301Smtm
643135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
644135301Smtm
645135301Smtm	if (!mac_enforce_fs)
646135301Smtm		return (0);
647135301Smtm
648135301Smtm	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
649135301Smtm	    vp->v_label);
650135301Smtm
651135301Smtm	return (error);
652135301Smtm}
653135301Smtm
654135301Smtmint
655135301Smtmmac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
656135301Smtm    struct vnode *vp)
657135301Smtm{
658135301Smtm	int error;
659135301Smtm
660112918Sjeff	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
661112918Sjeff
662112918Sjeff	if (!mac_enforce_fs)
663112918Sjeff		return (0);
664112918Sjeff
665112918Sjeff	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
666112918Sjeff	    vp->v_label);
667112918Sjeff
668112918Sjeff	return (error);
669112918Sjeff}
670112918Sjeff
671112918Sjeffint
672112918Sjeffmac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
673112918Sjeff{
674112918Sjeff	int error;
675112918Sjeff
676112918Sjeff	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
677112918Sjeff
678112918Sjeff	if (!mac_enforce_fs)
679112918Sjeff		return (0);
680112918Sjeff
681112918Sjeff	MAC_CHECK(check_vnode_readdir, cred, dvp, dvp->v_label);
682112918Sjeff	return (error);
683112918Sjeff}
684112918Sjeff
685112918Sjeffint
686112918Sjeffmac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
687112918Sjeff{
688112918Sjeff	int error;
689112918Sjeff
690112918Sjeff	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
691112918Sjeff
692112918Sjeff	if (!mac_enforce_fs)
693112918Sjeff		return (0);
694112918Sjeff
695112918Sjeff	MAC_CHECK(check_vnode_readlink, cred, vp, vp->v_label);
696112918Sjeff	return (error);
697112918Sjeff}
698112918Sjeff
699112918Sjeffstatic int
700112918Sjeffmac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
701112918Sjeff    struct label *newlabel)
702112918Sjeff{
703135301Smtm	int error;
704135301Smtm
705135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
706135301Smtm
707135301Smtm	MAC_CHECK(check_vnode_relabel, cred, vp, vp->v_label, newlabel);
708135301Smtm
709135301Smtm	return (error);
710135301Smtm}
711135301Smtm
712135301Smtmint
713135301Smtmmac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
714135301Smtm    struct vnode *vp, struct componentname *cnp)
715135301Smtm{
716135301Smtm	int error;
717135301Smtm
718135301Smtm	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
719135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
720135301Smtm
721135301Smtm	if (!mac_enforce_fs)
722112918Sjeff		return (0);
723112918Sjeff
724112918Sjeff	MAC_CHECK(check_vnode_rename_from, cred, dvp, dvp->v_label, vp,
725112918Sjeff	    vp->v_label, cnp);
726112918Sjeff	return (error);
727112918Sjeff}
728112918Sjeff
729112918Sjeffint
730112918Sjeffmac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
731112918Sjeff    struct vnode *vp, int samedir, struct componentname *cnp)
732112918Sjeff{
733112918Sjeff	int error;
734112918Sjeff
735112918Sjeff	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
736123347Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
737112918Sjeff
738112918Sjeff	if (!mac_enforce_fs)
739123347Smtm		return (0);
740112918Sjeff
741112918Sjeff	MAC_CHECK(check_vnode_rename_to, cred, dvp, dvp->v_label, vp,
742112918Sjeff	    vp != NULL ? vp->v_label : NULL, samedir, cnp);
743112918Sjeff	return (error);
744123347Smtm}
745112918Sjeff
746112918Sjeffint
747112918Sjeffmac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
748112918Sjeff{
749112918Sjeff	int error;
750135301Smtm
751135301Smtm	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
752135301Smtm
753135301Smtm	if (!mac_enforce_fs)
754112918Sjeff		return (0);
755112918Sjeff
756112918Sjeff	MAC_CHECK(check_vnode_revoke, cred, vp, vp->v_label);
757112918Sjeff	return (error);
758112918Sjeff}
759112918Sjeff
760112918Sjeffint
761112918Sjeffmac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
762112918Sjeff    struct acl *acl)
763112918Sjeff{
764112918Sjeff	int error;
765112918Sjeff
766112918Sjeff	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
767135301Smtm
768112918Sjeff	if (!mac_enforce_fs)
769123347Smtm		return (0);
770112918Sjeff
771112918Sjeff	MAC_CHECK(check_vnode_setacl, cred, vp, vp->v_label, type, acl);
772123347Smtm	return (error);
773112918Sjeff}
774112918Sjeff
775112918Sjeffint
776112918Sjeffmac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
777112918Sjeff    int attrnamespace, const char *name, struct uio *uio)
778112918Sjeff{
779112918Sjeff	int error;
780112918Sjeff
781112918Sjeff	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
782112918Sjeff
783123347Smtm	if (!mac_enforce_fs)
784112918Sjeff		return (0);
785112918Sjeff
786123347Smtm	MAC_CHECK(check_vnode_setextattr, cred, vp, vp->v_label,
787112918Sjeff	    attrnamespace, name, uio);
788112918Sjeff	return (error);
789112918Sjeff}
790112918Sjeff
791112918Sjeffint
792112918Sjeffmac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
793112918Sjeff{
794112918Sjeff	int error;
795112918Sjeff
796	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
797
798	if (!mac_enforce_fs)
799		return (0);
800
801	MAC_CHECK(check_vnode_setflags, cred, vp, vp->v_label, flags);
802	return (error);
803}
804
805int
806mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
807{
808	int error;
809
810	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
811
812	if (!mac_enforce_fs)
813		return (0);
814
815	MAC_CHECK(check_vnode_setmode, cred, vp, vp->v_label, mode);
816	return (error);
817}
818
819int
820mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
821    gid_t gid)
822{
823	int error;
824
825	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
826
827	if (!mac_enforce_fs)
828		return (0);
829
830	MAC_CHECK(check_vnode_setowner, cred, vp, vp->v_label, uid, gid);
831	return (error);
832}
833
834int
835mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
836    struct timespec atime, struct timespec mtime)
837{
838	int error;
839
840	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
841
842	if (!mac_enforce_fs)
843		return (0);
844
845	MAC_CHECK(check_vnode_setutimes, cred, vp, vp->v_label, atime,
846	    mtime);
847	return (error);
848}
849
850int
851mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
852    struct vnode *vp)
853{
854	int error;
855
856	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
857
858	if (!mac_enforce_fs)
859		return (0);
860
861	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
862	    vp->v_label);
863	return (error);
864}
865
866int
867mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
868    struct vnode *vp)
869{
870	int error;
871
872	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
873
874	if (!mac_enforce_fs)
875		return (0);
876
877	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
878	    vp->v_label);
879
880	return (error);
881}
882
883void
884mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
885{
886
887	MAC_PERFORM(relabel_vnode, cred, vp, vp->v_label, newlabel);
888}
889
890void
891mac_create_mount(struct ucred *cred, struct mount *mp)
892{
893
894	MAC_PERFORM(create_mount, cred, mp, mp->mnt_mntlabel,
895	    mp->mnt_fslabel);
896}
897
898int
899mac_check_mount_stat(struct ucred *cred, struct mount *mount)
900{
901	int error;
902
903	if (!mac_enforce_fs)
904		return (0);
905
906	MAC_CHECK(check_mount_stat, cred, mount, mount->mnt_mntlabel);
907
908	return (error);
909}
910
911void
912mac_create_devfs_device(struct ucred *cred, struct mount *mp,
913    struct cdev *dev, struct devfs_dirent *de)
914{
915
916	MAC_PERFORM(create_devfs_device, cred, mp, dev, de, de->de_label);
917}
918
919void
920mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
921    struct devfs_dirent *dd, struct devfs_dirent *de)
922{
923
924	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, dd->de_label, de,
925	    de->de_label);
926}
927
928void
929mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
930    struct devfs_dirent *de)
931{
932
933	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
934	    de->de_label);
935}
936
937/*
938 * Implementation of VOP_SETLABEL() that relies on extended attributes
939 * to store label data.  Can be referenced by filesystems supporting
940 * extended attributes.
941 */
942int
943vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
944{
945	struct vnode *vp = ap->a_vp;
946	struct label *intlabel = ap->a_label;
947	int error;
948
949	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
950
951	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
952		return (EOPNOTSUPP);
953
954	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
955	if (error)
956		return (error);
957
958	mac_relabel_vnode(ap->a_cred, vp, intlabel);
959
960	return (0);
961}
962
963int
964vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
965{
966	int error;
967
968	if (vp->v_mount == NULL) {
969		/* printf("vn_setlabel: null v_mount\n"); */
970		if (vp->v_type != VNON)
971			printf("vn_setlabel: null v_mount with non-VNON\n");
972		return (EBADF);
973	}
974
975	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
976		return (EOPNOTSUPP);
977
978	/*
979	 * Multi-phase commit.  First check the policies to confirm the
980	 * change is OK.  Then commit via the filesystem.  Finally,
981	 * update the actual vnode label.  Question: maybe the filesystem
982	 * should update the vnode at the end as part of VOP_SETLABEL()?
983	 */
984	error = mac_check_vnode_relabel(cred, vp, intlabel);
985	if (error)
986		return (error);
987
988	/*
989	 * VADMIN provides the opportunity for the filesystem to make
990	 * decisions about who is and is not able to modify labels
991	 * and protections on files.  This might not be right.  We can't
992	 * assume VOP_SETLABEL() will do it, because we might implement
993	 * that as part of vop_stdsetlabel_ea().
994	 */
995	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
996	if (error)
997		return (error);
998
999	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
1000	if (error)
1001		return (error);
1002
1003	return (0);
1004}
1005
1006void
1007mac_associate_nfsd_label(struct ucred *cred)
1008{
1009
1010	MAC_PERFORM(associate_nfsd_label, cred);
1011}
1012