vfs_acl.c revision 208781
154803Srwatson/*-
2160146Srwatson * Copyright (c) 1999-2006 Robert N. M. Watson
354803Srwatson * All rights reserved.
454803Srwatson *
585845Srwatson * This software was developed by Robert Watson for the TrustedBSD Project.
685845Srwatson *
754803Srwatson * Redistribution and use in source and binary forms, with or without
854803Srwatson * modification, are permitted provided that the following conditions
954803Srwatson * are met:
1054803Srwatson * 1. Redistributions of source code must retain the above copyright
1154803Srwatson *    notice, this list of conditions and the following disclaimer.
1254803Srwatson * 2. Redistributions in binary form must reproduce the above copyright
1354803Srwatson *    notice, this list of conditions and the following disclaimer in the
1454803Srwatson *    documentation and/or other materials provided with the distribution.
1554803Srwatson *
1654803Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1754803Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1854803Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1954803Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2054803Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2154803Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2254803Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2354803Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2454803Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2554803Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2654803Srwatson * SUCH DAMAGE.
2754803Srwatson */
2854803Srwatson/*
2973890Srwatson * Developed by the TrustedBSD Project.
30160146Srwatson *
31160146Srwatson * ACL system calls and other functions common across different ACL types.
32160146Srwatson * Type-specific routines go into subr_acl_<type>.c.
3354803Srwatson */
3454803Srwatson
35116182Sobrien#include <sys/cdefs.h>
36116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/vfs_acl.c 208781 2010-06-03 13:45:27Z trasz $");
37116182Sobrien
3854803Srwatson#include <sys/param.h>
3954803Srwatson#include <sys/systm.h>
4054803Srwatson#include <sys/sysproto.h>
41177785Skib#include <sys/fcntl.h>
4254803Srwatson#include <sys/kernel.h>
4354803Srwatson#include <sys/malloc.h>
44150262Scsjp#include <sys/mount.h>
4554803Srwatson#include <sys/vnode.h>
4654803Srwatson#include <sys/lock.h>
4782713Sdillon#include <sys/mutex.h>
4854803Srwatson#include <sys/namei.h>
4954803Srwatson#include <sys/file.h>
50108524Salfred#include <sys/filedesc.h>
5154803Srwatson#include <sys/proc.h>
5254803Srwatson#include <sys/sysent.h>
5354803Srwatson#include <sys/acl.h>
5454803Srwatson
55163606Srwatson#include <security/mac/mac_framework.h>
56163606Srwatson
57192586StraszCTASSERT(ACL_MAX_ENTRIES >= OLDACL_MAX_ENTRIES);
5854803Srwatson
59192586StraszMALLOC_DEFINE(M_ACL, "acl", "Access Control Lists");
60192586Strasz
6198927Srwatsonstatic int	vacl_set_acl(struct thread *td, struct vnode *vp,
6298927Srwatson		    acl_type_t type, struct acl *aclp);
6398927Srwatsonstatic int	vacl_get_acl(struct thread *td, struct vnode *vp,
6498927Srwatson		    acl_type_t type, struct acl *aclp);
6585582Srwatsonstatic int	vacl_aclcheck(struct thread *td, struct vnode *vp,
6698927Srwatson		    acl_type_t type, struct acl *aclp);
6754803Srwatson
68192586Straszint
69192586Straszacl_copy_oldacl_into_acl(const struct oldacl *source, struct acl *dest)
70192586Strasz{
71192586Strasz	int i;
72192586Strasz
73192586Strasz	if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES)
74192586Strasz		return (EINVAL);
75192586Strasz
76192586Strasz	bzero(dest, sizeof(*dest));
77192586Strasz
78192586Strasz	dest->acl_cnt = source->acl_cnt;
79192586Strasz	dest->acl_maxcnt = ACL_MAX_ENTRIES;
80192586Strasz
81192586Strasz	for (i = 0; i < dest->acl_cnt; i++) {
82192586Strasz		dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag;
83192586Strasz		dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id;
84192586Strasz		dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm;
85192586Strasz	}
86192586Strasz
87192586Strasz	return (0);
88192586Strasz}
89192586Strasz
90192586Straszint
91192586Straszacl_copy_acl_into_oldacl(const struct acl *source, struct oldacl *dest)
92192586Strasz{
93192586Strasz	int i;
94192586Strasz
95208781Strasz	if (source->acl_cnt > OLDACL_MAX_ENTRIES)
96192586Strasz		return (EINVAL);
97192586Strasz
98192586Strasz	bzero(dest, sizeof(*dest));
99192586Strasz
100192586Strasz	dest->acl_cnt = source->acl_cnt;
101192586Strasz
102192586Strasz	for (i = 0; i < dest->acl_cnt; i++) {
103192586Strasz		dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag;
104192586Strasz		dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id;
105192586Strasz		dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm;
106192586Strasz	}
107192586Strasz
108192586Strasz	return (0);
109192586Strasz}
110192586Strasz
11154803Srwatson/*
112192586Strasz * At one time, "struct ACL" was extended in order to add support for NFSv4
113192586Strasz * ACLs.  Instead of creating compatibility versions of all the ACL-related
114192586Strasz * syscalls, they were left intact.  It's possible to find out what the code
115192586Strasz * calling these syscalls (libc) expects basing on "type" argument - if it's
116192586Strasz * either ACL_TYPE_ACCESS_OLD or ACL_TYPE_DEFAULT_OLD (which previously were
117192586Strasz * known as ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT), then it's the "struct
118192586Strasz * oldacl".  If it's something else, then it's the new "struct acl".  In the
119192586Strasz * latter case, the routines below just copyin/copyout the contents.  In the
120192586Strasz * former case, they copyin the "struct oldacl" and convert it to the new
121192586Strasz * format.
122192586Strasz */
123192586Straszstatic int
124192586Straszacl_copyin(void *user_acl, struct acl *kernel_acl, acl_type_t type)
125192586Strasz{
126192586Strasz	int error;
127192586Strasz	struct oldacl old;
128192586Strasz
129192586Strasz	switch (type) {
130192586Strasz	case ACL_TYPE_ACCESS_OLD:
131192586Strasz	case ACL_TYPE_DEFAULT_OLD:
132192586Strasz		error = copyin(user_acl, &old, sizeof(old));
133192586Strasz		if (error != 0)
134192586Strasz			break;
135192586Strasz		acl_copy_oldacl_into_acl(&old, kernel_acl);
136192586Strasz		break;
137192586Strasz
138192586Strasz	default:
139192586Strasz		error = copyin(user_acl, kernel_acl, sizeof(*kernel_acl));
140192586Strasz		if (kernel_acl->acl_maxcnt != ACL_MAX_ENTRIES)
141192586Strasz			return (EINVAL);
142192586Strasz	}
143192586Strasz
144192586Strasz	return (error);
145192586Strasz}
146192586Strasz
147192586Straszstatic int
148192586Straszacl_copyout(struct acl *kernel_acl, void *user_acl, acl_type_t type)
149192586Strasz{
150192586Strasz	int error;
151192586Strasz	struct oldacl old;
152192586Strasz
153192586Strasz	switch (type) {
154192586Strasz	case ACL_TYPE_ACCESS_OLD:
155192586Strasz	case ACL_TYPE_DEFAULT_OLD:
156192586Strasz		error = acl_copy_acl_into_oldacl(kernel_acl, &old);
157192586Strasz		if (error != 0)
158192586Strasz			break;
159192586Strasz
160192586Strasz		error = copyout(&old, user_acl, sizeof(old));
161192586Strasz		break;
162192586Strasz
163192586Strasz	default:
164197789Strasz		if (fuword32((char *)user_acl +
165192586Strasz		    offsetof(struct acl, acl_maxcnt)) != ACL_MAX_ENTRIES)
166192586Strasz			return (EINVAL);
167192586Strasz
168192586Strasz		error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl));
169192586Strasz	}
170192586Strasz
171192586Strasz	return (error);
172192586Strasz}
173192586Strasz
174192586Strasz/*
175192586Strasz * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new"
176200058Strasz * counterpart.  It's required for old (pre-NFSv4 ACLs) libc to work
177192586Strasz * with new kernel.  Fixing 'type' for old binaries with new libc
178192586Strasz * is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold().
179192586Strasz */
180192586Straszstatic int
181192586Straszacl_type_unold(int type)
182192586Strasz{
183192586Strasz	switch (type) {
184192586Strasz	case ACL_TYPE_ACCESS_OLD:
185192586Strasz		return (ACL_TYPE_ACCESS);
186192586Strasz
187192586Strasz	case ACL_TYPE_DEFAULT_OLD:
188192586Strasz		return (ACL_TYPE_DEFAULT);
189192586Strasz
190192586Strasz	default:
191192586Strasz		return (type);
192192586Strasz	}
193192586Strasz}
194192586Strasz
195192586Strasz/*
196165983Srwatson * These calls wrap the real vnode operations, and are called by the syscall
197165983Srwatson * code once the syscall has converted the path or file descriptor to a vnode
198165983Srwatson * (unlocked).  The aclp pointer is assumed still to point to userland, so
199165983Srwatson * this should not be consumed within the kernel except by syscall code.
200165983Srwatson * Other code should directly invoke VOP_{SET,GET}ACL.
20154803Srwatson */
20254803Srwatson
20354803Srwatson/*
20454803Srwatson * Given a vnode, set its ACL.
20554803Srwatson */
20654803Srwatsonstatic int
20785582Srwatsonvacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type,
20856272Srwatson    struct acl *aclp)
20954803Srwatson{
210191249Strasz	struct acl *inkernelacl;
21190202Srwatson	struct mount *mp;
21254803Srwatson	int error;
21354803Srwatson
214191249Strasz	inkernelacl = acl_alloc(M_WAITOK);
215192586Strasz	error = acl_copyin(aclp, inkernelacl, type);
216198875Strasz	if (error != 0)
217191249Strasz		goto out;
21890202Srwatson	error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
21990202Srwatson	if (error != 0)
220191249Strasz		goto out;
221175202Sattilio	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
222101122Srwatson#ifdef MAC
223191249Strasz	error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl);
224101122Srwatson	if (error != 0)
225191249Strasz		goto out_unlock;
226101122Srwatson#endif
227192586Strasz	error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl,
228192586Strasz	    td->td_ucred, td);
229101122Srwatson#ifdef MAC
230191249Straszout_unlock:
231101122Srwatson#endif
232175294Sattilio	VOP_UNLOCK(vp, 0);
23390202Srwatson	vn_finished_write(mp);
234191249Straszout:
235191249Strasz	acl_free(inkernelacl);
236198875Strasz	return (error);
23754803Srwatson}
23854803Srwatson
23954803Srwatson/*
24054803Srwatson * Given a vnode, get its ACL.
24154803Srwatson */
24254803Srwatsonstatic int
24385582Srwatsonvacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type,
24454803Srwatson    struct acl *aclp)
24554803Srwatson{
246191249Strasz	struct acl *inkernelacl;
24754803Srwatson	int error;
24854803Srwatson
249191249Strasz	inkernelacl = acl_alloc(M_WAITOK);
250175202Sattilio	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
251101122Srwatson#ifdef MAC
252172930Srwatson	error = mac_vnode_check_getacl(td->td_ucred, vp, type);
253101122Srwatson	if (error != 0)
254101122Srwatson		goto out;
255101122Srwatson#endif
256192586Strasz	error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl,
257192586Strasz	    td->td_ucred, td);
258192586Strasz
259101122Srwatson#ifdef MAC
260101122Srwatsonout:
261101122Srwatson#endif
262175294Sattilio	VOP_UNLOCK(vp, 0);
26354803Srwatson	if (error == 0)
264192586Strasz		error = acl_copyout(inkernelacl, aclp, type);
265191249Strasz	acl_free(inkernelacl);
26654803Srwatson	return (error);
26754803Srwatson}
26854803Srwatson
26954803Srwatson/*
27054803Srwatson * Given a vnode, delete its ACL.
27154803Srwatson */
27254803Srwatsonstatic int
27385582Srwatsonvacl_delete(struct thread *td, struct vnode *vp, acl_type_t type)
27454803Srwatson{
27590202Srwatson	struct mount *mp;
27654803Srwatson	int error;
27754803Srwatson
27890202Srwatson	error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
279198875Strasz	if (error != 0)
28090202Srwatson		return (error);
281175202Sattilio	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
282101122Srwatson#ifdef MAC
283172930Srwatson	error = mac_vnode_check_deleteacl(td->td_ucred, vp, type);
284198875Strasz	if (error != 0)
285101122Srwatson		goto out;
286101122Srwatson#endif
287192586Strasz	error = VOP_SETACL(vp, acl_type_unold(type), 0, td->td_ucred, td);
288101122Srwatson#ifdef MAC
289101122Srwatsonout:
290101122Srwatson#endif
291175294Sattilio	VOP_UNLOCK(vp, 0);
29290202Srwatson	vn_finished_write(mp);
29354803Srwatson	return (error);
29454803Srwatson}
29554803Srwatson
29654803Srwatson/*
29754803Srwatson * Given a vnode, check whether an ACL is appropriate for it
29854803Srwatson */
29954803Srwatsonstatic int
30085582Srwatsonvacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type,
30154803Srwatson    struct acl *aclp)
30254803Srwatson{
303191249Strasz	struct acl *inkernelacl;
30454803Srwatson	int error;
30554803Srwatson
306191249Strasz	inkernelacl = acl_alloc(M_WAITOK);
307192586Strasz	error = acl_copyin(aclp, inkernelacl, type);
308198875Strasz	if (error != 0)
309191249Strasz		goto out;
310200058Strasz	error = VOP_ACLCHECK(vp, acl_type_unold(type), inkernelacl,
311200058Strasz	    td->td_ucred, td);
312191249Straszout:
313191249Strasz	acl_free(inkernelacl);
31454803Srwatson	return (error);
31554803Srwatson}
31654803Srwatson
31754803Srwatson/*
318165983Srwatson * syscalls -- convert the path/fd to a vnode, and call vacl_whatever.  Don't
319165983Srwatson * need to lock, as the vacl_ code will get/release any locks required.
32054803Srwatson */
32154803Srwatson
32254803Srwatson/*
32354803Srwatson * Given a file path, get an ACL for it
32454803Srwatson */
32554803Srwatsonint
32685582Srwatson__acl_get_file(struct thread *td, struct __acl_get_file_args *uap)
32754803Srwatson{
32854803Srwatson	struct nameidata nd;
329150262Scsjp	int vfslocked, error;
33054803Srwatson
331150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
33254803Srwatson	error = namei(&nd);
333150262Scsjp	vfslocked = NDHASGIANT(&nd);
33482713Sdillon	if (error == 0) {
335107855Salfred		error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp);
33682713Sdillon		NDFREE(&nd, 0);
33782713Sdillon	}
338150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
33954803Srwatson	return (error);
34054803Srwatson}
34154803Srwatson
34254803Srwatson/*
343108407Srwatson * Given a file path, get an ACL for it; don't follow links.
344108407Srwatson */
345108407Srwatsonint
346108407Srwatson__acl_get_link(struct thread *td, struct __acl_get_link_args *uap)
347108407Srwatson{
348108407Srwatson	struct nameidata nd;
349150262Scsjp	int vfslocked, error;
350108407Srwatson
351150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
352108407Srwatson	error = namei(&nd);
353150262Scsjp	vfslocked = NDHASGIANT(&nd);
354108407Srwatson	if (error == 0) {
355108407Srwatson		error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp);
356108407Srwatson		NDFREE(&nd, 0);
357108407Srwatson	}
358150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
359108407Srwatson	return (error);
360108407Srwatson}
361108407Srwatson
362108407Srwatson/*
363167211Srwatson * Given a file path, set an ACL for it.
36454803Srwatson */
36554803Srwatsonint
36685582Srwatson__acl_set_file(struct thread *td, struct __acl_set_file_args *uap)
36754803Srwatson{
36854803Srwatson	struct nameidata nd;
369150262Scsjp	int vfslocked, error;
37054803Srwatson
371150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
37254803Srwatson	error = namei(&nd);
373150262Scsjp	vfslocked = NDHASGIANT(&nd);
37482713Sdillon	if (error == 0) {
375107855Salfred		error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp);
37682713Sdillon		NDFREE(&nd, 0);
37782713Sdillon	}
378150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
37954803Srwatson	return (error);
38054803Srwatson}
38154803Srwatson
38254803Srwatson/*
383108407Srwatson * Given a file path, set an ACL for it; don't follow links.
384108407Srwatson */
385108407Srwatsonint
386108407Srwatson__acl_set_link(struct thread *td, struct __acl_set_link_args *uap)
387108407Srwatson{
388108407Srwatson	struct nameidata nd;
389150262Scsjp	int vfslocked, error;
390108407Srwatson
391150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
392108407Srwatson	error = namei(&nd);
393150262Scsjp	vfslocked = NDHASGIANT(&nd);
394108407Srwatson	if (error == 0) {
395108407Srwatson		error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp);
396108407Srwatson		NDFREE(&nd, 0);
397108407Srwatson	}
398150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
399108407Srwatson	return (error);
400108407Srwatson}
401108407Srwatson
402108407Srwatson/*
403167234Srwatson * Given a file descriptor, get an ACL for it.
40454803Srwatson */
40554803Srwatsonint
40685582Srwatson__acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap)
40754803Srwatson{
40854803Srwatson	struct file *fp;
409150262Scsjp	int vfslocked, error;
41054803Srwatson
411107849Salfred	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
41282713Sdillon	if (error == 0) {
413150262Scsjp		vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
414116678Sphk		error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp);
41589306Salfred		fdrop(fp, td);
416150262Scsjp		VFS_UNLOCK_GIANT(vfslocked);
41782713Sdillon	}
41882713Sdillon	return (error);
41954803Srwatson}
42054803Srwatson
42154803Srwatson/*
422167234Srwatson * Given a file descriptor, set an ACL for it.
42354803Srwatson */
42454803Srwatsonint
42585582Srwatson__acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap)
42654803Srwatson{
42754803Srwatson	struct file *fp;
428150262Scsjp	int vfslocked, error;
42954803Srwatson
430107849Salfred	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
43182713Sdillon	if (error == 0) {
432150262Scsjp		vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
433116678Sphk		error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp);
43489306Salfred		fdrop(fp, td);
435150262Scsjp		VFS_UNLOCK_GIANT(vfslocked);
43682713Sdillon	}
43782713Sdillon	return (error);
43854803Srwatson}
43954803Srwatson
44054803Srwatson/*
44154803Srwatson * Given a file path, delete an ACL from it.
44254803Srwatson */
44354803Srwatsonint
44485582Srwatson__acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap)
44554803Srwatson{
44654803Srwatson	struct nameidata nd;
447150262Scsjp	int vfslocked, error;
44854803Srwatson
449150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
45054803Srwatson	error = namei(&nd);
451150262Scsjp	vfslocked = NDHASGIANT(&nd);
45282713Sdillon	if (error == 0) {
453107849Salfred		error = vacl_delete(td, nd.ni_vp, uap->type);
45482713Sdillon		NDFREE(&nd, 0);
45582713Sdillon	}
456150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
45754803Srwatson	return (error);
45854803Srwatson}
45954803Srwatson
46054803Srwatson/*
461108407Srwatson * Given a file path, delete an ACL from it; don't follow links.
462108407Srwatson */
463108407Srwatsonint
464108407Srwatson__acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap)
465108407Srwatson{
466108407Srwatson	struct nameidata nd;
467150262Scsjp	int vfslocked, error;
468108407Srwatson
469150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
470108407Srwatson	error = namei(&nd);
471150262Scsjp	vfslocked = NDHASGIANT(&nd);
472108407Srwatson	if (error == 0) {
473108407Srwatson		error = vacl_delete(td, nd.ni_vp, uap->type);
474108407Srwatson		NDFREE(&nd, 0);
475108407Srwatson	}
476150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
477108407Srwatson	return (error);
478108407Srwatson}
479108407Srwatson
480108407Srwatson/*
48154803Srwatson * Given a file path, delete an ACL from it.
48254803Srwatson */
48354803Srwatsonint
48485582Srwatson__acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap)
48554803Srwatson{
48654803Srwatson	struct file *fp;
487150262Scsjp	int vfslocked, error;
48854803Srwatson
489107849Salfred	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
49082713Sdillon	if (error == 0) {
491150262Scsjp		vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
492116678Sphk		error = vacl_delete(td, fp->f_vnode, uap->type);
49389306Salfred		fdrop(fp, td);
494150262Scsjp		VFS_UNLOCK_GIANT(vfslocked);
49582713Sdillon	}
49654803Srwatson	return (error);
49754803Srwatson}
49854803Srwatson
49954803Srwatson/*
500167211Srwatson * Given a file path, check an ACL for it.
50154803Srwatson */
50254803Srwatsonint
50385582Srwatson__acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap)
50454803Srwatson{
505198875Strasz	struct nameidata nd;
506150262Scsjp	int vfslocked, error;
50754803Srwatson
508150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
50954803Srwatson	error = namei(&nd);
510150262Scsjp	vfslocked = NDHASGIANT(&nd);
51182713Sdillon	if (error == 0) {
512107855Salfred		error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp);
51382713Sdillon		NDFREE(&nd, 0);
51482713Sdillon	}
515150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
51654803Srwatson	return (error);
51754803Srwatson}
51854803Srwatson
51954803Srwatson/*
520108407Srwatson * Given a file path, check an ACL for it; don't follow links.
521108407Srwatson */
522108407Srwatsonint
523108407Srwatson__acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap)
524108407Srwatson{
525198877Strasz	struct nameidata nd;
526150262Scsjp	int vfslocked, error;
527108407Srwatson
528150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
529108407Srwatson	error = namei(&nd);
530150262Scsjp	vfslocked = NDHASGIANT(&nd);
531108407Srwatson	if (error == 0) {
532108407Srwatson		error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp);
533108407Srwatson		NDFREE(&nd, 0);
534108407Srwatson	}
535150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
536108407Srwatson	return (error);
537108407Srwatson}
538108407Srwatson
539108407Srwatson/*
540167211Srwatson * Given a file descriptor, check an ACL for it.
54154803Srwatson */
54254803Srwatsonint
54385582Srwatson__acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap)
54454803Srwatson{
54554803Srwatson	struct file *fp;
546150262Scsjp	int vfslocked, error;
54754803Srwatson
548107849Salfred	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
54982713Sdillon	if (error == 0) {
550150262Scsjp		vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
551116678Sphk		error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp);
55289306Salfred		fdrop(fp, td);
553150262Scsjp		VFS_UNLOCK_GIANT(vfslocked);
55482713Sdillon	}
55582713Sdillon	return (error);
55654803Srwatson}
557149811Scsjp
558191249Straszstruct acl *
559191249Straszacl_alloc(int flags)
560191249Strasz{
561191249Strasz	struct acl *aclp;
562191249Strasz
563191266Strasz	aclp = malloc(sizeof(*aclp), M_ACL, flags);
564192586Strasz	aclp->acl_maxcnt = ACL_MAX_ENTRIES;
565191249Strasz
566191249Strasz	return (aclp);
567191249Strasz}
568191249Strasz
569191249Straszvoid
570191249Straszacl_free(struct acl *aclp)
571191249Strasz{
572191249Strasz
573191266Strasz	free(aclp, M_ACL);
574191249Strasz}
575