vfs_acl.c revision 198877
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 198877 2009-11-04 08:25:58Z 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
95192586Strasz	if (source->acl_cnt < 0 || 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"
176192586Strasz * counterpart.  It's required for old (pre-NFS4 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;
310191249Strasz	error = VOP_ACLCHECK(vp, type, inkernelacl, td->td_ucred, td);
311191249Straszout:
312191249Strasz	acl_free(inkernelacl);
31354803Srwatson	return (error);
31454803Srwatson}
31554803Srwatson
31654803Srwatson/*
317165983Srwatson * syscalls -- convert the path/fd to a vnode, and call vacl_whatever.  Don't
318165983Srwatson * need to lock, as the vacl_ code will get/release any locks required.
31954803Srwatson */
32054803Srwatson
32154803Srwatson/*
32254803Srwatson * Given a file path, get an ACL for it
32354803Srwatson */
32454803Srwatsonint
32585582Srwatson__acl_get_file(struct thread *td, struct __acl_get_file_args *uap)
32654803Srwatson{
32754803Srwatson	struct nameidata nd;
328150262Scsjp	int vfslocked, error;
32954803Srwatson
330150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
33154803Srwatson	error = namei(&nd);
332150262Scsjp	vfslocked = NDHASGIANT(&nd);
33382713Sdillon	if (error == 0) {
334107855Salfred		error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp);
33582713Sdillon		NDFREE(&nd, 0);
33682713Sdillon	}
337150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
33854803Srwatson	return (error);
33954803Srwatson}
34054803Srwatson
34154803Srwatson/*
342108407Srwatson * Given a file path, get an ACL for it; don't follow links.
343108407Srwatson */
344108407Srwatsonint
345108407Srwatson__acl_get_link(struct thread *td, struct __acl_get_link_args *uap)
346108407Srwatson{
347108407Srwatson	struct nameidata nd;
348150262Scsjp	int vfslocked, error;
349108407Srwatson
350150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
351108407Srwatson	error = namei(&nd);
352150262Scsjp	vfslocked = NDHASGIANT(&nd);
353108407Srwatson	if (error == 0) {
354108407Srwatson		error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp);
355108407Srwatson		NDFREE(&nd, 0);
356108407Srwatson	}
357150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
358108407Srwatson	return (error);
359108407Srwatson}
360108407Srwatson
361108407Srwatson/*
362167211Srwatson * Given a file path, set an ACL for it.
36354803Srwatson */
36454803Srwatsonint
36585582Srwatson__acl_set_file(struct thread *td, struct __acl_set_file_args *uap)
36654803Srwatson{
36754803Srwatson	struct nameidata nd;
368150262Scsjp	int vfslocked, error;
36954803Srwatson
370150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
37154803Srwatson	error = namei(&nd);
372150262Scsjp	vfslocked = NDHASGIANT(&nd);
37382713Sdillon	if (error == 0) {
374107855Salfred		error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp);
37582713Sdillon		NDFREE(&nd, 0);
37682713Sdillon	}
377150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
37854803Srwatson	return (error);
37954803Srwatson}
38054803Srwatson
38154803Srwatson/*
382108407Srwatson * Given a file path, set an ACL for it; don't follow links.
383108407Srwatson */
384108407Srwatsonint
385108407Srwatson__acl_set_link(struct thread *td, struct __acl_set_link_args *uap)
386108407Srwatson{
387108407Srwatson	struct nameidata nd;
388150262Scsjp	int vfslocked, error;
389108407Srwatson
390150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
391108407Srwatson	error = namei(&nd);
392150262Scsjp	vfslocked = NDHASGIANT(&nd);
393108407Srwatson	if (error == 0) {
394108407Srwatson		error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp);
395108407Srwatson		NDFREE(&nd, 0);
396108407Srwatson	}
397150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
398108407Srwatson	return (error);
399108407Srwatson}
400108407Srwatson
401108407Srwatson/*
402167234Srwatson * Given a file descriptor, get an ACL for it.
40354803Srwatson */
40454803Srwatsonint
40585582Srwatson__acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap)
40654803Srwatson{
40754803Srwatson	struct file *fp;
408150262Scsjp	int vfslocked, error;
40954803Srwatson
410107849Salfred	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
41182713Sdillon	if (error == 0) {
412150262Scsjp		vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
413116678Sphk		error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp);
41489306Salfred		fdrop(fp, td);
415150262Scsjp		VFS_UNLOCK_GIANT(vfslocked);
41682713Sdillon	}
41782713Sdillon	return (error);
41854803Srwatson}
41954803Srwatson
42054803Srwatson/*
421167234Srwatson * Given a file descriptor, set an ACL for it.
42254803Srwatson */
42354803Srwatsonint
42485582Srwatson__acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap)
42554803Srwatson{
42654803Srwatson	struct file *fp;
427150262Scsjp	int vfslocked, error;
42854803Srwatson
429107849Salfred	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
43082713Sdillon	if (error == 0) {
431150262Scsjp		vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
432116678Sphk		error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp);
43389306Salfred		fdrop(fp, td);
434150262Scsjp		VFS_UNLOCK_GIANT(vfslocked);
43582713Sdillon	}
43682713Sdillon	return (error);
43754803Srwatson}
43854803Srwatson
43954803Srwatson/*
44054803Srwatson * Given a file path, delete an ACL from it.
44154803Srwatson */
44254803Srwatsonint
44385582Srwatson__acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap)
44454803Srwatson{
44554803Srwatson	struct nameidata nd;
446150262Scsjp	int vfslocked, error;
44754803Srwatson
448150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
44954803Srwatson	error = namei(&nd);
450150262Scsjp	vfslocked = NDHASGIANT(&nd);
45182713Sdillon	if (error == 0) {
452107849Salfred		error = vacl_delete(td, nd.ni_vp, uap->type);
45382713Sdillon		NDFREE(&nd, 0);
45482713Sdillon	}
455150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
45654803Srwatson	return (error);
45754803Srwatson}
45854803Srwatson
45954803Srwatson/*
460108407Srwatson * Given a file path, delete an ACL from it; don't follow links.
461108407Srwatson */
462108407Srwatsonint
463108407Srwatson__acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap)
464108407Srwatson{
465108407Srwatson	struct nameidata nd;
466150262Scsjp	int vfslocked, error;
467108407Srwatson
468150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
469108407Srwatson	error = namei(&nd);
470150262Scsjp	vfslocked = NDHASGIANT(&nd);
471108407Srwatson	if (error == 0) {
472108407Srwatson		error = vacl_delete(td, nd.ni_vp, uap->type);
473108407Srwatson		NDFREE(&nd, 0);
474108407Srwatson	}
475150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
476108407Srwatson	return (error);
477108407Srwatson}
478108407Srwatson
479108407Srwatson/*
48054803Srwatson * Given a file path, delete an ACL from it.
48154803Srwatson */
48254803Srwatsonint
48385582Srwatson__acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap)
48454803Srwatson{
48554803Srwatson	struct file *fp;
486150262Scsjp	int vfslocked, error;
48754803Srwatson
488107849Salfred	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
48982713Sdillon	if (error == 0) {
490150262Scsjp		vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
491116678Sphk		error = vacl_delete(td, fp->f_vnode, uap->type);
49289306Salfred		fdrop(fp, td);
493150262Scsjp		VFS_UNLOCK_GIANT(vfslocked);
49482713Sdillon	}
49554803Srwatson	return (error);
49654803Srwatson}
49754803Srwatson
49854803Srwatson/*
499167211Srwatson * Given a file path, check an ACL for it.
50054803Srwatson */
50154803Srwatsonint
50285582Srwatson__acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap)
50354803Srwatson{
504198875Strasz	struct nameidata nd;
505150262Scsjp	int vfslocked, error;
50654803Srwatson
507150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
50854803Srwatson	error = namei(&nd);
509150262Scsjp	vfslocked = NDHASGIANT(&nd);
51082713Sdillon	if (error == 0) {
511107855Salfred		error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp);
51282713Sdillon		NDFREE(&nd, 0);
51382713Sdillon	}
514150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
51554803Srwatson	return (error);
51654803Srwatson}
51754803Srwatson
51854803Srwatson/*
519108407Srwatson * Given a file path, check an ACL for it; don't follow links.
520108407Srwatson */
521108407Srwatsonint
522108407Srwatson__acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap)
523108407Srwatson{
524198877Strasz	struct nameidata nd;
525150262Scsjp	int vfslocked, error;
526108407Srwatson
527150262Scsjp	NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
528108407Srwatson	error = namei(&nd);
529150262Scsjp	vfslocked = NDHASGIANT(&nd);
530108407Srwatson	if (error == 0) {
531108407Srwatson		error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp);
532108407Srwatson		NDFREE(&nd, 0);
533108407Srwatson	}
534150262Scsjp	VFS_UNLOCK_GIANT(vfslocked);
535108407Srwatson	return (error);
536108407Srwatson}
537108407Srwatson
538108407Srwatson/*
539167211Srwatson * Given a file descriptor, check an ACL for it.
54054803Srwatson */
54154803Srwatsonint
54285582Srwatson__acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap)
54354803Srwatson{
54454803Srwatson	struct file *fp;
545150262Scsjp	int vfslocked, error;
54654803Srwatson
547107849Salfred	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
54882713Sdillon	if (error == 0) {
549150262Scsjp		vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
550116678Sphk		error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp);
55189306Salfred		fdrop(fp, td);
552150262Scsjp		VFS_UNLOCK_GIANT(vfslocked);
55382713Sdillon	}
55482713Sdillon	return (error);
55554803Srwatson}
556149811Scsjp
557191249Straszstruct acl *
558191249Straszacl_alloc(int flags)
559191249Strasz{
560191249Strasz	struct acl *aclp;
561191249Strasz
562191266Strasz	aclp = malloc(sizeof(*aclp), M_ACL, flags);
563192586Strasz	aclp->acl_maxcnt = ACL_MAX_ENTRIES;
564191249Strasz
565191249Strasz	return (aclp);
566191249Strasz}
567191249Strasz
568191249Straszvoid
569191249Straszacl_free(struct acl *aclp)
570191249Strasz{
571191249Strasz
572191266Strasz	free(aclp, M_ACL);
573191249Strasz}
574