vfs_extattr.c revision 165470
1/*-
2 * Copyright (c) 1989, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 4. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 *	@(#)vfs_syscalls.c	8.13 (Berkeley) 4/15/94
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/kern/vfs_extattr.c 164033 2006-11-06 13:42:10Z rwatson $");
39
40#include "opt_compat.h"
41#include "opt_mac.h"
42
43#include <sys/param.h>
44#include <sys/systm.h>
45#include <sys/bio.h>
46#include <sys/buf.h>
47#include <sys/sysent.h>
48#include <sys/malloc.h>
49#include <sys/mount.h>
50#include <sys/mutex.h>
51#include <sys/sysproto.h>
52#include <sys/namei.h>
53#include <sys/filedesc.h>
54#include <sys/kernel.h>
55#include <sys/fcntl.h>
56#include <sys/file.h>
57#include <sys/limits.h>
58#include <sys/linker.h>
59#include <sys/stat.h>
60#include <sys/sx.h>
61#include <sys/unistd.h>
62#include <sys/vnode.h>
63#include <sys/priv.h>
64#include <sys/proc.h>
65#include <sys/dirent.h>
66#include <sys/extattr.h>
67#include <sys/jail.h>
68#include <sys/syscallsubr.h>
69#include <sys/sysctl.h>
70
71#include <machine/stdarg.h>
72
73#include <security/audit/audit.h>
74#include <security/mac/mac_framework.h>
75
76#include <vm/vm.h>
77#include <vm/vm_object.h>
78#include <vm/vm_page.h>
79#include <vm/uma.h>
80
81static int chroot_refuse_vdir_fds(struct filedesc *fdp);
82static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
83static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
84static int setfmode(struct thread *td, struct vnode *, int);
85static int setfflags(struct thread *td, struct vnode *, int);
86static int setutimes(struct thread *td, struct vnode *,
87    const struct timespec *, int, int);
88static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
89    struct thread *td);
90
91static int extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
92    size_t nbytes, struct thread *td);
93
94int (*union_dircheckp)(struct thread *td, struct vnode **, struct file *);
95
96/*
97 * The module initialization routine for POSIX asynchronous I/O will
98 * set this to the version of AIO that it implements.  (Zero means
99 * that it is not implemented.)  This value is used here by pathconf()
100 * and in kern_descrip.c by fpathconf().
101 */
102int async_io_version;
103
104/*
105 * Sync each mounted filesystem.
106 */
107#ifndef _SYS_SYSPROTO_H_
108struct sync_args {
109	int     dummy;
110};
111#endif
112
113#ifdef DEBUG
114static int syncprt = 0;
115SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
116#endif
117
118/* ARGSUSED */
119int
120sync(td, uap)
121	struct thread *td;
122	struct sync_args *uap;
123{
124	struct mount *mp, *nmp;
125	int vfslocked;
126
127	mtx_lock(&mountlist_mtx);
128	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
129		if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
130			nmp = TAILQ_NEXT(mp, mnt_list);
131			continue;
132		}
133		vfslocked = VFS_LOCK_GIANT(mp);
134		if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
135		    vn_start_write(NULL, &mp, V_NOWAIT) == 0) {
136			MNT_ILOCK(mp);
137			mp->mnt_noasync++;
138			mp->mnt_kern_flag &= ~MNTK_ASYNC;
139			MNT_IUNLOCK(mp);
140			vfs_msync(mp, MNT_NOWAIT);
141			VFS_SYNC(mp, MNT_NOWAIT, td);
142			MNT_ILOCK(mp);
143			mp->mnt_noasync--;
144			if ((mp->mnt_flag & MNT_ASYNC) != 0 &&
145			    mp->mnt_noasync == 0)
146				mp->mnt_kern_flag |= MNTK_ASYNC;
147			MNT_IUNLOCK(mp);
148			vn_finished_write(mp);
149		}
150		VFS_UNLOCK_GIANT(vfslocked);
151		mtx_lock(&mountlist_mtx);
152		nmp = TAILQ_NEXT(mp, mnt_list);
153		vfs_unbusy(mp, td);
154	}
155	mtx_unlock(&mountlist_mtx);
156	return (0);
157}
158
159/* XXX PRISON: could be per prison flag */
160static int prison_quotas;
161#if 0
162SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
163#endif
164
165/*
166 * Change filesystem quotas.
167 *
168 * MP SAFE
169 */
170#ifndef _SYS_SYSPROTO_H_
171struct quotactl_args {
172	char *path;
173	int cmd;
174	int uid;
175	caddr_t arg;
176};
177#endif
178int
179quotactl(td, uap)
180	struct thread *td;
181	register struct quotactl_args /* {
182		char *path;
183		int cmd;
184		int uid;
185		caddr_t arg;
186	} */ *uap;
187{
188	struct mount *mp, *vmp;
189	int vfslocked;
190	int error;
191	struct nameidata nd;
192
193	AUDIT_ARG(cmd, uap->cmd);
194	AUDIT_ARG(uid, uap->uid);
195	if (jailed(td->td_ucred) && !prison_quotas)
196		return (EPERM);
197	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1,
198	   UIO_USERSPACE, uap->path, td);
199	if ((error = namei(&nd)) != 0)
200		return (error);
201	vfslocked = NDHASGIANT(&nd);
202	NDFREE(&nd, NDF_ONLY_PNBUF);
203	error = vn_start_write(nd.ni_vp, &vmp, V_WAIT | PCATCH);
204	mp = nd.ni_vp->v_mount;
205	vrele(nd.ni_vp);
206	if (error)
207		goto out;
208	error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, td);
209	vn_finished_write(vmp);
210out:
211	VFS_UNLOCK_GIANT(vfslocked);
212	return (error);
213}
214
215/*
216 * Get filesystem statistics.
217 */
218#ifndef _SYS_SYSPROTO_H_
219struct statfs_args {
220	char *path;
221	struct statfs *buf;
222};
223#endif
224int
225statfs(td, uap)
226	struct thread *td;
227	register struct statfs_args /* {
228		char *path;
229		struct statfs *buf;
230	} */ *uap;
231{
232	struct statfs sf;
233	int error;
234
235	error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
236	if (error == 0)
237		error = copyout(&sf, uap->buf, sizeof(sf));
238	return (error);
239}
240
241int
242kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
243    struct statfs *buf)
244{
245	struct mount *mp;
246	struct statfs *sp, sb;
247	int vfslocked;
248	int error;
249	struct nameidata nd;
250
251	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
252	    pathseg, path, td);
253	error = namei(&nd);
254	if (error)
255		return (error);
256	vfslocked = NDHASGIANT(&nd);
257	mp = nd.ni_vp->v_mount;
258	vfs_ref(mp);
259	NDFREE(&nd, NDF_ONLY_PNBUF);
260	vput(nd.ni_vp);
261#ifdef MAC
262	error = mac_check_mount_stat(td->td_ucred, mp);
263	if (error)
264		goto out;
265#endif
266	/*
267	 * Set these in case the underlying filesystem fails to do so.
268	 */
269	sp = &mp->mnt_stat;
270	sp->f_version = STATFS_VERSION;
271	sp->f_namemax = NAME_MAX;
272	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
273	error = VFS_STATFS(mp, sp, td);
274	if (error)
275		goto out;
276	if (priv_check(td, PRIV_VFS_GENERATION)) {
277		bcopy(sp, &sb, sizeof(sb));
278		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
279		prison_enforce_statfs(td->td_ucred, mp, &sb);
280		sp = &sb;
281	}
282	*buf = *sp;
283out:
284	vfs_rel(mp);
285	VFS_UNLOCK_GIANT(vfslocked);
286	if (mtx_owned(&Giant))
287		printf("statfs(%d): %s: %d\n", vfslocked, path, error);
288	return (error);
289}
290
291/*
292 * Get filesystem statistics.
293 */
294#ifndef _SYS_SYSPROTO_H_
295struct fstatfs_args {
296	int fd;
297	struct statfs *buf;
298};
299#endif
300int
301fstatfs(td, uap)
302	struct thread *td;
303	register struct fstatfs_args /* {
304		int fd;
305		struct statfs *buf;
306	} */ *uap;
307{
308	struct statfs sf;
309	int error;
310
311	error = kern_fstatfs(td, uap->fd, &sf);
312	if (error == 0)
313		error = copyout(&sf, uap->buf, sizeof(sf));
314	return (error);
315}
316
317int
318kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
319{
320	struct file *fp;
321	struct mount *mp;
322	struct statfs *sp, sb;
323	int vfslocked;
324	struct vnode *vp;
325	int error;
326
327	AUDIT_ARG(fd, fd);
328	error = getvnode(td->td_proc->p_fd, fd, &fp);
329	if (error)
330		return (error);
331	vp = fp->f_vnode;
332	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
333	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
334#ifdef AUDIT
335	AUDIT_ARG(vnode, vp, ARG_VNODE1);
336#endif
337	mp = vp->v_mount;
338	if (mp)
339		vfs_ref(mp);
340	VOP_UNLOCK(vp, 0, td);
341	fdrop(fp, td);
342	if (vp->v_iflag & VI_DOOMED) {
343		error = EBADF;
344		goto out;
345	}
346#ifdef MAC
347	error = mac_check_mount_stat(td->td_ucred, mp);
348	if (error)
349		goto out;
350#endif
351	/*
352	 * Set these in case the underlying filesystem fails to do so.
353	 */
354	sp = &mp->mnt_stat;
355	sp->f_version = STATFS_VERSION;
356	sp->f_namemax = NAME_MAX;
357	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
358	error = VFS_STATFS(mp, sp, td);
359	if (error)
360		goto out;
361	if (priv_check(td, PRIV_VFS_GENERATION)) {
362		bcopy(sp, &sb, sizeof(sb));
363		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
364		prison_enforce_statfs(td->td_ucred, mp, &sb);
365		sp = &sb;
366	}
367	*buf = *sp;
368out:
369	if (mp)
370		vfs_rel(mp);
371	VFS_UNLOCK_GIANT(vfslocked);
372	return (error);
373}
374
375/*
376 * Get statistics on all filesystems.
377 */
378#ifndef _SYS_SYSPROTO_H_
379struct getfsstat_args {
380	struct statfs *buf;
381	long bufsize;
382	int flags;
383};
384#endif
385int
386getfsstat(td, uap)
387	struct thread *td;
388	register struct getfsstat_args /* {
389		struct statfs *buf;
390		long bufsize;
391		int flags;
392	} */ *uap;
393{
394
395	return (kern_getfsstat(td, &uap->buf, uap->bufsize, UIO_USERSPACE,
396	    uap->flags));
397}
398
399/*
400 * If (bufsize > 0 && bufseg == UIO_SYSSPACE)
401 * 	The caller is responsible for freeing memory which will be allocated
402 *	in '*buf'.
403 */
404int
405kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
406    enum uio_seg bufseg, int flags)
407{
408	struct mount *mp, *nmp;
409	struct statfs *sfsp, *sp, sb;
410	size_t count, maxcount;
411	int vfslocked;
412	int error;
413
414	maxcount = bufsize / sizeof(struct statfs);
415	if (bufsize == 0)
416		sfsp = NULL;
417	else if (bufseg == UIO_USERSPACE)
418		sfsp = *buf;
419	else /* if (bufseg == UIO_SYSSPACE) */ {
420		count = 0;
421		mtx_lock(&mountlist_mtx);
422		TAILQ_FOREACH(mp, &mountlist, mnt_list) {
423			count++;
424		}
425		mtx_unlock(&mountlist_mtx);
426		if (maxcount > count)
427			maxcount = count;
428		sfsp = *buf = malloc(maxcount * sizeof(struct statfs), M_TEMP,
429		    M_WAITOK);
430	}
431	count = 0;
432	mtx_lock(&mountlist_mtx);
433	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
434		if (prison_canseemount(td->td_ucred, mp) != 0) {
435			nmp = TAILQ_NEXT(mp, mnt_list);
436			continue;
437		}
438#ifdef MAC
439		if (mac_check_mount_stat(td->td_ucred, mp) != 0) {
440			nmp = TAILQ_NEXT(mp, mnt_list);
441			continue;
442		}
443#endif
444		if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) {
445			nmp = TAILQ_NEXT(mp, mnt_list);
446			continue;
447		}
448		vfslocked = VFS_LOCK_GIANT(mp);
449		if (sfsp && count < maxcount) {
450			sp = &mp->mnt_stat;
451			/*
452			 * Set these in case the underlying filesystem
453			 * fails to do so.
454			 */
455			sp->f_version = STATFS_VERSION;
456			sp->f_namemax = NAME_MAX;
457			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
458			/*
459			 * If MNT_NOWAIT or MNT_LAZY is specified, do not
460			 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
461			 * overrides MNT_WAIT.
462			 */
463			if (((flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
464			    (flags & MNT_WAIT)) &&
465			    (error = VFS_STATFS(mp, sp, td))) {
466				VFS_UNLOCK_GIANT(vfslocked);
467				mtx_lock(&mountlist_mtx);
468				nmp = TAILQ_NEXT(mp, mnt_list);
469				vfs_unbusy(mp, td);
470				continue;
471			}
472			if (priv_check(td, PRIV_VFS_GENERATION)) {
473				bcopy(sp, &sb, sizeof(sb));
474				sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
475				prison_enforce_statfs(td->td_ucred, mp, &sb);
476				sp = &sb;
477			}
478			if (bufseg == UIO_SYSSPACE)
479				bcopy(sp, sfsp, sizeof(*sp));
480			else /* if (bufseg == UIO_USERSPACE) */ {
481				error = copyout(sp, sfsp, sizeof(*sp));
482				if (error) {
483					vfs_unbusy(mp, td);
484					VFS_UNLOCK_GIANT(vfslocked);
485					return (error);
486				}
487			}
488			sfsp++;
489		}
490		VFS_UNLOCK_GIANT(vfslocked);
491		count++;
492		mtx_lock(&mountlist_mtx);
493		nmp = TAILQ_NEXT(mp, mnt_list);
494		vfs_unbusy(mp, td);
495	}
496	mtx_unlock(&mountlist_mtx);
497	if (sfsp && count > maxcount)
498		td->td_retval[0] = maxcount;
499	else
500		td->td_retval[0] = count;
501	return (0);
502}
503
504#ifdef COMPAT_FREEBSD4
505/*
506 * Get old format filesystem statistics.
507 */
508static void cvtstatfs(struct statfs *, struct ostatfs *);
509
510#ifndef _SYS_SYSPROTO_H_
511struct freebsd4_statfs_args {
512	char *path;
513	struct ostatfs *buf;
514};
515#endif
516int
517freebsd4_statfs(td, uap)
518	struct thread *td;
519	struct freebsd4_statfs_args /* {
520		char *path;
521		struct ostatfs *buf;
522	} */ *uap;
523{
524	struct ostatfs osb;
525	struct statfs sf;
526	int error;
527
528	error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
529	if (error)
530		return (error);
531	cvtstatfs(&sf, &osb);
532	return (copyout(&osb, uap->buf, sizeof(osb)));
533}
534
535/*
536 * Get filesystem statistics.
537 */
538#ifndef _SYS_SYSPROTO_H_
539struct freebsd4_fstatfs_args {
540	int fd;
541	struct ostatfs *buf;
542};
543#endif
544int
545freebsd4_fstatfs(td, uap)
546	struct thread *td;
547	struct freebsd4_fstatfs_args /* {
548		int fd;
549		struct ostatfs *buf;
550	} */ *uap;
551{
552	struct ostatfs osb;
553	struct statfs sf;
554	int error;
555
556	error = kern_fstatfs(td, uap->fd, &sf);
557	if (error)
558		return (error);
559	cvtstatfs(&sf, &osb);
560	return (copyout(&osb, uap->buf, sizeof(osb)));
561}
562
563/*
564 * Get statistics on all filesystems.
565 */
566#ifndef _SYS_SYSPROTO_H_
567struct freebsd4_getfsstat_args {
568	struct ostatfs *buf;
569	long bufsize;
570	int flags;
571};
572#endif
573int
574freebsd4_getfsstat(td, uap)
575	struct thread *td;
576	register struct freebsd4_getfsstat_args /* {
577		struct ostatfs *buf;
578		long bufsize;
579		int flags;
580	} */ *uap;
581{
582	struct statfs *buf, *sp;
583	struct ostatfs osb;
584	size_t count, size;
585	int error;
586
587	count = uap->bufsize / sizeof(struct ostatfs);
588	size = count * sizeof(struct statfs);
589	error = kern_getfsstat(td, &buf, size, UIO_SYSSPACE, uap->flags);
590	if (size > 0) {
591		count = td->td_retval[0];
592		sp = buf;
593		while (count > 0 && error == 0) {
594			cvtstatfs(sp, &osb);
595			error = copyout(&osb, uap->buf, sizeof(osb));
596			sp++;
597			uap->buf++;
598			count--;
599		}
600		free(buf, M_TEMP);
601	}
602	return (error);
603}
604
605/*
606 * Implement fstatfs() for (NFS) file handles.
607 */
608#ifndef _SYS_SYSPROTO_H_
609struct freebsd4_fhstatfs_args {
610	struct fhandle *u_fhp;
611	struct ostatfs *buf;
612};
613#endif
614int
615freebsd4_fhstatfs(td, uap)
616	struct thread *td;
617	struct freebsd4_fhstatfs_args /* {
618		struct fhandle *u_fhp;
619		struct ostatfs *buf;
620	} */ *uap;
621{
622	struct ostatfs osb;
623	struct statfs sf;
624	fhandle_t fh;
625	int error;
626
627	error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
628	if (error)
629		return (error);
630	error = kern_fhstatfs(td, fh, &sf);
631	if (error)
632		return (error);
633	cvtstatfs(&sf, &osb);
634	return (copyout(&osb, uap->buf, sizeof(osb)));
635}
636
637/*
638 * Convert a new format statfs structure to an old format statfs structure.
639 */
640static void
641cvtstatfs(nsp, osp)
642	struct statfs *nsp;
643	struct ostatfs *osp;
644{
645
646	bzero(osp, sizeof(*osp));
647	osp->f_bsize = MIN(nsp->f_bsize, LONG_MAX);
648	osp->f_iosize = MIN(nsp->f_iosize, LONG_MAX);
649	osp->f_blocks = MIN(nsp->f_blocks, LONG_MAX);
650	osp->f_bfree = MIN(nsp->f_bfree, LONG_MAX);
651	osp->f_bavail = MIN(nsp->f_bavail, LONG_MAX);
652	osp->f_files = MIN(nsp->f_files, LONG_MAX);
653	osp->f_ffree = MIN(nsp->f_ffree, LONG_MAX);
654	osp->f_owner = nsp->f_owner;
655	osp->f_type = nsp->f_type;
656	osp->f_flags = nsp->f_flags;
657	osp->f_syncwrites = MIN(nsp->f_syncwrites, LONG_MAX);
658	osp->f_asyncwrites = MIN(nsp->f_asyncwrites, LONG_MAX);
659	osp->f_syncreads = MIN(nsp->f_syncreads, LONG_MAX);
660	osp->f_asyncreads = MIN(nsp->f_asyncreads, LONG_MAX);
661	strlcpy(osp->f_fstypename, nsp->f_fstypename,
662	    MIN(MFSNAMELEN, OMFSNAMELEN));
663	strlcpy(osp->f_mntonname, nsp->f_mntonname,
664	    MIN(MNAMELEN, OMNAMELEN));
665	strlcpy(osp->f_mntfromname, nsp->f_mntfromname,
666	    MIN(MNAMELEN, OMNAMELEN));
667	osp->f_fsid = nsp->f_fsid;
668}
669#endif /* COMPAT_FREEBSD4 */
670
671/*
672 * Change current working directory to a given file descriptor.
673 */
674#ifndef _SYS_SYSPROTO_H_
675struct fchdir_args {
676	int	fd;
677};
678#endif
679int
680fchdir(td, uap)
681	struct thread *td;
682	struct fchdir_args /* {
683		int fd;
684	} */ *uap;
685{
686	register struct filedesc *fdp = td->td_proc->p_fd;
687	struct vnode *vp, *tdp, *vpold;
688	struct mount *mp;
689	struct file *fp;
690	int vfslocked;
691	int error;
692
693	AUDIT_ARG(fd, uap->fd);
694	if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
695		return (error);
696	vp = fp->f_vnode;
697	VREF(vp);
698	fdrop(fp, td);
699	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
700	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
701	AUDIT_ARG(vnode, vp, ARG_VNODE1);
702	error = change_dir(vp, td);
703	while (!error && (mp = vp->v_mountedhere) != NULL) {
704		int tvfslocked;
705		if (vfs_busy(mp, 0, 0, td))
706			continue;
707		tvfslocked = VFS_LOCK_GIANT(mp);
708		error = VFS_ROOT(mp, LK_EXCLUSIVE, &tdp, td);
709		vfs_unbusy(mp, td);
710		if (error) {
711			VFS_UNLOCK_GIANT(tvfslocked);
712			break;
713		}
714		vput(vp);
715		VFS_UNLOCK_GIANT(vfslocked);
716		vp = tdp;
717		vfslocked = tvfslocked;
718	}
719	if (error) {
720		vput(vp);
721		VFS_UNLOCK_GIANT(vfslocked);
722		return (error);
723	}
724	VOP_UNLOCK(vp, 0, td);
725	VFS_UNLOCK_GIANT(vfslocked);
726	FILEDESC_LOCK_FAST(fdp);
727	vpold = fdp->fd_cdir;
728	fdp->fd_cdir = vp;
729	FILEDESC_UNLOCK_FAST(fdp);
730	vfslocked = VFS_LOCK_GIANT(vpold->v_mount);
731	vrele(vpold);
732	VFS_UNLOCK_GIANT(vfslocked);
733	return (0);
734}
735
736/*
737 * Change current working directory (``.'').
738 */
739#ifndef _SYS_SYSPROTO_H_
740struct chdir_args {
741	char	*path;
742};
743#endif
744int
745chdir(td, uap)
746	struct thread *td;
747	struct chdir_args /* {
748		char *path;
749	} */ *uap;
750{
751
752	return (kern_chdir(td, uap->path, UIO_USERSPACE));
753}
754
755int
756kern_chdir(struct thread *td, char *path, enum uio_seg pathseg)
757{
758	register struct filedesc *fdp = td->td_proc->p_fd;
759	int error;
760	struct nameidata nd;
761	struct vnode *vp;
762	int vfslocked;
763
764	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1 | MPSAFE,
765	    pathseg, path, td);
766	if ((error = namei(&nd)) != 0)
767		return (error);
768	vfslocked = NDHASGIANT(&nd);
769	if ((error = change_dir(nd.ni_vp, td)) != 0) {
770		vput(nd.ni_vp);
771		VFS_UNLOCK_GIANT(vfslocked);
772		NDFREE(&nd, NDF_ONLY_PNBUF);
773		return (error);
774	}
775	VOP_UNLOCK(nd.ni_vp, 0, td);
776	VFS_UNLOCK_GIANT(vfslocked);
777	NDFREE(&nd, NDF_ONLY_PNBUF);
778	FILEDESC_LOCK_FAST(fdp);
779	vp = fdp->fd_cdir;
780	fdp->fd_cdir = nd.ni_vp;
781	FILEDESC_UNLOCK_FAST(fdp);
782	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
783	vrele(vp);
784	VFS_UNLOCK_GIANT(vfslocked);
785	return (0);
786}
787
788/*
789 * Helper function for raised chroot(2) security function:  Refuse if
790 * any filedescriptors are open directories.
791 */
792static int
793chroot_refuse_vdir_fds(fdp)
794	struct filedesc *fdp;
795{
796	struct vnode *vp;
797	struct file *fp;
798	int fd;
799
800	FILEDESC_LOCK_ASSERT(fdp, MA_OWNED);
801	for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
802		fp = fget_locked(fdp, fd);
803		if (fp == NULL)
804			continue;
805		if (fp->f_type == DTYPE_VNODE) {
806			vp = fp->f_vnode;
807			if (vp->v_type == VDIR)
808				return (EPERM);
809		}
810	}
811	return (0);
812}
813
814/*
815 * This sysctl determines if we will allow a process to chroot(2) if it
816 * has a directory open:
817 *	0: disallowed for all processes.
818 *	1: allowed for processes that were not already chroot(2)'ed.
819 *	2: allowed for all processes.
820 */
821
822static int chroot_allow_open_directories = 1;
823
824SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
825     &chroot_allow_open_directories, 0, "");
826
827/*
828 * Change notion of root (``/'') directory.
829 */
830#ifndef _SYS_SYSPROTO_H_
831struct chroot_args {
832	char	*path;
833};
834#endif
835int
836chroot(td, uap)
837	struct thread *td;
838	struct chroot_args /* {
839		char *path;
840	} */ *uap;
841{
842	int error;
843	struct nameidata nd;
844	int vfslocked;
845
846	error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT,
847	    SUSER_ALLOWJAIL);
848	if (error)
849		return (error);
850	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
851	    UIO_USERSPACE, uap->path, td);
852	error = namei(&nd);
853	if (error)
854		goto error;
855	vfslocked = NDHASGIANT(&nd);
856	if ((error = change_dir(nd.ni_vp, td)) != 0)
857		goto e_vunlock;
858#ifdef MAC
859	if ((error = mac_check_vnode_chroot(td->td_ucred, nd.ni_vp)))
860		goto e_vunlock;
861#endif
862	VOP_UNLOCK(nd.ni_vp, 0, td);
863	error = change_root(nd.ni_vp, td);
864	vrele(nd.ni_vp);
865	VFS_UNLOCK_GIANT(vfslocked);
866	NDFREE(&nd, NDF_ONLY_PNBUF);
867	return (error);
868e_vunlock:
869	vput(nd.ni_vp);
870	VFS_UNLOCK_GIANT(vfslocked);
871error:
872	NDFREE(&nd, NDF_ONLY_PNBUF);
873	return (error);
874}
875
876/*
877 * Common routine for chroot and chdir.  Callers must provide a locked vnode
878 * instance.
879 */
880int
881change_dir(vp, td)
882	struct vnode *vp;
883	struct thread *td;
884{
885	int error;
886
887	ASSERT_VOP_LOCKED(vp, "change_dir(): vp not locked");
888	if (vp->v_type != VDIR)
889		return (ENOTDIR);
890#ifdef MAC
891	error = mac_check_vnode_chdir(td->td_ucred, vp);
892	if (error)
893		return (error);
894#endif
895	error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
896	return (error);
897}
898
899/*
900 * Common routine for kern_chroot() and jail_attach().  The caller is
901 * responsible for invoking priv_check() and mac_check_chroot() to authorize
902 * this operation.
903 */
904int
905change_root(vp, td)
906	struct vnode *vp;
907	struct thread *td;
908{
909	struct filedesc *fdp;
910	struct vnode *oldvp;
911	int vfslocked;
912	int error;
913
914	VFS_ASSERT_GIANT(vp->v_mount);
915	fdp = td->td_proc->p_fd;
916	FILEDESC_LOCK(fdp);
917	if (chroot_allow_open_directories == 0 ||
918	    (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
919		error = chroot_refuse_vdir_fds(fdp);
920		if (error) {
921			FILEDESC_UNLOCK(fdp);
922			return (error);
923		}
924	}
925	oldvp = fdp->fd_rdir;
926	fdp->fd_rdir = vp;
927	VREF(fdp->fd_rdir);
928	if (!fdp->fd_jdir) {
929		fdp->fd_jdir = vp;
930		VREF(fdp->fd_jdir);
931	}
932	FILEDESC_UNLOCK(fdp);
933	vfslocked = VFS_LOCK_GIANT(oldvp->v_mount);
934	vrele(oldvp);
935	VFS_UNLOCK_GIANT(vfslocked);
936	return (0);
937}
938
939/*
940 * Check permissions, allocate an open file structure,
941 * and call the device open routine if any.
942 *
943 * MP SAFE
944 */
945#ifndef _SYS_SYSPROTO_H_
946struct open_args {
947	char	*path;
948	int	flags;
949	int	mode;
950};
951#endif
952int
953open(td, uap)
954	struct thread *td;
955	register struct open_args /* {
956		char *path;
957		int flags;
958		int mode;
959	} */ *uap;
960{
961
962	return kern_open(td, uap->path, UIO_USERSPACE, uap->flags, uap->mode);
963}
964
965int
966kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags,
967    int mode)
968{
969	struct proc *p = td->td_proc;
970	struct filedesc *fdp = p->p_fd;
971	struct file *fp;
972	struct vnode *vp;
973	struct vattr vat;
974	struct mount *mp;
975	int cmode;
976	struct file *nfp;
977	int type, indx, error;
978	struct flock lf;
979	struct nameidata nd;
980	int vfslocked;
981
982	AUDIT_ARG(fflags, flags);
983	AUDIT_ARG(mode, mode);
984	if ((flags & O_ACCMODE) == O_ACCMODE)
985		return (EINVAL);
986	flags = FFLAGS(flags);
987	error = falloc(td, &nfp, &indx);
988	if (error)
989		return (error);
990	/* An extra reference on `nfp' has been held for us by falloc(). */
991	fp = nfp;
992	cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
993	NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1 | MPSAFE, pathseg, path, td);
994	td->td_dupfd = -1;		/* XXX check for fdopen */
995	error = vn_open(&nd, &flags, cmode, indx);
996	if (error) {
997		/*
998		 * If the vn_open replaced the method vector, something
999		 * wonderous happened deep below and we just pass it up
1000		 * pretending we know what we do.
1001		 */
1002		if (error == ENXIO && fp->f_ops != &badfileops) {
1003			fdrop(fp, td);
1004			td->td_retval[0] = indx;
1005			return (0);
1006		}
1007
1008		/*
1009		 * release our own reference
1010		 */
1011		fdrop(fp, td);
1012
1013		/*
1014		 * handle special fdopen() case.  bleh.  dupfdopen() is
1015		 * responsible for dropping the old contents of ofiles[indx]
1016		 * if it succeeds.
1017		 */
1018		if ((error == ENODEV || error == ENXIO) &&
1019		    td->td_dupfd >= 0 &&		/* XXX from fdopen */
1020		    (error =
1021			dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
1022			td->td_retval[0] = indx;
1023			return (0);
1024		}
1025		/*
1026		 * Clean up the descriptor, but only if another thread hadn't
1027		 * replaced or closed it.
1028		 */
1029		fdclose(fdp, fp, indx, td);
1030
1031		if (error == ERESTART)
1032			error = EINTR;
1033		return (error);
1034	}
1035	td->td_dupfd = 0;
1036	vfslocked = NDHASGIANT(&nd);
1037	NDFREE(&nd, NDF_ONLY_PNBUF);
1038	vp = nd.ni_vp;
1039
1040	/*
1041	 * There should be 2 references on the file, one from the descriptor
1042	 * table, and one for us.
1043	 *
1044	 * Handle the case where someone closed the file (via its file
1045	 * descriptor) while we were blocked.  The end result should look
1046	 * like opening the file succeeded but it was immediately closed.
1047	 * We call vn_close() manually because we haven't yet hooked up
1048	 * the various 'struct file' fields.
1049	 */
1050	FILEDESC_LOCK(fdp);
1051	FILE_LOCK(fp);
1052	if (fp->f_count == 1) {
1053		mp = vp->v_mount;
1054		KASSERT(fdp->fd_ofiles[indx] != fp,
1055		    ("Open file descriptor lost all refs"));
1056		FILE_UNLOCK(fp);
1057		FILEDESC_UNLOCK(fdp);
1058		VOP_UNLOCK(vp, 0, td);
1059		vn_close(vp, flags & FMASK, fp->f_cred, td);
1060		VFS_UNLOCK_GIANT(vfslocked);
1061		fdrop(fp, td);
1062		td->td_retval[0] = indx;
1063		return (0);
1064	}
1065	fp->f_vnode = vp;
1066	if (fp->f_data == NULL)
1067		fp->f_data = vp;
1068	fp->f_flag = flags & FMASK;
1069	if (fp->f_ops == &badfileops)
1070		fp->f_ops = &vnops;
1071	fp->f_seqcount = 1;
1072	fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
1073	FILE_UNLOCK(fp);
1074	FILEDESC_UNLOCK(fdp);
1075
1076	VOP_UNLOCK(vp, 0, td);
1077	if (flags & (O_EXLOCK | O_SHLOCK)) {
1078		lf.l_whence = SEEK_SET;
1079		lf.l_start = 0;
1080		lf.l_len = 0;
1081		if (flags & O_EXLOCK)
1082			lf.l_type = F_WRLCK;
1083		else
1084			lf.l_type = F_RDLCK;
1085		type = F_FLOCK;
1086		if ((flags & FNONBLOCK) == 0)
1087			type |= F_WAIT;
1088		if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
1089			    type)) != 0)
1090			goto bad;
1091		fp->f_flag |= FHASLOCK;
1092	}
1093	if (flags & O_TRUNC) {
1094		if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
1095			goto bad;
1096		VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1097		VATTR_NULL(&vat);
1098		vat.va_size = 0;
1099		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1100#ifdef MAC
1101		error = mac_check_vnode_write(td->td_ucred, fp->f_cred, vp);
1102		if (error == 0)
1103#endif
1104			error = VOP_SETATTR(vp, &vat, td->td_ucred, td);
1105		VOP_UNLOCK(vp, 0, td);
1106		vn_finished_write(mp);
1107		if (error)
1108			goto bad;
1109	}
1110	VFS_UNLOCK_GIANT(vfslocked);
1111	/*
1112	 * Release our private reference, leaving the one associated with
1113	 * the descriptor table intact.
1114	 */
1115	fdrop(fp, td);
1116	td->td_retval[0] = indx;
1117	return (0);
1118bad:
1119	VFS_UNLOCK_GIANT(vfslocked);
1120	fdclose(fdp, fp, indx, td);
1121	fdrop(fp, td);
1122	return (error);
1123}
1124
1125#ifdef COMPAT_43
1126/*
1127 * Create a file.
1128 *
1129 * MP SAFE
1130 */
1131#ifndef _SYS_SYSPROTO_H_
1132struct ocreat_args {
1133	char	*path;
1134	int	mode;
1135};
1136#endif
1137int
1138ocreat(td, uap)
1139	struct thread *td;
1140	register struct ocreat_args /* {
1141		char *path;
1142		int mode;
1143	} */ *uap;
1144{
1145
1146	return (kern_open(td, uap->path, UIO_USERSPACE,
1147	    O_WRONLY | O_CREAT | O_TRUNC, uap->mode));
1148}
1149#endif /* COMPAT_43 */
1150
1151/*
1152 * Create a special file.
1153 */
1154#ifndef _SYS_SYSPROTO_H_
1155struct mknod_args {
1156	char	*path;
1157	int	mode;
1158	int	dev;
1159};
1160#endif
1161int
1162mknod(td, uap)
1163	struct thread *td;
1164	register struct mknod_args /* {
1165		char *path;
1166		int mode;
1167		int dev;
1168	} */ *uap;
1169{
1170
1171	return (kern_mknod(td, uap->path, UIO_USERSPACE, uap->mode, uap->dev));
1172}
1173
1174int
1175kern_mknod(struct thread *td, char *path, enum uio_seg pathseg, int mode,
1176    int dev)
1177{
1178	struct vnode *vp;
1179	struct mount *mp;
1180	struct vattr vattr;
1181	int error;
1182	int whiteout = 0;
1183	struct nameidata nd;
1184	int vfslocked;
1185
1186	AUDIT_ARG(mode, mode);
1187	AUDIT_ARG(dev, dev);
1188	switch (mode & S_IFMT) {
1189	case S_IFCHR:
1190	case S_IFBLK:
1191		error = priv_check(td, PRIV_VFS_MKNOD_DEV);
1192		break;
1193	case S_IFMT:
1194		error = priv_check(td, PRIV_VFS_MKNOD_BAD);
1195		break;
1196	case S_IFWHT:
1197		error = priv_check(td, PRIV_VFS_MKNOD_WHT);
1198		break;
1199	default:
1200		error = EINVAL;
1201		break;
1202	}
1203	if (error)
1204		return (error);
1205restart:
1206	bwillwrite();
1207	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
1208	    pathseg, path, td);
1209	if ((error = namei(&nd)) != 0)
1210		return (error);
1211	vfslocked = NDHASGIANT(&nd);
1212	vp = nd.ni_vp;
1213	if (vp != NULL) {
1214		NDFREE(&nd, NDF_ONLY_PNBUF);
1215		if (vp == nd.ni_dvp)
1216			vrele(nd.ni_dvp);
1217		else
1218			vput(nd.ni_dvp);
1219		vrele(vp);
1220		VFS_UNLOCK_GIANT(vfslocked);
1221		return (EEXIST);
1222	} else {
1223		VATTR_NULL(&vattr);
1224		FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1225		vattr.va_mode = (mode & ALLPERMS) &
1226		    ~td->td_proc->p_fd->fd_cmask;
1227		FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1228		vattr.va_rdev = dev;
1229		whiteout = 0;
1230
1231		switch (mode & S_IFMT) {
1232		case S_IFMT:	/* used by badsect to flag bad sectors */
1233			vattr.va_type = VBAD;
1234			break;
1235		case S_IFCHR:
1236			vattr.va_type = VCHR;
1237			break;
1238		case S_IFBLK:
1239			vattr.va_type = VBLK;
1240			break;
1241		case S_IFWHT:
1242			whiteout = 1;
1243			break;
1244		default:
1245			panic("kern_mknod: invalid mode");
1246		}
1247	}
1248	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1249		NDFREE(&nd, NDF_ONLY_PNBUF);
1250		vput(nd.ni_dvp);
1251		VFS_UNLOCK_GIANT(vfslocked);
1252		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1253			return (error);
1254		goto restart;
1255	}
1256#ifdef MAC
1257	if (error == 0 && !whiteout)
1258		error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp,
1259		    &nd.ni_cnd, &vattr);
1260#endif
1261	if (!error) {
1262		VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1263		if (whiteout)
1264			error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
1265		else {
1266			error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
1267						&nd.ni_cnd, &vattr);
1268			if (error == 0)
1269				vput(nd.ni_vp);
1270		}
1271	}
1272	NDFREE(&nd, NDF_ONLY_PNBUF);
1273	vput(nd.ni_dvp);
1274	vn_finished_write(mp);
1275	VFS_UNLOCK_GIANT(vfslocked);
1276	return (error);
1277}
1278
1279/*
1280 * Create a named pipe.
1281 */
1282#ifndef _SYS_SYSPROTO_H_
1283struct mkfifo_args {
1284	char	*path;
1285	int	mode;
1286};
1287#endif
1288int
1289mkfifo(td, uap)
1290	struct thread *td;
1291	register struct mkfifo_args /* {
1292		char *path;
1293		int mode;
1294	} */ *uap;
1295{
1296
1297	return (kern_mkfifo(td, uap->path, UIO_USERSPACE, uap->mode));
1298}
1299
1300int
1301kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg, int mode)
1302{
1303	struct mount *mp;
1304	struct vattr vattr;
1305	int error;
1306	struct nameidata nd;
1307	int vfslocked;
1308
1309	AUDIT_ARG(mode, mode);
1310restart:
1311	bwillwrite();
1312	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
1313	    pathseg, path, td);
1314	if ((error = namei(&nd)) != 0)
1315		return (error);
1316	vfslocked = NDHASGIANT(&nd);
1317	if (nd.ni_vp != NULL) {
1318		NDFREE(&nd, NDF_ONLY_PNBUF);
1319		if (nd.ni_vp == nd.ni_dvp)
1320			vrele(nd.ni_dvp);
1321		else
1322			vput(nd.ni_dvp);
1323		vrele(nd.ni_vp);
1324		VFS_UNLOCK_GIANT(vfslocked);
1325		return (EEXIST);
1326	}
1327	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1328		NDFREE(&nd, NDF_ONLY_PNBUF);
1329		vput(nd.ni_dvp);
1330		VFS_UNLOCK_GIANT(vfslocked);
1331		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1332			return (error);
1333		goto restart;
1334	}
1335	VATTR_NULL(&vattr);
1336	vattr.va_type = VFIFO;
1337	FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1338	vattr.va_mode = (mode & ALLPERMS) & ~td->td_proc->p_fd->fd_cmask;
1339	FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1340#ifdef MAC
1341	error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1342	    &vattr);
1343	if (error)
1344		goto out;
1345#endif
1346	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1347	error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
1348	if (error == 0)
1349		vput(nd.ni_vp);
1350#ifdef MAC
1351out:
1352#endif
1353	vput(nd.ni_dvp);
1354	vn_finished_write(mp);
1355	VFS_UNLOCK_GIANT(vfslocked);
1356	NDFREE(&nd, NDF_ONLY_PNBUF);
1357	return (error);
1358}
1359
1360/*
1361 * Make a hard file link.
1362 */
1363#ifndef _SYS_SYSPROTO_H_
1364struct link_args {
1365	char	*path;
1366	char	*link;
1367};
1368#endif
1369int
1370link(td, uap)
1371	struct thread *td;
1372	register struct link_args /* {
1373		char *path;
1374		char *link;
1375	} */ *uap;
1376{
1377	int error;
1378
1379	error = kern_link(td, uap->path, uap->link, UIO_USERSPACE);
1380	return (error);
1381}
1382
1383static int hardlink_check_uid = 0;
1384SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
1385    &hardlink_check_uid, 0,
1386    "Unprivileged processes cannot create hard links to files owned by other "
1387    "users");
1388static int hardlink_check_gid = 0;
1389SYSCTL_INT(_security_bsd, OID_AUTO, hardlink_check_gid, CTLFLAG_RW,
1390    &hardlink_check_gid, 0,
1391    "Unprivileged processes cannot create hard links to files owned by other "
1392    "groups");
1393
1394static int
1395can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
1396{
1397	struct vattr va;
1398	int error;
1399
1400	if (!hardlink_check_uid && !hardlink_check_gid)
1401		return (0);
1402
1403	error = VOP_GETATTR(vp, &va, cred, td);
1404	if (error != 0)
1405		return (error);
1406
1407	if (hardlink_check_uid && cred->cr_uid != va.va_uid) {
1408		error = priv_check_cred(cred, PRIV_VFS_LINK,
1409		    SUSER_ALLOWJAIL);
1410		if (error)
1411			return (error);
1412	}
1413
1414	if (hardlink_check_gid && !groupmember(va.va_gid, cred)) {
1415		error = priv_check_cred(cred, PRIV_VFS_LINK,
1416		    SUSER_ALLOWJAIL);
1417		if (error)
1418			return (error);
1419	}
1420
1421	return (0);
1422}
1423
1424int
1425kern_link(struct thread *td, char *path, char *link, enum uio_seg segflg)
1426{
1427	struct vnode *vp;
1428	struct mount *mp;
1429	struct nameidata nd;
1430	int vfslocked;
1431	int lvfslocked;
1432	int error;
1433
1434	bwillwrite();
1435	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, segflg, path, td);
1436	if ((error = namei(&nd)) != 0)
1437		return (error);
1438	vfslocked = NDHASGIANT(&nd);
1439	NDFREE(&nd, NDF_ONLY_PNBUF);
1440	vp = nd.ni_vp;
1441	if (vp->v_type == VDIR) {
1442		vrele(vp);
1443		VFS_UNLOCK_GIANT(vfslocked);
1444		return (EPERM);		/* POSIX */
1445	}
1446	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
1447		vrele(vp);
1448		VFS_UNLOCK_GIANT(vfslocked);
1449		return (error);
1450	}
1451	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE2,
1452	    segflg, link, td);
1453	if ((error = namei(&nd)) == 0) {
1454		lvfslocked = NDHASGIANT(&nd);
1455		if (nd.ni_vp != NULL) {
1456			if (nd.ni_dvp == nd.ni_vp)
1457				vrele(nd.ni_dvp);
1458			else
1459				vput(nd.ni_dvp);
1460			vrele(nd.ni_vp);
1461			error = EEXIST;
1462		} else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td))
1463		    == 0) {
1464			VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1465			VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
1466			error = can_hardlink(vp, td, td->td_ucred);
1467			if (error == 0)
1468#ifdef MAC
1469				error = mac_check_vnode_link(td->td_ucred,
1470				    nd.ni_dvp, vp, &nd.ni_cnd);
1471			if (error == 0)
1472#endif
1473				error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1474			VOP_UNLOCK(vp, 0, td);
1475			vput(nd.ni_dvp);
1476		}
1477		NDFREE(&nd, NDF_ONLY_PNBUF);
1478		VFS_UNLOCK_GIANT(lvfslocked);
1479	}
1480	vrele(vp);
1481	vn_finished_write(mp);
1482	VFS_UNLOCK_GIANT(vfslocked);
1483	return (error);
1484}
1485
1486/*
1487 * Make a symbolic link.
1488 */
1489#ifndef _SYS_SYSPROTO_H_
1490struct symlink_args {
1491	char	*path;
1492	char	*link;
1493};
1494#endif
1495int
1496symlink(td, uap)
1497	struct thread *td;
1498	register struct symlink_args /* {
1499		char *path;
1500		char *link;
1501	} */ *uap;
1502{
1503
1504	return (kern_symlink(td, uap->path, uap->link, UIO_USERSPACE));
1505}
1506
1507int
1508kern_symlink(struct thread *td, char *path, char *link, enum uio_seg segflg)
1509{
1510	struct mount *mp;
1511	struct vattr vattr;
1512	char *syspath;
1513	int error;
1514	struct nameidata nd;
1515	int vfslocked;
1516
1517	if (segflg == UIO_SYSSPACE) {
1518		syspath = path;
1519	} else {
1520		syspath = uma_zalloc(namei_zone, M_WAITOK);
1521		if ((error = copyinstr(path, syspath, MAXPATHLEN, NULL)) != 0)
1522			goto out;
1523	}
1524	AUDIT_ARG(text, syspath);
1525restart:
1526	bwillwrite();
1527	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
1528	    segflg, link, td);
1529	if ((error = namei(&nd)) != 0)
1530		goto out;
1531	vfslocked = NDHASGIANT(&nd);
1532	if (nd.ni_vp) {
1533		NDFREE(&nd, NDF_ONLY_PNBUF);
1534		if (nd.ni_vp == nd.ni_dvp)
1535			vrele(nd.ni_dvp);
1536		else
1537			vput(nd.ni_dvp);
1538		vrele(nd.ni_vp);
1539		VFS_UNLOCK_GIANT(vfslocked);
1540		error = EEXIST;
1541		goto out;
1542	}
1543	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1544		NDFREE(&nd, NDF_ONLY_PNBUF);
1545		vput(nd.ni_dvp);
1546		VFS_UNLOCK_GIANT(vfslocked);
1547		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1548			goto out;
1549		goto restart;
1550	}
1551	VATTR_NULL(&vattr);
1552	FILEDESC_LOCK_FAST(td->td_proc->p_fd);
1553	vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask;
1554	FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
1555#ifdef MAC
1556	vattr.va_type = VLNK;
1557	error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
1558	    &vattr);
1559	if (error)
1560		goto out2;
1561#endif
1562	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1563	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath);
1564	if (error == 0)
1565		vput(nd.ni_vp);
1566#ifdef MAC
1567out2:
1568#endif
1569	NDFREE(&nd, NDF_ONLY_PNBUF);
1570	vput(nd.ni_dvp);
1571	vn_finished_write(mp);
1572	VFS_UNLOCK_GIANT(vfslocked);
1573out:
1574	if (segflg != UIO_SYSSPACE)
1575		uma_zfree(namei_zone, syspath);
1576	return (error);
1577}
1578
1579/*
1580 * Delete a whiteout from the filesystem.
1581 */
1582int
1583undelete(td, uap)
1584	struct thread *td;
1585	register struct undelete_args /* {
1586		char *path;
1587	} */ *uap;
1588{
1589	int error;
1590	struct mount *mp;
1591	struct nameidata nd;
1592	int vfslocked;
1593
1594restart:
1595	bwillwrite();
1596	NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | MPSAFE | AUDITVNODE1,
1597	    UIO_USERSPACE, uap->path, td);
1598	error = namei(&nd);
1599	if (error)
1600		return (error);
1601	vfslocked = NDHASGIANT(&nd);
1602
1603	if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
1604		NDFREE(&nd, NDF_ONLY_PNBUF);
1605		if (nd.ni_vp == nd.ni_dvp)
1606			vrele(nd.ni_dvp);
1607		else
1608			vput(nd.ni_dvp);
1609		if (nd.ni_vp)
1610			vrele(nd.ni_vp);
1611		VFS_UNLOCK_GIANT(vfslocked);
1612		return (EEXIST);
1613	}
1614	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1615		NDFREE(&nd, NDF_ONLY_PNBUF);
1616		vput(nd.ni_dvp);
1617		VFS_UNLOCK_GIANT(vfslocked);
1618		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
1619			return (error);
1620		goto restart;
1621	}
1622	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1623	error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
1624	NDFREE(&nd, NDF_ONLY_PNBUF);
1625	vput(nd.ni_dvp);
1626	vn_finished_write(mp);
1627	VFS_UNLOCK_GIANT(vfslocked);
1628	return (error);
1629}
1630
1631/*
1632 * Delete a name from the filesystem.
1633 */
1634#ifndef _SYS_SYSPROTO_H_
1635struct unlink_args {
1636	char	*path;
1637};
1638#endif
1639int
1640unlink(td, uap)
1641	struct thread *td;
1642	struct unlink_args /* {
1643		char *path;
1644	} */ *uap;
1645{
1646	int error;
1647
1648	error = kern_unlink(td, uap->path, UIO_USERSPACE);
1649	return (error);
1650}
1651
1652int
1653kern_unlink(struct thread *td, char *path, enum uio_seg pathseg)
1654{
1655	struct mount *mp;
1656	struct vnode *vp;
1657	int error;
1658	struct nameidata nd;
1659	int vfslocked;
1660
1661restart:
1662	bwillwrite();
1663	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1,
1664	    pathseg, path, td);
1665	if ((error = namei(&nd)) != 0)
1666		return (error == EINVAL ? EPERM : error);
1667	vfslocked = NDHASGIANT(&nd);
1668	vp = nd.ni_vp;
1669	if (vp->v_type == VDIR)
1670		error = EPERM;		/* POSIX */
1671	else {
1672		/*
1673		 * The root of a mounted filesystem cannot be deleted.
1674		 *
1675		 * XXX: can this only be a VDIR case?
1676		 */
1677		if (vp->v_vflag & VV_ROOT)
1678			error = EBUSY;
1679	}
1680	if (error == 0) {
1681		if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
1682			NDFREE(&nd, NDF_ONLY_PNBUF);
1683			vput(nd.ni_dvp);
1684			if (vp == nd.ni_dvp)
1685				vrele(vp);
1686			else
1687				vput(vp);
1688			VFS_UNLOCK_GIANT(vfslocked);
1689			if ((error = vn_start_write(NULL, &mp,
1690			    V_XSLEEP | PCATCH)) != 0)
1691				return (error);
1692			goto restart;
1693		}
1694#ifdef MAC
1695		error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
1696		    &nd.ni_cnd);
1697		if (error)
1698			goto out;
1699#endif
1700		VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
1701		error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
1702#ifdef MAC
1703out:
1704#endif
1705		vn_finished_write(mp);
1706	}
1707	NDFREE(&nd, NDF_ONLY_PNBUF);
1708	vput(nd.ni_dvp);
1709	if (vp == nd.ni_dvp)
1710		vrele(vp);
1711	else
1712		vput(vp);
1713	VFS_UNLOCK_GIANT(vfslocked);
1714	return (error);
1715}
1716
1717/*
1718 * Reposition read/write file offset.
1719 */
1720#ifndef _SYS_SYSPROTO_H_
1721struct lseek_args {
1722	int	fd;
1723	int	pad;
1724	off_t	offset;
1725	int	whence;
1726};
1727#endif
1728int
1729lseek(td, uap)
1730	struct thread *td;
1731	register struct lseek_args /* {
1732		int fd;
1733		int pad;
1734		off_t offset;
1735		int whence;
1736	} */ *uap;
1737{
1738	struct ucred *cred = td->td_ucred;
1739	struct file *fp;
1740	struct vnode *vp;
1741	struct vattr vattr;
1742	off_t offset;
1743	int error, noneg;
1744	int vfslocked;
1745
1746	if ((error = fget(td, uap->fd, &fp)) != 0)
1747		return (error);
1748	if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) {
1749		fdrop(fp, td);
1750		return (ESPIPE);
1751	}
1752	vp = fp->f_vnode;
1753	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1754	noneg = (vp->v_type != VCHR);
1755	offset = uap->offset;
1756	switch (uap->whence) {
1757	case L_INCR:
1758		if (noneg &&
1759		    (fp->f_offset < 0 ||
1760		    (offset > 0 && fp->f_offset > OFF_MAX - offset))) {
1761			error = EOVERFLOW;
1762			break;
1763		}
1764		offset += fp->f_offset;
1765		break;
1766	case L_XTND:
1767		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1768		error = VOP_GETATTR(vp, &vattr, cred, td);
1769		VOP_UNLOCK(vp, 0, td);
1770		if (error)
1771			break;
1772		if (noneg &&
1773		    (vattr.va_size > OFF_MAX ||
1774		    (offset > 0 && vattr.va_size > OFF_MAX - offset))) {
1775			error = EOVERFLOW;
1776			break;
1777		}
1778		offset += vattr.va_size;
1779		break;
1780	case L_SET:
1781		break;
1782	default:
1783		error = EINVAL;
1784	}
1785	if (error == 0 && noneg && offset < 0)
1786		error = EINVAL;
1787	if (error != 0)
1788		goto drop;
1789	fp->f_offset = offset;
1790	*(off_t *)(td->td_retval) = fp->f_offset;
1791drop:
1792	fdrop(fp, td);
1793	VFS_UNLOCK_GIANT(vfslocked);
1794	return (error);
1795}
1796
1797#if defined(COMPAT_43)
1798/*
1799 * Reposition read/write file offset.
1800 */
1801#ifndef _SYS_SYSPROTO_H_
1802struct olseek_args {
1803	int	fd;
1804	long	offset;
1805	int	whence;
1806};
1807#endif
1808int
1809olseek(td, uap)
1810	struct thread *td;
1811	register struct olseek_args /* {
1812		int fd;
1813		long offset;
1814		int whence;
1815	} */ *uap;
1816{
1817	struct lseek_args /* {
1818		int fd;
1819		int pad;
1820		off_t offset;
1821		int whence;
1822	} */ nuap;
1823	int error;
1824
1825	nuap.fd = uap->fd;
1826	nuap.offset = uap->offset;
1827	nuap.whence = uap->whence;
1828	error = lseek(td, &nuap);
1829	return (error);
1830}
1831#endif /* COMPAT_43 */
1832
1833/*
1834 * Check access permissions using passed credentials.
1835 */
1836static int
1837vn_access(vp, user_flags, cred, td)
1838	struct vnode	*vp;
1839	int		user_flags;
1840	struct ucred	*cred;
1841	struct thread	*td;
1842{
1843	int error, flags;
1844
1845	/* Flags == 0 means only check for existence. */
1846	error = 0;
1847	if (user_flags) {
1848		flags = 0;
1849		if (user_flags & R_OK)
1850			flags |= VREAD;
1851		if (user_flags & W_OK)
1852			flags |= VWRITE;
1853		if (user_flags & X_OK)
1854			flags |= VEXEC;
1855#ifdef MAC
1856		error = mac_check_vnode_access(cred, vp, flags);
1857		if (error)
1858			return (error);
1859#endif
1860		if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0)
1861			error = VOP_ACCESS(vp, flags, cred, td);
1862	}
1863	return (error);
1864}
1865
1866/*
1867 * Check access permissions using "real" credentials.
1868 */
1869#ifndef _SYS_SYSPROTO_H_
1870struct access_args {
1871	char	*path;
1872	int	flags;
1873};
1874#endif
1875int
1876access(td, uap)
1877	struct thread *td;
1878	register struct access_args /* {
1879		char *path;
1880		int flags;
1881	} */ *uap;
1882{
1883
1884	return (kern_access(td, uap->path, UIO_USERSPACE, uap->flags));
1885}
1886
1887int
1888kern_access(struct thread *td, char *path, enum uio_seg pathseg, int flags)
1889{
1890	struct ucred *cred, *tmpcred;
1891	register struct vnode *vp;
1892	struct nameidata nd;
1893	int vfslocked;
1894	int error;
1895
1896	/*
1897	 * Create and modify a temporary credential instead of one that
1898	 * is potentially shared.  This could also mess up socket
1899	 * buffer accounting which can run in an interrupt context.
1900	 */
1901	cred = td->td_ucred;
1902	tmpcred = crdup(cred);
1903	tmpcred->cr_uid = cred->cr_ruid;
1904	tmpcred->cr_groups[0] = cred->cr_rgid;
1905	td->td_ucred = tmpcred;
1906	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
1907	    pathseg, path, td);
1908	if ((error = namei(&nd)) != 0)
1909		goto out1;
1910	vfslocked = NDHASGIANT(&nd);
1911	vp = nd.ni_vp;
1912
1913	error = vn_access(vp, flags, tmpcred, td);
1914	NDFREE(&nd, NDF_ONLY_PNBUF);
1915	vput(vp);
1916	VFS_UNLOCK_GIANT(vfslocked);
1917out1:
1918	td->td_ucred = cred;
1919	crfree(tmpcred);
1920	return (error);
1921}
1922
1923/*
1924 * Check access permissions using "effective" credentials.
1925 */
1926#ifndef _SYS_SYSPROTO_H_
1927struct eaccess_args {
1928	char	*path;
1929	int	flags;
1930};
1931#endif
1932int
1933eaccess(td, uap)
1934	struct thread *td;
1935	register struct eaccess_args /* {
1936		char *path;
1937		int flags;
1938	} */ *uap;
1939{
1940
1941	return (kern_eaccess(td, uap->path, UIO_USERSPACE, uap->flags));
1942}
1943
1944int
1945kern_eaccess(struct thread *td, char *path, enum uio_seg pathseg, int flags)
1946{
1947	struct nameidata nd;
1948	struct vnode *vp;
1949	int vfslocked;
1950	int error;
1951
1952	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
1953	    pathseg, path, td);
1954	if ((error = namei(&nd)) != 0)
1955		return (error);
1956	vp = nd.ni_vp;
1957	vfslocked = NDHASGIANT(&nd);
1958	error = vn_access(vp, flags, td->td_ucred, td);
1959	NDFREE(&nd, NDF_ONLY_PNBUF);
1960	vput(vp);
1961	VFS_UNLOCK_GIANT(vfslocked);
1962	return (error);
1963}
1964
1965#if defined(COMPAT_43)
1966/*
1967 * Get file status; this version follows links.
1968 */
1969#ifndef _SYS_SYSPROTO_H_
1970struct ostat_args {
1971	char	*path;
1972	struct ostat *ub;
1973};
1974#endif
1975int
1976ostat(td, uap)
1977	struct thread *td;
1978	register struct ostat_args /* {
1979		char *path;
1980		struct ostat *ub;
1981	} */ *uap;
1982{
1983	struct stat sb;
1984	struct ostat osb;
1985	int error;
1986
1987	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
1988	if (error)
1989		return (error);
1990	cvtstat(&sb, &osb);
1991	error = copyout(&osb, uap->ub, sizeof (osb));
1992	return (error);
1993}
1994
1995/*
1996 * Get file status; this version does not follow links.
1997 */
1998#ifndef _SYS_SYSPROTO_H_
1999struct olstat_args {
2000	char	*path;
2001	struct ostat *ub;
2002};
2003#endif
2004int
2005olstat(td, uap)
2006	struct thread *td;
2007	register struct olstat_args /* {
2008		char *path;
2009		struct ostat *ub;
2010	} */ *uap;
2011{
2012	struct stat sb;
2013	struct ostat osb;
2014	int error;
2015
2016	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2017	if (error)
2018		return (error);
2019	cvtstat(&sb, &osb);
2020	error = copyout(&osb, uap->ub, sizeof (osb));
2021	return (error);
2022}
2023
2024/*
2025 * Convert from an old to a new stat structure.
2026 */
2027void
2028cvtstat(st, ost)
2029	struct stat *st;
2030	struct ostat *ost;
2031{
2032
2033	ost->st_dev = st->st_dev;
2034	ost->st_ino = st->st_ino;
2035	ost->st_mode = st->st_mode;
2036	ost->st_nlink = st->st_nlink;
2037	ost->st_uid = st->st_uid;
2038	ost->st_gid = st->st_gid;
2039	ost->st_rdev = st->st_rdev;
2040	if (st->st_size < (quad_t)1 << 32)
2041		ost->st_size = st->st_size;
2042	else
2043		ost->st_size = -2;
2044	ost->st_atime = st->st_atime;
2045	ost->st_mtime = st->st_mtime;
2046	ost->st_ctime = st->st_ctime;
2047	ost->st_blksize = st->st_blksize;
2048	ost->st_blocks = st->st_blocks;
2049	ost->st_flags = st->st_flags;
2050	ost->st_gen = st->st_gen;
2051}
2052#endif /* COMPAT_43 */
2053
2054/*
2055 * Get file status; this version follows links.
2056 */
2057#ifndef _SYS_SYSPROTO_H_
2058struct stat_args {
2059	char	*path;
2060	struct stat *ub;
2061};
2062#endif
2063int
2064stat(td, uap)
2065	struct thread *td;
2066	register struct stat_args /* {
2067		char *path;
2068		struct stat *ub;
2069	} */ *uap;
2070{
2071	struct stat sb;
2072	int error;
2073
2074	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2075	if (error == 0)
2076		error = copyout(&sb, uap->ub, sizeof (sb));
2077	return (error);
2078}
2079
2080int
2081kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
2082{
2083	struct nameidata nd;
2084	struct stat sb;
2085	int error, vfslocked;
2086
2087	NDINIT(&nd, LOOKUP,
2088	    FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | AUDITVNODE1,
2089	    pathseg, path, td);
2090	if ((error = namei(&nd)) != 0)
2091		return (error);
2092	vfslocked = NDHASGIANT(&nd);
2093	error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
2094	NDFREE(&nd, NDF_ONLY_PNBUF);
2095	vput(nd.ni_vp);
2096	VFS_UNLOCK_GIANT(vfslocked);
2097	if (mtx_owned(&Giant))
2098		printf("stat(%d): %s\n", vfslocked, path);
2099	if (error)
2100		return (error);
2101	*sbp = sb;
2102	return (0);
2103}
2104
2105/*
2106 * Get file status; this version does not follow links.
2107 */
2108#ifndef _SYS_SYSPROTO_H_
2109struct lstat_args {
2110	char	*path;
2111	struct stat *ub;
2112};
2113#endif
2114int
2115lstat(td, uap)
2116	struct thread *td;
2117	register struct lstat_args /* {
2118		char *path;
2119		struct stat *ub;
2120	} */ *uap;
2121{
2122	struct stat sb;
2123	int error;
2124
2125	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2126	if (error == 0)
2127		error = copyout(&sb, uap->ub, sizeof (sb));
2128	return (error);
2129}
2130
2131int
2132kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
2133{
2134	struct vnode *vp;
2135	struct stat sb;
2136	struct nameidata nd;
2137	int error, vfslocked;
2138
2139	NDINIT(&nd, LOOKUP,
2140	    NOFOLLOW | LOCKLEAF | LOCKSHARED | MPSAFE | AUDITVNODE1,
2141	    pathseg, path, td);
2142	if ((error = namei(&nd)) != 0)
2143		return (error);
2144	vfslocked = NDHASGIANT(&nd);
2145	vp = nd.ni_vp;
2146	error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
2147	NDFREE(&nd, NDF_ONLY_PNBUF);
2148	vput(vp);
2149	VFS_UNLOCK_GIANT(vfslocked);
2150	if (error)
2151		return (error);
2152	*sbp = sb;
2153	return (0);
2154}
2155
2156/*
2157 * Implementation of the NetBSD [l]stat() functions.
2158 */
2159void
2160cvtnstat(sb, nsb)
2161	struct stat *sb;
2162	struct nstat *nsb;
2163{
2164	bzero(nsb, sizeof *nsb);
2165	nsb->st_dev = sb->st_dev;
2166	nsb->st_ino = sb->st_ino;
2167	nsb->st_mode = sb->st_mode;
2168	nsb->st_nlink = sb->st_nlink;
2169	nsb->st_uid = sb->st_uid;
2170	nsb->st_gid = sb->st_gid;
2171	nsb->st_rdev = sb->st_rdev;
2172	nsb->st_atimespec = sb->st_atimespec;
2173	nsb->st_mtimespec = sb->st_mtimespec;
2174	nsb->st_ctimespec = sb->st_ctimespec;
2175	nsb->st_size = sb->st_size;
2176	nsb->st_blocks = sb->st_blocks;
2177	nsb->st_blksize = sb->st_blksize;
2178	nsb->st_flags = sb->st_flags;
2179	nsb->st_gen = sb->st_gen;
2180	nsb->st_birthtimespec = sb->st_birthtimespec;
2181}
2182
2183#ifndef _SYS_SYSPROTO_H_
2184struct nstat_args {
2185	char	*path;
2186	struct nstat *ub;
2187};
2188#endif
2189int
2190nstat(td, uap)
2191	struct thread *td;
2192	register struct nstat_args /* {
2193		char *path;
2194		struct nstat *ub;
2195	} */ *uap;
2196{
2197	struct stat sb;
2198	struct nstat nsb;
2199	int error;
2200
2201	error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
2202	if (error)
2203		return (error);
2204	cvtnstat(&sb, &nsb);
2205	error = copyout(&nsb, uap->ub, sizeof (nsb));
2206	return (error);
2207}
2208
2209/*
2210 * NetBSD lstat.  Get file status; this version does not follow links.
2211 */
2212#ifndef _SYS_SYSPROTO_H_
2213struct lstat_args {
2214	char	*path;
2215	struct stat *ub;
2216};
2217#endif
2218int
2219nlstat(td, uap)
2220	struct thread *td;
2221	register struct nlstat_args /* {
2222		char *path;
2223		struct nstat *ub;
2224	} */ *uap;
2225{
2226	struct stat sb;
2227	struct nstat nsb;
2228	int error;
2229
2230	error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
2231	if (error)
2232		return (error);
2233	cvtnstat(&sb, &nsb);
2234	error = copyout(&nsb, uap->ub, sizeof (nsb));
2235	return (error);
2236}
2237
2238/*
2239 * Get configurable pathname variables.
2240 */
2241#ifndef _SYS_SYSPROTO_H_
2242struct pathconf_args {
2243	char	*path;
2244	int	name;
2245};
2246#endif
2247int
2248pathconf(td, uap)
2249	struct thread *td;
2250	register struct pathconf_args /* {
2251		char *path;
2252		int name;
2253	} */ *uap;
2254{
2255
2256	return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name));
2257}
2258
2259int
2260kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int name)
2261{
2262	struct nameidata nd;
2263	int error, vfslocked;
2264
2265	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
2266	    pathseg, path, td);
2267	if ((error = namei(&nd)) != 0)
2268		return (error);
2269	vfslocked = NDHASGIANT(&nd);
2270	NDFREE(&nd, NDF_ONLY_PNBUF);
2271
2272	/* If asynchronous I/O is available, it works for all files. */
2273	if (name == _PC_ASYNC_IO)
2274		td->td_retval[0] = async_io_version;
2275	else
2276		error = VOP_PATHCONF(nd.ni_vp, name, td->td_retval);
2277	vput(nd.ni_vp);
2278	VFS_UNLOCK_GIANT(vfslocked);
2279	return (error);
2280}
2281
2282/*
2283 * Return target name of a symbolic link.
2284 */
2285#ifndef _SYS_SYSPROTO_H_
2286struct readlink_args {
2287	char	*path;
2288	char	*buf;
2289	int	count;
2290};
2291#endif
2292int
2293readlink(td, uap)
2294	struct thread *td;
2295	register struct readlink_args /* {
2296		char *path;
2297		char *buf;
2298		int count;
2299	} */ *uap;
2300{
2301
2302	return (kern_readlink(td, uap->path, UIO_USERSPACE, uap->buf,
2303	    UIO_USERSPACE, uap->count));
2304}
2305
2306int
2307kern_readlink(struct thread *td, char *path, enum uio_seg pathseg, char *buf,
2308    enum uio_seg bufseg, int count)
2309{
2310	register struct vnode *vp;
2311	struct iovec aiov;
2312	struct uio auio;
2313	int error;
2314	struct nameidata nd;
2315	int vfslocked;
2316
2317	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
2318	    pathseg, path, td);
2319	if ((error = namei(&nd)) != 0)
2320		return (error);
2321	NDFREE(&nd, NDF_ONLY_PNBUF);
2322	vfslocked = NDHASGIANT(&nd);
2323	vp = nd.ni_vp;
2324#ifdef MAC
2325	error = mac_check_vnode_readlink(td->td_ucred, vp);
2326	if (error) {
2327		vput(vp);
2328		VFS_UNLOCK_GIANT(vfslocked);
2329		return (error);
2330	}
2331#endif
2332	if (vp->v_type != VLNK)
2333		error = EINVAL;
2334	else {
2335		aiov.iov_base = buf;
2336		aiov.iov_len = count;
2337		auio.uio_iov = &aiov;
2338		auio.uio_iovcnt = 1;
2339		auio.uio_offset = 0;
2340		auio.uio_rw = UIO_READ;
2341		auio.uio_segflg = bufseg;
2342		auio.uio_td = td;
2343		auio.uio_resid = count;
2344		error = VOP_READLINK(vp, &auio, td->td_ucred);
2345	}
2346	vput(vp);
2347	VFS_UNLOCK_GIANT(vfslocked);
2348	td->td_retval[0] = count - auio.uio_resid;
2349	return (error);
2350}
2351
2352/*
2353 * Common implementation code for chflags() and fchflags().
2354 */
2355static int
2356setfflags(td, vp, flags)
2357	struct thread *td;
2358	struct vnode *vp;
2359	int flags;
2360{
2361	int error;
2362	struct mount *mp;
2363	struct vattr vattr;
2364
2365	/*
2366	 * Prevent non-root users from setting flags on devices.  When
2367	 * a device is reused, users can retain ownership of the device
2368	 * if they are allowed to set flags and programs assume that
2369	 * chown can't fail when done as root.
2370	 */
2371	if (vp->v_type == VCHR || vp->v_type == VBLK) {
2372		error = priv_check_cred(td->td_ucred, PRIV_VFS_CHFLAGS_DEV,
2373		    SUSER_ALLOWJAIL);
2374		if (error)
2375			return (error);
2376	}
2377
2378	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2379		return (error);
2380	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2381	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2382	VATTR_NULL(&vattr);
2383	vattr.va_flags = flags;
2384#ifdef MAC
2385	error = mac_check_vnode_setflags(td->td_ucred, vp, vattr.va_flags);
2386	if (error == 0)
2387#endif
2388		error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2389	VOP_UNLOCK(vp, 0, td);
2390	vn_finished_write(mp);
2391	return (error);
2392}
2393
2394/*
2395 * Change flags of a file given a path name.
2396 */
2397#ifndef _SYS_SYSPROTO_H_
2398struct chflags_args {
2399	char	*path;
2400	int	flags;
2401};
2402#endif
2403int
2404chflags(td, uap)
2405	struct thread *td;
2406	register struct chflags_args /* {
2407		char *path;
2408		int flags;
2409	} */ *uap;
2410{
2411	int error;
2412	struct nameidata nd;
2413	int vfslocked;
2414
2415	AUDIT_ARG(fflags, uap->flags);
2416	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE,
2417	    uap->path, td);
2418	if ((error = namei(&nd)) != 0)
2419		return (error);
2420	NDFREE(&nd, NDF_ONLY_PNBUF);
2421	vfslocked = NDHASGIANT(&nd);
2422	error = setfflags(td, nd.ni_vp, uap->flags);
2423	vrele(nd.ni_vp);
2424	VFS_UNLOCK_GIANT(vfslocked);
2425	return (error);
2426}
2427
2428/*
2429 * Same as chflags() but doesn't follow symlinks.
2430 */
2431int
2432lchflags(td, uap)
2433	struct thread *td;
2434	register struct lchflags_args /* {
2435		char *path;
2436		int flags;
2437	} */ *uap;
2438{
2439	int error;
2440	struct nameidata nd;
2441	int vfslocked;
2442
2443	AUDIT_ARG(fflags, uap->flags);
2444	NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE,
2445	    uap->path, td);
2446	if ((error = namei(&nd)) != 0)
2447		return (error);
2448	vfslocked = NDHASGIANT(&nd);
2449	NDFREE(&nd, NDF_ONLY_PNBUF);
2450	error = setfflags(td, nd.ni_vp, uap->flags);
2451	vrele(nd.ni_vp);
2452	VFS_UNLOCK_GIANT(vfslocked);
2453	return (error);
2454}
2455
2456/*
2457 * Change flags of a file given a file descriptor.
2458 */
2459#ifndef _SYS_SYSPROTO_H_
2460struct fchflags_args {
2461	int	fd;
2462	int	flags;
2463};
2464#endif
2465int
2466fchflags(td, uap)
2467	struct thread *td;
2468	register struct fchflags_args /* {
2469		int fd;
2470		int flags;
2471	} */ *uap;
2472{
2473	struct file *fp;
2474	int vfslocked;
2475	int error;
2476
2477	AUDIT_ARG(fd, uap->fd);
2478	AUDIT_ARG(fflags, uap->flags);
2479	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2480		return (error);
2481	vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2482#ifdef AUDIT
2483	vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
2484	AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1);
2485	VOP_UNLOCK(fp->f_vnode, 0, td);
2486#endif
2487	error = setfflags(td, fp->f_vnode, uap->flags);
2488	VFS_UNLOCK_GIANT(vfslocked);
2489	fdrop(fp, td);
2490	return (error);
2491}
2492
2493/*
2494 * Common implementation code for chmod(), lchmod() and fchmod().
2495 */
2496static int
2497setfmode(td, vp, mode)
2498	struct thread *td;
2499	struct vnode *vp;
2500	int mode;
2501{
2502	int error;
2503	struct mount *mp;
2504	struct vattr vattr;
2505
2506	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2507		return (error);
2508	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2509	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2510	VATTR_NULL(&vattr);
2511	vattr.va_mode = mode & ALLPERMS;
2512#ifdef MAC
2513	error = mac_check_vnode_setmode(td->td_ucred, vp, vattr.va_mode);
2514	if (error == 0)
2515#endif
2516		error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2517	VOP_UNLOCK(vp, 0, td);
2518	vn_finished_write(mp);
2519	return (error);
2520}
2521
2522/*
2523 * Change mode of a file given path name.
2524 */
2525#ifndef _SYS_SYSPROTO_H_
2526struct chmod_args {
2527	char	*path;
2528	int	mode;
2529};
2530#endif
2531int
2532chmod(td, uap)
2533	struct thread *td;
2534	register struct chmod_args /* {
2535		char *path;
2536		int mode;
2537	} */ *uap;
2538{
2539
2540	return (kern_chmod(td, uap->path, UIO_USERSPACE, uap->mode));
2541}
2542
2543int
2544kern_chmod(struct thread *td, char *path, enum uio_seg pathseg, int mode)
2545{
2546	int error;
2547	struct nameidata nd;
2548	int vfslocked;
2549
2550	AUDIT_ARG(mode, mode);
2551	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2552	if ((error = namei(&nd)) != 0)
2553		return (error);
2554	vfslocked = NDHASGIANT(&nd);
2555	NDFREE(&nd, NDF_ONLY_PNBUF);
2556	error = setfmode(td, nd.ni_vp, mode);
2557	vrele(nd.ni_vp);
2558	VFS_UNLOCK_GIANT(vfslocked);
2559	return (error);
2560}
2561
2562/*
2563 * Change mode of a file given path name (don't follow links.)
2564 */
2565#ifndef _SYS_SYSPROTO_H_
2566struct lchmod_args {
2567	char	*path;
2568	int	mode;
2569};
2570#endif
2571int
2572lchmod(td, uap)
2573	struct thread *td;
2574	register struct lchmod_args /* {
2575		char *path;
2576		int mode;
2577	} */ *uap;
2578{
2579	int error;
2580	struct nameidata nd;
2581	int vfslocked;
2582
2583	AUDIT_ARG(mode, (mode_t)uap->mode);
2584	NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, UIO_USERSPACE,
2585	    uap->path, td);
2586	if ((error = namei(&nd)) != 0)
2587		return (error);
2588	vfslocked = NDHASGIANT(&nd);
2589	NDFREE(&nd, NDF_ONLY_PNBUF);
2590	error = setfmode(td, nd.ni_vp, uap->mode);
2591	vrele(nd.ni_vp);
2592	VFS_UNLOCK_GIANT(vfslocked);
2593	return (error);
2594}
2595
2596/*
2597 * Change mode of a file given a file descriptor.
2598 */
2599#ifndef _SYS_SYSPROTO_H_
2600struct fchmod_args {
2601	int	fd;
2602	int	mode;
2603};
2604#endif
2605int
2606fchmod(td, uap)
2607	struct thread *td;
2608	register struct fchmod_args /* {
2609		int fd;
2610		int mode;
2611	} */ *uap;
2612{
2613	struct file *fp;
2614	int vfslocked;
2615	int error;
2616
2617	AUDIT_ARG(fd, uap->fd);
2618	AUDIT_ARG(mode, uap->mode);
2619	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2620		return (error);
2621	vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2622#ifdef AUDIT
2623	vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
2624	AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1);
2625	VOP_UNLOCK(fp->f_vnode, 0, td);
2626#endif
2627	error = setfmode(td, fp->f_vnode, uap->mode);
2628	VFS_UNLOCK_GIANT(vfslocked);
2629	fdrop(fp, td);
2630	return (error);
2631}
2632
2633/*
2634 * Common implementation for chown(), lchown(), and fchown()
2635 */
2636static int
2637setfown(td, vp, uid, gid)
2638	struct thread *td;
2639	struct vnode *vp;
2640	uid_t uid;
2641	gid_t gid;
2642{
2643	int error;
2644	struct mount *mp;
2645	struct vattr vattr;
2646
2647	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2648		return (error);
2649	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2650	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2651	VATTR_NULL(&vattr);
2652	vattr.va_uid = uid;
2653	vattr.va_gid = gid;
2654#ifdef MAC
2655	error = mac_check_vnode_setowner(td->td_ucred, vp, vattr.va_uid,
2656	    vattr.va_gid);
2657	if (error == 0)
2658#endif
2659		error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2660	VOP_UNLOCK(vp, 0, td);
2661	vn_finished_write(mp);
2662	return (error);
2663}
2664
2665/*
2666 * Set ownership given a path name.
2667 */
2668#ifndef _SYS_SYSPROTO_H_
2669struct chown_args {
2670	char	*path;
2671	int	uid;
2672	int	gid;
2673};
2674#endif
2675int
2676chown(td, uap)
2677	struct thread *td;
2678	register struct chown_args /* {
2679		char *path;
2680		int uid;
2681		int gid;
2682	} */ *uap;
2683{
2684
2685	return (kern_chown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2686}
2687
2688int
2689kern_chown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2690    int gid)
2691{
2692	int error;
2693	struct nameidata nd;
2694	int vfslocked;
2695
2696	AUDIT_ARG(owner, uid, gid);
2697	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2698	if ((error = namei(&nd)) != 0)
2699		return (error);
2700	vfslocked = NDHASGIANT(&nd);
2701	NDFREE(&nd, NDF_ONLY_PNBUF);
2702	error = setfown(td, nd.ni_vp, uid, gid);
2703	vrele(nd.ni_vp);
2704	VFS_UNLOCK_GIANT(vfslocked);
2705	return (error);
2706}
2707
2708/*
2709 * Set ownership given a path name, do not cross symlinks.
2710 */
2711#ifndef _SYS_SYSPROTO_H_
2712struct lchown_args {
2713	char	*path;
2714	int	uid;
2715	int	gid;
2716};
2717#endif
2718int
2719lchown(td, uap)
2720	struct thread *td;
2721	register struct lchown_args /* {
2722		char *path;
2723		int uid;
2724		int gid;
2725	} */ *uap;
2726{
2727
2728	return (kern_lchown(td, uap->path, UIO_USERSPACE, uap->uid, uap->gid));
2729}
2730
2731int
2732kern_lchown(struct thread *td, char *path, enum uio_seg pathseg, int uid,
2733    int gid)
2734{
2735	int error;
2736	struct nameidata nd;
2737	int vfslocked;
2738
2739	AUDIT_ARG(owner, uid, gid);
2740	NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2741	if ((error = namei(&nd)) != 0)
2742		return (error);
2743	vfslocked = NDHASGIANT(&nd);
2744	NDFREE(&nd, NDF_ONLY_PNBUF);
2745	error = setfown(td, nd.ni_vp, uid, gid);
2746	vrele(nd.ni_vp);
2747	VFS_UNLOCK_GIANT(vfslocked);
2748	return (error);
2749}
2750
2751/*
2752 * Set ownership given a file descriptor.
2753 */
2754#ifndef _SYS_SYSPROTO_H_
2755struct fchown_args {
2756	int	fd;
2757	int	uid;
2758	int	gid;
2759};
2760#endif
2761int
2762fchown(td, uap)
2763	struct thread *td;
2764	register struct fchown_args /* {
2765		int fd;
2766		int uid;
2767		int gid;
2768	} */ *uap;
2769{
2770	struct file *fp;
2771	int vfslocked;
2772	int error;
2773
2774	AUDIT_ARG(fd, uap->fd);
2775	AUDIT_ARG(owner, uap->uid, uap->gid);
2776	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
2777		return (error);
2778	vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2779#ifdef AUDIT
2780	vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
2781	AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1);
2782	VOP_UNLOCK(fp->f_vnode, 0, td);
2783#endif
2784	error = setfown(td, fp->f_vnode, uap->uid, uap->gid);
2785	VFS_UNLOCK_GIANT(vfslocked);
2786	fdrop(fp, td);
2787	return (error);
2788}
2789
2790/*
2791 * Common implementation code for utimes(), lutimes(), and futimes().
2792 */
2793static int
2794getutimes(usrtvp, tvpseg, tsp)
2795	const struct timeval *usrtvp;
2796	enum uio_seg tvpseg;
2797	struct timespec *tsp;
2798{
2799	struct timeval tv[2];
2800	const struct timeval *tvp;
2801	int error;
2802
2803	if (usrtvp == NULL) {
2804		microtime(&tv[0]);
2805		TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
2806		tsp[1] = tsp[0];
2807	} else {
2808		if (tvpseg == UIO_SYSSPACE) {
2809			tvp = usrtvp;
2810		} else {
2811			if ((error = copyin(usrtvp, tv, sizeof(tv))) != 0)
2812				return (error);
2813			tvp = tv;
2814		}
2815
2816		if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 ||
2817		    tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000)
2818			return (EINVAL);
2819		TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
2820		TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
2821	}
2822	return (0);
2823}
2824
2825/*
2826 * Common implementation code for utimes(), lutimes(), and futimes().
2827 */
2828static int
2829setutimes(td, vp, ts, numtimes, nullflag)
2830	struct thread *td;
2831	struct vnode *vp;
2832	const struct timespec *ts;
2833	int numtimes;
2834	int nullflag;
2835{
2836	int error, setbirthtime;
2837	struct mount *mp;
2838	struct vattr vattr;
2839
2840	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
2841		return (error);
2842	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
2843	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2844	setbirthtime = 0;
2845	if (numtimes < 3 && VOP_GETATTR(vp, &vattr, td->td_ucred, td) == 0 &&
2846	    timespeccmp(&ts[1], &vattr.va_birthtime, < ))
2847		setbirthtime = 1;
2848	VATTR_NULL(&vattr);
2849	vattr.va_atime = ts[0];
2850	vattr.va_mtime = ts[1];
2851	if (setbirthtime)
2852		vattr.va_birthtime = ts[1];
2853	if (numtimes > 2)
2854		vattr.va_birthtime = ts[2];
2855	if (nullflag)
2856		vattr.va_vaflags |= VA_UTIMES_NULL;
2857#ifdef MAC
2858	error = mac_check_vnode_setutimes(td->td_ucred, vp, vattr.va_atime,
2859	    vattr.va_mtime);
2860#endif
2861	if (error == 0)
2862		error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
2863	VOP_UNLOCK(vp, 0, td);
2864	vn_finished_write(mp);
2865	return (error);
2866}
2867
2868/*
2869 * Set the access and modification times of a file.
2870 */
2871#ifndef _SYS_SYSPROTO_H_
2872struct utimes_args {
2873	char	*path;
2874	struct	timeval *tptr;
2875};
2876#endif
2877int
2878utimes(td, uap)
2879	struct thread *td;
2880	register struct utimes_args /* {
2881		char *path;
2882		struct timeval *tptr;
2883	} */ *uap;
2884{
2885
2886	return (kern_utimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2887	    UIO_USERSPACE));
2888}
2889
2890int
2891kern_utimes(struct thread *td, char *path, enum uio_seg pathseg,
2892    struct timeval *tptr, enum uio_seg tptrseg)
2893{
2894	struct timespec ts[2];
2895	int error;
2896	struct nameidata nd;
2897	int vfslocked;
2898
2899	if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2900		return (error);
2901	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2902	if ((error = namei(&nd)) != 0)
2903		return (error);
2904	vfslocked = NDHASGIANT(&nd);
2905	NDFREE(&nd, NDF_ONLY_PNBUF);
2906	error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2907	vrele(nd.ni_vp);
2908	VFS_UNLOCK_GIANT(vfslocked);
2909	return (error);
2910}
2911
2912/*
2913 * Set the access and modification times of a file.
2914 */
2915#ifndef _SYS_SYSPROTO_H_
2916struct lutimes_args {
2917	char	*path;
2918	struct	timeval *tptr;
2919};
2920#endif
2921int
2922lutimes(td, uap)
2923	struct thread *td;
2924	register struct lutimes_args /* {
2925		char *path;
2926		struct timeval *tptr;
2927	} */ *uap;
2928{
2929
2930	return (kern_lutimes(td, uap->path, UIO_USERSPACE, uap->tptr,
2931	    UIO_USERSPACE));
2932}
2933
2934int
2935kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg,
2936    struct timeval *tptr, enum uio_seg tptrseg)
2937{
2938	struct timespec ts[2];
2939	int error;
2940	struct nameidata nd;
2941	int vfslocked;
2942
2943	if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2944		return (error);
2945	NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
2946	if ((error = namei(&nd)) != 0)
2947		return (error);
2948	vfslocked = NDHASGIANT(&nd);
2949	NDFREE(&nd, NDF_ONLY_PNBUF);
2950	error = setutimes(td, nd.ni_vp, ts, 2, tptr == NULL);
2951	vrele(nd.ni_vp);
2952	VFS_UNLOCK_GIANT(vfslocked);
2953	return (error);
2954}
2955
2956/*
2957 * Set the access and modification times of a file.
2958 */
2959#ifndef _SYS_SYSPROTO_H_
2960struct futimes_args {
2961	int	fd;
2962	struct	timeval *tptr;
2963};
2964#endif
2965int
2966futimes(td, uap)
2967	struct thread *td;
2968	register struct futimes_args /* {
2969		int  fd;
2970		struct timeval *tptr;
2971	} */ *uap;
2972{
2973
2974	return (kern_futimes(td, uap->fd, uap->tptr, UIO_USERSPACE));
2975}
2976
2977int
2978kern_futimes(struct thread *td, int fd, struct timeval *tptr,
2979    enum uio_seg tptrseg)
2980{
2981	struct timespec ts[2];
2982	struct file *fp;
2983	int vfslocked;
2984	int error;
2985
2986	AUDIT_ARG(fd, fd);
2987	if ((error = getutimes(tptr, tptrseg, ts)) != 0)
2988		return (error);
2989	if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
2990		return (error);
2991	vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
2992#ifdef AUDIT
2993	vn_lock(fp->f_vnode, LK_EXCLUSIVE | LK_RETRY, td);
2994	AUDIT_ARG(vnode, fp->f_vnode, ARG_VNODE1);
2995	VOP_UNLOCK(fp->f_vnode, 0, td);
2996#endif
2997	error = setutimes(td, fp->f_vnode, ts, 2, tptr == NULL);
2998	VFS_UNLOCK_GIANT(vfslocked);
2999	fdrop(fp, td);
3000	return (error);
3001}
3002
3003/*
3004 * Truncate a file given its path name.
3005 */
3006#ifndef _SYS_SYSPROTO_H_
3007struct truncate_args {
3008	char	*path;
3009	int	pad;
3010	off_t	length;
3011};
3012#endif
3013int
3014truncate(td, uap)
3015	struct thread *td;
3016	register struct truncate_args /* {
3017		char *path;
3018		int pad;
3019		off_t length;
3020	} */ *uap;
3021{
3022
3023	return (kern_truncate(td, uap->path, UIO_USERSPACE, uap->length));
3024}
3025
3026int
3027kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length)
3028{
3029	struct mount *mp;
3030	struct vnode *vp;
3031	struct vattr vattr;
3032	int error;
3033	struct nameidata nd;
3034	int vfslocked;
3035
3036	if (length < 0)
3037		return(EINVAL);
3038	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path, td);
3039	if ((error = namei(&nd)) != 0)
3040		return (error);
3041	vfslocked = NDHASGIANT(&nd);
3042	vp = nd.ni_vp;
3043	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
3044		vrele(vp);
3045		VFS_UNLOCK_GIANT(vfslocked);
3046		return (error);
3047	}
3048	NDFREE(&nd, NDF_ONLY_PNBUF);
3049	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3050	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3051	if (vp->v_type == VDIR)
3052		error = EISDIR;
3053#ifdef MAC
3054	else if ((error = mac_check_vnode_write(td->td_ucred, NOCRED, vp))) {
3055	}
3056#endif
3057	else if ((error = vn_writechk(vp)) == 0 &&
3058	    (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
3059		VATTR_NULL(&vattr);
3060		vattr.va_size = length;
3061		error = VOP_SETATTR(vp, &vattr, td->td_ucred, td);
3062	}
3063	vput(vp);
3064	vn_finished_write(mp);
3065	VFS_UNLOCK_GIANT(vfslocked);
3066	return (error);
3067}
3068
3069/*
3070 * Truncate a file given a file descriptor.
3071 */
3072#ifndef _SYS_SYSPROTO_H_
3073struct ftruncate_args {
3074	int	fd;
3075	int	pad;
3076	off_t	length;
3077};
3078#endif
3079int
3080ftruncate(td, uap)
3081	struct thread *td;
3082	register struct ftruncate_args /* {
3083		int fd;
3084		int pad;
3085		off_t length;
3086	} */ *uap;
3087{
3088	struct mount *mp;
3089	struct vattr vattr;
3090	struct vnode *vp;
3091	struct file *fp;
3092	int vfslocked;
3093	int error;
3094
3095	AUDIT_ARG(fd, uap->fd);
3096	if (uap->length < 0)
3097		return(EINVAL);
3098	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3099		return (error);
3100	if ((fp->f_flag & FWRITE) == 0) {
3101		fdrop(fp, td);
3102		return (EINVAL);
3103	}
3104	vp = fp->f_vnode;
3105	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3106	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3107		goto drop;
3108	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3109	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3110	AUDIT_ARG(vnode, vp, ARG_VNODE1);
3111	if (vp->v_type == VDIR)
3112		error = EISDIR;
3113#ifdef MAC
3114	else if ((error = mac_check_vnode_write(td->td_ucred, fp->f_cred,
3115	    vp))) {
3116	}
3117#endif
3118	else if ((error = vn_writechk(vp)) == 0) {
3119		VATTR_NULL(&vattr);
3120		vattr.va_size = uap->length;
3121		error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
3122	}
3123	VOP_UNLOCK(vp, 0, td);
3124	vn_finished_write(mp);
3125drop:
3126	VFS_UNLOCK_GIANT(vfslocked);
3127	fdrop(fp, td);
3128	return (error);
3129}
3130
3131#if defined(COMPAT_43)
3132/*
3133 * Truncate a file given its path name.
3134 */
3135#ifndef _SYS_SYSPROTO_H_
3136struct otruncate_args {
3137	char	*path;
3138	long	length;
3139};
3140#endif
3141int
3142otruncate(td, uap)
3143	struct thread *td;
3144	register struct otruncate_args /* {
3145		char *path;
3146		long length;
3147	} */ *uap;
3148{
3149	struct truncate_args /* {
3150		char *path;
3151		int pad;
3152		off_t length;
3153	} */ nuap;
3154
3155	nuap.path = uap->path;
3156	nuap.length = uap->length;
3157	return (truncate(td, &nuap));
3158}
3159
3160/*
3161 * Truncate a file given a file descriptor.
3162 */
3163#ifndef _SYS_SYSPROTO_H_
3164struct oftruncate_args {
3165	int	fd;
3166	long	length;
3167};
3168#endif
3169int
3170oftruncate(td, uap)
3171	struct thread *td;
3172	register struct oftruncate_args /* {
3173		int fd;
3174		long length;
3175	} */ *uap;
3176{
3177	struct ftruncate_args /* {
3178		int fd;
3179		int pad;
3180		off_t length;
3181	} */ nuap;
3182
3183	nuap.fd = uap->fd;
3184	nuap.length = uap->length;
3185	return (ftruncate(td, &nuap));
3186}
3187#endif /* COMPAT_43 */
3188
3189/*
3190 * Sync an open file.
3191 */
3192#ifndef _SYS_SYSPROTO_H_
3193struct fsync_args {
3194	int	fd;
3195};
3196#endif
3197int
3198fsync(td, uap)
3199	struct thread *td;
3200	struct fsync_args /* {
3201		int fd;
3202	} */ *uap;
3203{
3204	struct vnode *vp;
3205	struct mount *mp;
3206	struct file *fp;
3207	int vfslocked;
3208	int error;
3209
3210	AUDIT_ARG(fd, uap->fd);
3211	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3212		return (error);
3213	vp = fp->f_vnode;
3214	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3215	if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
3216		goto drop;
3217	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3218	AUDIT_ARG(vnode, vp, ARG_VNODE1);
3219	if (vp->v_object != NULL) {
3220		VM_OBJECT_LOCK(vp->v_object);
3221		vm_object_page_clean(vp->v_object, 0, 0, 0);
3222		VM_OBJECT_UNLOCK(vp->v_object);
3223	}
3224	error = VOP_FSYNC(vp, MNT_WAIT, td);
3225
3226	VOP_UNLOCK(vp, 0, td);
3227	vn_finished_write(mp);
3228drop:
3229	VFS_UNLOCK_GIANT(vfslocked);
3230	fdrop(fp, td);
3231	return (error);
3232}
3233
3234/*
3235 * Rename files.  Source and destination must either both be directories,
3236 * or both not be directories.  If target is a directory, it must be empty.
3237 */
3238#ifndef _SYS_SYSPROTO_H_
3239struct rename_args {
3240	char	*from;
3241	char	*to;
3242};
3243#endif
3244int
3245rename(td, uap)
3246	struct thread *td;
3247	register struct rename_args /* {
3248		char *from;
3249		char *to;
3250	} */ *uap;
3251{
3252
3253	return (kern_rename(td, uap->from, uap->to, UIO_USERSPACE));
3254}
3255
3256int
3257kern_rename(struct thread *td, char *from, char *to, enum uio_seg pathseg)
3258{
3259	struct mount *mp = NULL;
3260	struct vnode *tvp, *fvp, *tdvp;
3261	struct nameidata fromnd, tond;
3262	int tvfslocked;
3263	int fvfslocked;
3264	int error;
3265
3266	bwillwrite();
3267#ifdef MAC
3268	NDINIT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE |
3269	    AUDITVNODE1, pathseg, from, td);
3270#else
3271	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART | MPSAFE |
3272	    AUDITVNODE1, pathseg, from, td);
3273#endif
3274	if ((error = namei(&fromnd)) != 0)
3275		return (error);
3276	fvfslocked = NDHASGIANT(&fromnd);
3277	tvfslocked = 0;
3278#ifdef MAC
3279	error = mac_check_vnode_rename_from(td->td_ucred, fromnd.ni_dvp,
3280	    fromnd.ni_vp, &fromnd.ni_cnd);
3281	VOP_UNLOCK(fromnd.ni_dvp, 0, td);
3282	if (fromnd.ni_dvp != fromnd.ni_vp)
3283		VOP_UNLOCK(fromnd.ni_vp, 0, td);
3284#endif
3285	fvp = fromnd.ni_vp;
3286	if (error == 0)
3287		error = vn_start_write(fvp, &mp, V_WAIT | PCATCH);
3288	if (error != 0) {
3289		NDFREE(&fromnd, NDF_ONLY_PNBUF);
3290		vrele(fromnd.ni_dvp);
3291		vrele(fvp);
3292		goto out1;
3293	}
3294	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART |
3295	    MPSAFE | AUDITVNODE2, pathseg, to, td);
3296	if (fromnd.ni_vp->v_type == VDIR)
3297		tond.ni_cnd.cn_flags |= WILLBEDIR;
3298	if ((error = namei(&tond)) != 0) {
3299		/* Translate error code for rename("dir1", "dir2/."). */
3300		if (error == EISDIR && fvp->v_type == VDIR)
3301			error = EINVAL;
3302		NDFREE(&fromnd, NDF_ONLY_PNBUF);
3303		vrele(fromnd.ni_dvp);
3304		vrele(fvp);
3305		vn_finished_write(mp);
3306		goto out1;
3307	}
3308	tvfslocked = NDHASGIANT(&tond);
3309	tdvp = tond.ni_dvp;
3310	tvp = tond.ni_vp;
3311	if (tvp != NULL) {
3312		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
3313			error = ENOTDIR;
3314			goto out;
3315		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
3316			error = EISDIR;
3317			goto out;
3318		}
3319	}
3320	if (fvp == tdvp)
3321		error = EINVAL;
3322	/*
3323	 * If the source is the same as the destination (that is, if they
3324	 * are links to the same vnode), then there is nothing to do.
3325	 */
3326	if (fvp == tvp)
3327		error = -1;
3328#ifdef MAC
3329	else
3330		error = mac_check_vnode_rename_to(td->td_ucred, tdvp,
3331		    tond.ni_vp, fromnd.ni_dvp == tdvp, &tond.ni_cnd);
3332#endif
3333out:
3334	if (!error) {
3335		VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE);
3336		if (fromnd.ni_dvp != tdvp) {
3337			VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3338		}
3339		if (tvp) {
3340			VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE);
3341		}
3342		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
3343				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
3344		NDFREE(&fromnd, NDF_ONLY_PNBUF);
3345		NDFREE(&tond, NDF_ONLY_PNBUF);
3346	} else {
3347		NDFREE(&fromnd, NDF_ONLY_PNBUF);
3348		NDFREE(&tond, NDF_ONLY_PNBUF);
3349		if (tvp)
3350			vput(tvp);
3351		if (tdvp == tvp)
3352			vrele(tdvp);
3353		else
3354			vput(tdvp);
3355		vrele(fromnd.ni_dvp);
3356		vrele(fvp);
3357	}
3358	vrele(tond.ni_startdir);
3359	vn_finished_write(mp);
3360out1:
3361	if (fromnd.ni_startdir)
3362		vrele(fromnd.ni_startdir);
3363	VFS_UNLOCK_GIANT(fvfslocked);
3364	VFS_UNLOCK_GIANT(tvfslocked);
3365	if (error == -1)
3366		return (0);
3367	return (error);
3368}
3369
3370/*
3371 * Make a directory file.
3372 */
3373#ifndef _SYS_SYSPROTO_H_
3374struct mkdir_args {
3375	char	*path;
3376	int	mode;
3377};
3378#endif
3379int
3380mkdir(td, uap)
3381	struct thread *td;
3382	register struct mkdir_args /* {
3383		char *path;
3384		int mode;
3385	} */ *uap;
3386{
3387
3388	return (kern_mkdir(td, uap->path, UIO_USERSPACE, uap->mode));
3389}
3390
3391int
3392kern_mkdir(struct thread *td, char *path, enum uio_seg segflg, int mode)
3393{
3394	struct mount *mp;
3395	struct vnode *vp;
3396	struct vattr vattr;
3397	int error;
3398	struct nameidata nd;
3399	int vfslocked;
3400
3401	AUDIT_ARG(mode, mode);
3402restart:
3403	bwillwrite();
3404	NDINIT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
3405	    segflg, path, td);
3406	nd.ni_cnd.cn_flags |= WILLBEDIR;
3407	if ((error = namei(&nd)) != 0)
3408		return (error);
3409	vfslocked = NDHASGIANT(&nd);
3410	vp = nd.ni_vp;
3411	if (vp != NULL) {
3412		NDFREE(&nd, NDF_ONLY_PNBUF);
3413		/*
3414		 * XXX namei called with LOCKPARENT but not LOCKLEAF has
3415		 * the strange behaviour of leaving the vnode unlocked
3416		 * if the target is the same vnode as the parent.
3417		 */
3418		if (vp == nd.ni_dvp)
3419			vrele(nd.ni_dvp);
3420		else
3421			vput(nd.ni_dvp);
3422		vrele(vp);
3423		VFS_UNLOCK_GIANT(vfslocked);
3424		return (EEXIST);
3425	}
3426	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3427		NDFREE(&nd, NDF_ONLY_PNBUF);
3428		vput(nd.ni_dvp);
3429		VFS_UNLOCK_GIANT(vfslocked);
3430		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3431			return (error);
3432		goto restart;
3433	}
3434	VATTR_NULL(&vattr);
3435	vattr.va_type = VDIR;
3436	FILEDESC_LOCK_FAST(td->td_proc->p_fd);
3437	vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask;
3438	FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
3439#ifdef MAC
3440	error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
3441	    &vattr);
3442	if (error)
3443		goto out;
3444#endif
3445	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3446	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
3447#ifdef MAC
3448out:
3449#endif
3450	NDFREE(&nd, NDF_ONLY_PNBUF);
3451	vput(nd.ni_dvp);
3452	if (!error)
3453		vput(nd.ni_vp);
3454	vn_finished_write(mp);
3455	VFS_UNLOCK_GIANT(vfslocked);
3456	return (error);
3457}
3458
3459/*
3460 * Remove a directory file.
3461 */
3462#ifndef _SYS_SYSPROTO_H_
3463struct rmdir_args {
3464	char	*path;
3465};
3466#endif
3467int
3468rmdir(td, uap)
3469	struct thread *td;
3470	struct rmdir_args /* {
3471		char *path;
3472	} */ *uap;
3473{
3474
3475	return (kern_rmdir(td, uap->path, UIO_USERSPACE));
3476}
3477
3478int
3479kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg)
3480{
3481	struct mount *mp;
3482	struct vnode *vp;
3483	int error;
3484	struct nameidata nd;
3485	int vfslocked;
3486
3487restart:
3488	bwillwrite();
3489	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1,
3490	    pathseg, path, td);
3491	if ((error = namei(&nd)) != 0)
3492		return (error);
3493	vfslocked = NDHASGIANT(&nd);
3494	vp = nd.ni_vp;
3495	if (vp->v_type != VDIR) {
3496		error = ENOTDIR;
3497		goto out;
3498	}
3499	/*
3500	 * No rmdir "." please.
3501	 */
3502	if (nd.ni_dvp == vp) {
3503		error = EINVAL;
3504		goto out;
3505	}
3506	/*
3507	 * The root of a mounted filesystem cannot be deleted.
3508	 */
3509	if (vp->v_vflag & VV_ROOT) {
3510		error = EBUSY;
3511		goto out;
3512	}
3513#ifdef MAC
3514	error = mac_check_vnode_delete(td->td_ucred, nd.ni_dvp, vp,
3515	    &nd.ni_cnd);
3516	if (error)
3517		goto out;
3518#endif
3519	if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
3520		NDFREE(&nd, NDF_ONLY_PNBUF);
3521		vput(vp);
3522		if (nd.ni_dvp == vp)
3523			vrele(nd.ni_dvp);
3524		else
3525			vput(nd.ni_dvp);
3526		VFS_UNLOCK_GIANT(vfslocked);
3527		if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
3528			return (error);
3529		goto restart;
3530	}
3531	VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
3532	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
3533	error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3534	vn_finished_write(mp);
3535out:
3536	NDFREE(&nd, NDF_ONLY_PNBUF);
3537	vput(vp);
3538	if (nd.ni_dvp == vp)
3539		vrele(nd.ni_dvp);
3540	else
3541		vput(nd.ni_dvp);
3542	VFS_UNLOCK_GIANT(vfslocked);
3543	return (error);
3544}
3545
3546#ifdef COMPAT_43
3547/*
3548 * Read a block of directory entries in a filesystem independent format.
3549 */
3550#ifndef _SYS_SYSPROTO_H_
3551struct ogetdirentries_args {
3552	int	fd;
3553	char	*buf;
3554	u_int	count;
3555	long	*basep;
3556};
3557#endif
3558int
3559ogetdirentries(td, uap)
3560	struct thread *td;
3561	register struct ogetdirentries_args /* {
3562		int fd;
3563		char *buf;
3564		u_int count;
3565		long *basep;
3566	} */ *uap;
3567{
3568	struct vnode *vp;
3569	struct file *fp;
3570	struct uio auio, kuio;
3571	struct iovec aiov, kiov;
3572	struct dirent *dp, *edp;
3573	caddr_t dirbuf;
3574	int error, eofflag, readcnt, vfslocked;
3575	long loff;
3576
3577	/* XXX arbitrary sanity limit on `count'. */
3578	if (uap->count > 64 * 1024)
3579		return (EINVAL);
3580	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3581		return (error);
3582	if ((fp->f_flag & FREAD) == 0) {
3583		fdrop(fp, td);
3584		return (EBADF);
3585	}
3586	vp = fp->f_vnode;
3587unionread:
3588	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3589	if (vp->v_type != VDIR) {
3590		VFS_UNLOCK_GIANT(vfslocked);
3591		fdrop(fp, td);
3592		return (EINVAL);
3593	}
3594	aiov.iov_base = uap->buf;
3595	aiov.iov_len = uap->count;
3596	auio.uio_iov = &aiov;
3597	auio.uio_iovcnt = 1;
3598	auio.uio_rw = UIO_READ;
3599	auio.uio_segflg = UIO_USERSPACE;
3600	auio.uio_td = td;
3601	auio.uio_resid = uap->count;
3602	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3603	loff = auio.uio_offset = fp->f_offset;
3604#ifdef MAC
3605	error = mac_check_vnode_readdir(td->td_ucred, vp);
3606	if (error) {
3607		VOP_UNLOCK(vp, 0, td);
3608		VFS_UNLOCK_GIANT(vfslocked);
3609		fdrop(fp, td);
3610		return (error);
3611	}
3612#endif
3613#	if (BYTE_ORDER != LITTLE_ENDIAN)
3614		if (vp->v_mount->mnt_maxsymlinklen <= 0) {
3615			error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
3616			    NULL, NULL);
3617			fp->f_offset = auio.uio_offset;
3618		} else
3619#	endif
3620	{
3621		kuio = auio;
3622		kuio.uio_iov = &kiov;
3623		kuio.uio_segflg = UIO_SYSSPACE;
3624		kiov.iov_len = uap->count;
3625		MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);
3626		kiov.iov_base = dirbuf;
3627		error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
3628			    NULL, NULL);
3629		fp->f_offset = kuio.uio_offset;
3630		if (error == 0) {
3631			readcnt = uap->count - kuio.uio_resid;
3632			edp = (struct dirent *)&dirbuf[readcnt];
3633			for (dp = (struct dirent *)dirbuf; dp < edp; ) {
3634#				if (BYTE_ORDER == LITTLE_ENDIAN)
3635					/*
3636					 * The expected low byte of
3637					 * dp->d_namlen is our dp->d_type.
3638					 * The high MBZ byte of dp->d_namlen
3639					 * is our dp->d_namlen.
3640					 */
3641					dp->d_type = dp->d_namlen;
3642					dp->d_namlen = 0;
3643#				else
3644					/*
3645					 * The dp->d_type is the high byte
3646					 * of the expected dp->d_namlen,
3647					 * so must be zero'ed.
3648					 */
3649					dp->d_type = 0;
3650#				endif
3651				if (dp->d_reclen > 0) {
3652					dp = (struct dirent *)
3653					    ((char *)dp + dp->d_reclen);
3654				} else {
3655					error = EIO;
3656					break;
3657				}
3658			}
3659			if (dp >= edp)
3660				error = uiomove(dirbuf, readcnt, &auio);
3661		}
3662		FREE(dirbuf, M_TEMP);
3663	}
3664	VOP_UNLOCK(vp, 0, td);
3665	if (error) {
3666		VFS_UNLOCK_GIANT(vfslocked);
3667		fdrop(fp, td);
3668		return (error);
3669	}
3670	if (uap->count == auio.uio_resid) {
3671		if (union_dircheckp) {
3672			error = union_dircheckp(td, &vp, fp);
3673			if (error == -1) {
3674				VFS_UNLOCK_GIANT(vfslocked);
3675				goto unionread;
3676			}
3677			if (error) {
3678				VFS_UNLOCK_GIANT(vfslocked);
3679				fdrop(fp, td);
3680				return (error);
3681			}
3682		}
3683		/*
3684		 * XXX We could delay dropping the lock above but
3685		 * union_dircheckp complicates things.
3686		 */
3687		vn_lock(vp, LK_EXCLUSIVE|LK_RETRY, td);
3688		if ((vp->v_vflag & VV_ROOT) &&
3689		    (vp->v_mount->mnt_flag & MNT_UNION)) {
3690			struct vnode *tvp = vp;
3691			vp = vp->v_mount->mnt_vnodecovered;
3692			VREF(vp);
3693			fp->f_vnode = vp;
3694			fp->f_data = vp;
3695			fp->f_offset = 0;
3696			vput(tvp);
3697			VFS_UNLOCK_GIANT(vfslocked);
3698			goto unionread;
3699		}
3700		VOP_UNLOCK(vp, 0, td);
3701	}
3702	VFS_UNLOCK_GIANT(vfslocked);
3703	error = copyout(&loff, uap->basep, sizeof(long));
3704	fdrop(fp, td);
3705	td->td_retval[0] = uap->count - auio.uio_resid;
3706	return (error);
3707}
3708#endif /* COMPAT_43 */
3709
3710/*
3711 * Read a block of directory entries in a filesystem independent format.
3712 */
3713#ifndef _SYS_SYSPROTO_H_
3714struct getdirentries_args {
3715	int	fd;
3716	char	*buf;
3717	u_int	count;
3718	long	*basep;
3719};
3720#endif
3721int
3722getdirentries(td, uap)
3723	struct thread *td;
3724	register struct getdirentries_args /* {
3725		int fd;
3726		char *buf;
3727		u_int count;
3728		long *basep;
3729	} */ *uap;
3730{
3731	struct vnode *vp;
3732	struct file *fp;
3733	struct uio auio;
3734	struct iovec aiov;
3735	int vfslocked;
3736	long loff;
3737	int error, eofflag;
3738
3739	AUDIT_ARG(fd, uap->fd);
3740	if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
3741		return (error);
3742	if ((fp->f_flag & FREAD) == 0) {
3743		fdrop(fp, td);
3744		return (EBADF);
3745	}
3746	vp = fp->f_vnode;
3747unionread:
3748	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
3749	if (vp->v_type != VDIR) {
3750		error = EINVAL;
3751		goto fail;
3752	}
3753	aiov.iov_base = uap->buf;
3754	aiov.iov_len = uap->count;
3755	auio.uio_iov = &aiov;
3756	auio.uio_iovcnt = 1;
3757	auio.uio_rw = UIO_READ;
3758	auio.uio_segflg = UIO_USERSPACE;
3759	auio.uio_td = td;
3760	auio.uio_resid = uap->count;
3761	/* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
3762	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3763	AUDIT_ARG(vnode, vp, ARG_VNODE1);
3764	loff = auio.uio_offset = fp->f_offset;
3765#ifdef MAC
3766	error = mac_check_vnode_readdir(td->td_ucred, vp);
3767	if (error == 0)
3768#endif
3769		error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL,
3770		    NULL);
3771	fp->f_offset = auio.uio_offset;
3772	VOP_UNLOCK(vp, 0, td);
3773	if (error)
3774		goto fail;
3775	if (uap->count == auio.uio_resid) {
3776		if (union_dircheckp) {
3777			error = union_dircheckp(td, &vp, fp);
3778			if (error == -1) {
3779				VFS_UNLOCK_GIANT(vfslocked);
3780				goto unionread;
3781			}
3782			if (error)
3783				goto fail;
3784		}
3785		/*
3786		 * XXX We could delay dropping the lock above but
3787		 * union_dircheckp complicates things.
3788		 */
3789		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3790		if ((vp->v_vflag & VV_ROOT) &&
3791		    (vp->v_mount->mnt_flag & MNT_UNION)) {
3792			struct vnode *tvp = vp;
3793			vp = vp->v_mount->mnt_vnodecovered;
3794			VREF(vp);
3795			fp->f_vnode = vp;
3796			fp->f_data = vp;
3797			fp->f_offset = 0;
3798			vput(tvp);
3799			VFS_UNLOCK_GIANT(vfslocked);
3800			goto unionread;
3801		}
3802		VOP_UNLOCK(vp, 0, td);
3803	}
3804	if (uap->basep != NULL) {
3805		error = copyout(&loff, uap->basep, sizeof(long));
3806	}
3807	td->td_retval[0] = uap->count - auio.uio_resid;
3808fail:
3809	VFS_UNLOCK_GIANT(vfslocked);
3810	fdrop(fp, td);
3811	return (error);
3812}
3813#ifndef _SYS_SYSPROTO_H_
3814struct getdents_args {
3815	int fd;
3816	char *buf;
3817	size_t count;
3818};
3819#endif
3820int
3821getdents(td, uap)
3822	struct thread *td;
3823	register struct getdents_args /* {
3824		int fd;
3825		char *buf;
3826		u_int count;
3827	} */ *uap;
3828{
3829	struct getdirentries_args ap;
3830	ap.fd = uap->fd;
3831	ap.buf = uap->buf;
3832	ap.count = uap->count;
3833	ap.basep = NULL;
3834	return (getdirentries(td, &ap));
3835}
3836
3837/*
3838 * Set the mode mask for creation of filesystem nodes.
3839 *
3840 * MP SAFE
3841 */
3842#ifndef _SYS_SYSPROTO_H_
3843struct umask_args {
3844	int	newmask;
3845};
3846#endif
3847int
3848umask(td, uap)
3849	struct thread *td;
3850	struct umask_args /* {
3851		int newmask;
3852	} */ *uap;
3853{
3854	register struct filedesc *fdp;
3855
3856	FILEDESC_LOCK_FAST(td->td_proc->p_fd);
3857	fdp = td->td_proc->p_fd;
3858	td->td_retval[0] = fdp->fd_cmask;
3859	fdp->fd_cmask = uap->newmask & ALLPERMS;
3860	FILEDESC_UNLOCK_FAST(td->td_proc->p_fd);
3861	return (0);
3862}
3863
3864/*
3865 * Void all references to file by ripping underlying filesystem
3866 * away from vnode.
3867 */
3868#ifndef _SYS_SYSPROTO_H_
3869struct revoke_args {
3870	char	*path;
3871};
3872#endif
3873int
3874revoke(td, uap)
3875	struct thread *td;
3876	register struct revoke_args /* {
3877		char *path;
3878	} */ *uap;
3879{
3880	struct vnode *vp;
3881	struct vattr vattr;
3882	int error;
3883	struct nameidata nd;
3884	int vfslocked;
3885
3886	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
3887	    UIO_USERSPACE, uap->path, td);
3888	if ((error = namei(&nd)) != 0)
3889		return (error);
3890	vfslocked = NDHASGIANT(&nd);
3891	vp = nd.ni_vp;
3892	NDFREE(&nd, NDF_ONLY_PNBUF);
3893	if (vp->v_type != VCHR) {
3894		error = EINVAL;
3895		goto out;
3896	}
3897#ifdef MAC
3898	error = mac_check_vnode_revoke(td->td_ucred, vp);
3899	if (error)
3900		goto out;
3901#endif
3902	error = VOP_GETATTR(vp, &vattr, td->td_ucred, td);
3903	if (error)
3904		goto out;
3905	if (td->td_ucred->cr_uid != vattr.va_uid) {
3906		error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN,
3907		    SUSER_ALLOWJAIL);
3908		if (error)
3909			goto out;
3910	}
3911	if (vcount(vp) > 1)
3912		VOP_REVOKE(vp, REVOKEALL);
3913out:
3914	vput(vp);
3915	VFS_UNLOCK_GIANT(vfslocked);
3916	return (error);
3917}
3918
3919/*
3920 * Convert a user file descriptor to a kernel file entry.
3921 * A reference on the file entry is held upon returning.
3922 */
3923int
3924getvnode(fdp, fd, fpp)
3925	struct filedesc *fdp;
3926	int fd;
3927	struct file **fpp;
3928{
3929	int error;
3930	struct file *fp;
3931
3932	fp = NULL;
3933	if (fdp == NULL)
3934		error = EBADF;
3935	else {
3936		FILEDESC_LOCK(fdp);
3937		if ((u_int)fd >= fdp->fd_nfiles ||
3938		    (fp = fdp->fd_ofiles[fd]) == NULL)
3939			error = EBADF;
3940		else if (fp->f_vnode == NULL) {
3941			fp = NULL;
3942			error = EINVAL;
3943		} else {
3944			fhold(fp);
3945			error = 0;
3946		}
3947		FILEDESC_UNLOCK(fdp);
3948	}
3949	*fpp = fp;
3950	return (error);
3951}
3952
3953/*
3954 * Get (NFS) file handle
3955 */
3956#ifndef _SYS_SYSPROTO_H_
3957struct lgetfh_args {
3958	char	*fname;
3959	fhandle_t *fhp;
3960};
3961#endif
3962int
3963lgetfh(td, uap)
3964	struct thread *td;
3965	register struct lgetfh_args *uap;
3966{
3967	struct nameidata nd;
3968	fhandle_t fh;
3969	register struct vnode *vp;
3970	int vfslocked;
3971	int error;
3972
3973	error = priv_check(td, PRIV_VFS_GETFH);
3974	if (error)
3975		return (error);
3976	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
3977	    UIO_USERSPACE, uap->fname, td);
3978	error = namei(&nd);
3979	if (error)
3980		return (error);
3981	vfslocked = NDHASGIANT(&nd);
3982	NDFREE(&nd, NDF_ONLY_PNBUF);
3983	vp = nd.ni_vp;
3984	bzero(&fh, sizeof(fh));
3985	fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
3986	error = VFS_VPTOFH(vp, &fh.fh_fid);
3987	vput(vp);
3988	VFS_UNLOCK_GIANT(vfslocked);
3989	if (error)
3990		return (error);
3991	error = copyout(&fh, uap->fhp, sizeof (fh));
3992	return (error);
3993}
3994
3995#ifndef _SYS_SYSPROTO_H_
3996struct getfh_args {
3997	char	*fname;
3998	fhandle_t *fhp;
3999};
4000#endif
4001int
4002getfh(td, uap)
4003	struct thread *td;
4004	register struct getfh_args *uap;
4005{
4006	struct nameidata nd;
4007	fhandle_t fh;
4008	register struct vnode *vp;
4009	int vfslocked;
4010	int error;
4011
4012	error = priv_check(td, PRIV_VFS_GETFH);
4013	if (error)
4014		return (error);
4015	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
4016	    UIO_USERSPACE, uap->fname, td);
4017	error = namei(&nd);
4018	if (error)
4019		return (error);
4020	vfslocked = NDHASGIANT(&nd);
4021	NDFREE(&nd, NDF_ONLY_PNBUF);
4022	vp = nd.ni_vp;
4023	bzero(&fh, sizeof(fh));
4024	fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
4025	error = VFS_VPTOFH(vp, &fh.fh_fid);
4026	vput(vp);
4027	VFS_UNLOCK_GIANT(vfslocked);
4028	if (error)
4029		return (error);
4030	error = copyout(&fh, uap->fhp, sizeof (fh));
4031	return (error);
4032}
4033
4034/*
4035 * syscall for the rpc.lockd to use to translate a NFS file handle into an
4036 * open descriptor.
4037 *
4038 * warning: do not remove the priv_check() call or this becomes one giant
4039 * security hole.
4040 *
4041 * MP SAFE
4042 */
4043#ifndef _SYS_SYSPROTO_H_
4044struct fhopen_args {
4045	const struct fhandle *u_fhp;
4046	int flags;
4047};
4048#endif
4049int
4050fhopen(td, uap)
4051	struct thread *td;
4052	struct fhopen_args /* {
4053		const struct fhandle *u_fhp;
4054		int flags;
4055	} */ *uap;
4056{
4057	struct proc *p = td->td_proc;
4058	struct mount *mp;
4059	struct vnode *vp;
4060	struct fhandle fhp;
4061	struct vattr vat;
4062	struct vattr *vap = &vat;
4063	struct flock lf;
4064	struct file *fp;
4065	register struct filedesc *fdp = p->p_fd;
4066	int fmode, mode, error, type;
4067	struct file *nfp;
4068	int vfslocked;
4069	int indx;
4070
4071	error = priv_check(td, PRIV_VFS_FHOPEN);
4072	if (error)
4073		return (error);
4074	fmode = FFLAGS(uap->flags);
4075	/* why not allow a non-read/write open for our lockd? */
4076	if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
4077		return (EINVAL);
4078	error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
4079	if (error)
4080		return(error);
4081	/* find the mount point */
4082	mp = vfs_getvfs(&fhp.fh_fsid);
4083	if (mp == NULL)
4084		return (ESTALE);
4085	vfslocked = VFS_LOCK_GIANT(mp);
4086	/* now give me my vnode, it gets returned to me locked */
4087	error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp);
4088	if (error)
4089		goto out;
4090	/*
4091	 * from now on we have to make sure not
4092	 * to forget about the vnode
4093	 * any error that causes an abort must vput(vp)
4094	 * just set error = err and 'goto bad;'.
4095	 */
4096
4097	/*
4098	 * from vn_open
4099	 */
4100	if (vp->v_type == VLNK) {
4101		error = EMLINK;
4102		goto bad;
4103	}
4104	if (vp->v_type == VSOCK) {
4105		error = EOPNOTSUPP;
4106		goto bad;
4107	}
4108	mode = 0;
4109	if (fmode & (FWRITE | O_TRUNC)) {
4110		if (vp->v_type == VDIR) {
4111			error = EISDIR;
4112			goto bad;
4113		}
4114		error = vn_writechk(vp);
4115		if (error)
4116			goto bad;
4117		mode |= VWRITE;
4118	}
4119	if (fmode & FREAD)
4120		mode |= VREAD;
4121	if (fmode & O_APPEND)
4122		mode |= VAPPEND;
4123#ifdef MAC
4124	error = mac_check_vnode_open(td->td_ucred, vp, mode);
4125	if (error)
4126		goto bad;
4127#endif
4128	if (mode) {
4129		error = VOP_ACCESS(vp, mode, td->td_ucred, td);
4130		if (error)
4131			goto bad;
4132	}
4133	if (fmode & O_TRUNC) {
4134		VOP_UNLOCK(vp, 0, td);				/* XXX */
4135		if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
4136			vrele(vp);
4137			goto out;
4138		}
4139		VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4140		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);	/* XXX */
4141#ifdef MAC
4142		/*
4143		 * We don't yet have fp->f_cred, so use td->td_ucred, which
4144		 * should be right.
4145		 */
4146		error = mac_check_vnode_write(td->td_ucred, td->td_ucred, vp);
4147		if (error == 0) {
4148#endif
4149			VATTR_NULL(vap);
4150			vap->va_size = 0;
4151			error = VOP_SETATTR(vp, vap, td->td_ucred, td);
4152#ifdef MAC
4153		}
4154#endif
4155		vn_finished_write(mp);
4156		if (error)
4157			goto bad;
4158	}
4159	error = VOP_OPEN(vp, fmode, td->td_ucred, td, -1);
4160	if (error)
4161		goto bad;
4162
4163	if (fmode & FWRITE)
4164		vp->v_writecount++;
4165
4166	/*
4167	 * end of vn_open code
4168	 */
4169
4170	if ((error = falloc(td, &nfp, &indx)) != 0) {
4171		if (fmode & FWRITE)
4172			vp->v_writecount--;
4173		goto bad;
4174	}
4175	/* An extra reference on `nfp' has been held for us by falloc(). */
4176	fp = nfp;
4177
4178	nfp->f_vnode = vp;
4179	nfp->f_data = vp;
4180	nfp->f_flag = fmode & FMASK;
4181	nfp->f_ops = &vnops;
4182	nfp->f_type = DTYPE_VNODE;
4183	if (fmode & (O_EXLOCK | O_SHLOCK)) {
4184		lf.l_whence = SEEK_SET;
4185		lf.l_start = 0;
4186		lf.l_len = 0;
4187		if (fmode & O_EXLOCK)
4188			lf.l_type = F_WRLCK;
4189		else
4190			lf.l_type = F_RDLCK;
4191		type = F_FLOCK;
4192		if ((fmode & FNONBLOCK) == 0)
4193			type |= F_WAIT;
4194		VOP_UNLOCK(vp, 0, td);
4195		if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
4196			    type)) != 0) {
4197			/*
4198			 * The lock request failed.  Normally close the
4199			 * descriptor but handle the case where someone might
4200			 * have dup()d or close()d it when we weren't looking.
4201			 */
4202			fdclose(fdp, fp, indx, td);
4203
4204			/*
4205			 * release our private reference
4206			 */
4207			fdrop(fp, td);
4208			goto out;
4209		}
4210		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4211		fp->f_flag |= FHASLOCK;
4212	}
4213
4214	VOP_UNLOCK(vp, 0, td);
4215	fdrop(fp, td);
4216	vfs_rel(mp);
4217	VFS_UNLOCK_GIANT(vfslocked);
4218	td->td_retval[0] = indx;
4219	return (0);
4220
4221bad:
4222	vput(vp);
4223out:
4224	vfs_rel(mp);
4225	VFS_UNLOCK_GIANT(vfslocked);
4226	return (error);
4227}
4228
4229/*
4230 * Stat an (NFS) file handle.
4231 *
4232 * MP SAFE
4233 */
4234#ifndef _SYS_SYSPROTO_H_
4235struct fhstat_args {
4236	struct fhandle *u_fhp;
4237	struct stat *sb;
4238};
4239#endif
4240int
4241fhstat(td, uap)
4242	struct thread *td;
4243	register struct fhstat_args /* {
4244		struct fhandle *u_fhp;
4245		struct stat *sb;
4246	} */ *uap;
4247{
4248	struct stat sb;
4249	fhandle_t fh;
4250	struct mount *mp;
4251	struct vnode *vp;
4252	int vfslocked;
4253	int error;
4254
4255	error = priv_check(td, PRIV_VFS_FHSTAT);
4256	if (error)
4257		return (error);
4258	error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4259	if (error)
4260		return (error);
4261	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
4262		return (ESTALE);
4263	vfslocked = VFS_LOCK_GIANT(mp);
4264	if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) {
4265		vfs_rel(mp);
4266		VFS_UNLOCK_GIANT(vfslocked);
4267		return (error);
4268	}
4269	error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
4270	vput(vp);
4271	vfs_rel(mp);
4272	VFS_UNLOCK_GIANT(vfslocked);
4273	if (error)
4274		return (error);
4275	error = copyout(&sb, uap->sb, sizeof(sb));
4276	return (error);
4277}
4278
4279/*
4280 * Implement fstatfs() for (NFS) file handles.
4281 *
4282 * MP SAFE
4283 */
4284#ifndef _SYS_SYSPROTO_H_
4285struct fhstatfs_args {
4286	struct fhandle *u_fhp;
4287	struct statfs *buf;
4288};
4289#endif
4290int
4291fhstatfs(td, uap)
4292	struct thread *td;
4293	struct fhstatfs_args /* {
4294		struct fhandle *u_fhp;
4295		struct statfs *buf;
4296	} */ *uap;
4297{
4298	struct statfs sf;
4299	fhandle_t fh;
4300	int error;
4301
4302	error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4303	if (error)
4304		return (error);
4305	error = kern_fhstatfs(td, fh, &sf);
4306	if (error)
4307		return (error);
4308	return (copyout(&sf, uap->buf, sizeof(sf)));
4309}
4310
4311int
4312kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
4313{
4314	struct statfs *sp;
4315	struct mount *mp;
4316	struct vnode *vp;
4317	int vfslocked;
4318	int error;
4319
4320	error = priv_check(td, PRIV_VFS_FHSTATFS);
4321	if (error)
4322		return (error);
4323	if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
4324		return (ESTALE);
4325	vfslocked = VFS_LOCK_GIANT(mp);
4326	error = VFS_FHTOVP(mp, &fh.fh_fid, &vp);
4327	if (error) {
4328		VFS_UNLOCK_GIANT(vfslocked);
4329		vfs_rel(mp);
4330		return (error);
4331	}
4332	vput(vp);
4333	error = prison_canseemount(td->td_ucred, mp);
4334	if (error)
4335		goto out;
4336#ifdef MAC
4337	error = mac_check_mount_stat(td->td_ucred, mp);
4338	if (error)
4339		goto out;
4340#endif
4341	/*
4342	 * Set these in case the underlying filesystem fails to do so.
4343	 */
4344	sp = &mp->mnt_stat;
4345	sp->f_version = STATFS_VERSION;
4346	sp->f_namemax = NAME_MAX;
4347	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
4348	error = VFS_STATFS(mp, sp, td);
4349	if (error == 0)
4350		*buf = *sp;
4351out:
4352	vfs_rel(mp);
4353	VFS_UNLOCK_GIANT(vfslocked);
4354	return (error);
4355}
4356
4357/*
4358 * Syscall to push extended attribute configuration information into the
4359 * VFS.  Accepts a path, which it converts to a mountpoint, as well as
4360 * a command (int cmd), and attribute name and misc data.  For now, the
4361 * attribute name is left in userspace for consumption by the VFS_op.
4362 * It will probably be changed to be copied into sysspace by the
4363 * syscall in the future, once issues with various consumers of the
4364 * attribute code have raised their hands.
4365 *
4366 * Currently this is used only by UFS Extended Attributes.
4367 */
4368int
4369extattrctl(td, uap)
4370	struct thread *td;
4371	struct extattrctl_args /* {
4372		const char *path;
4373		int cmd;
4374		const char *filename;
4375		int attrnamespace;
4376		const char *attrname;
4377	} */ *uap;
4378{
4379	struct vnode *filename_vp;
4380	struct nameidata nd;
4381	struct mount *mp, *mp_writable;
4382	char attrname[EXTATTR_MAXNAMELEN];
4383	int vfslocked, fnvfslocked, error;
4384
4385	AUDIT_ARG(cmd, uap->cmd);
4386	AUDIT_ARG(value, uap->attrnamespace);
4387	/*
4388	 * uap->attrname is not always defined.  We check again later when we
4389	 * invoke the VFS call so as to pass in NULL there if needed.
4390	 */
4391	if (uap->attrname != NULL) {
4392		error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
4393		    NULL);
4394		if (error)
4395			return (error);
4396	}
4397	AUDIT_ARG(text, attrname);
4398
4399	vfslocked = fnvfslocked = 0;
4400	/*
4401	 * uap->filename is not always defined.  If it is, grab a vnode lock,
4402	 * which VFS_EXTATTRCTL() will later release.
4403	 */
4404	filename_vp = NULL;
4405	if (uap->filename != NULL) {
4406		NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF |
4407		    AUDITVNODE2, UIO_USERSPACE, uap->filename, td);
4408		error = namei(&nd);
4409		if (error)
4410			return (error);
4411		fnvfslocked = NDHASGIANT(&nd);
4412		filename_vp = nd.ni_vp;
4413		NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
4414	}
4415
4416	/* uap->path is always defined. */
4417	NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
4418	    uap->path, td);
4419	error = namei(&nd);
4420	if (error) {
4421		if (filename_vp != NULL)
4422			vput(filename_vp);
4423		goto out;
4424	}
4425	vfslocked = NDHASGIANT(&nd);
4426	mp = nd.ni_vp->v_mount;
4427	error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
4428	NDFREE(&nd, 0);
4429	if (error) {
4430		if (filename_vp != NULL)
4431			vput(filename_vp);
4432		goto out;
4433	}
4434
4435	error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
4436	    uap->attrname != NULL ? attrname : NULL, td);
4437
4438	vn_finished_write(mp_writable);
4439	/*
4440	 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd,
4441	 * filename_vp, so vrele it if it is defined.
4442	 */
4443	if (filename_vp != NULL)
4444		vrele(filename_vp);
4445out:
4446	VFS_UNLOCK_GIANT(fnvfslocked);
4447	VFS_UNLOCK_GIANT(vfslocked);
4448	return (error);
4449}
4450
4451/*-
4452 * Set a named extended attribute on a file or directory
4453 *
4454 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4455 *            kernelspace string pointer "attrname", userspace buffer
4456 *            pointer "data", buffer length "nbytes", thread "td".
4457 * Returns: 0 on success, an error number otherwise
4458 * Locks: none
4459 * References: vp must be a valid reference for the duration of the call
4460 */
4461static int
4462extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4463    void *data, size_t nbytes, struct thread *td)
4464{
4465	struct mount *mp;
4466	struct uio auio;
4467	struct iovec aiov;
4468	ssize_t cnt;
4469	int error;
4470
4471	VFS_ASSERT_GIANT(vp->v_mount);
4472	error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4473	if (error)
4474		return (error);
4475	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4476	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4477
4478	aiov.iov_base = data;
4479	aiov.iov_len = nbytes;
4480	auio.uio_iov = &aiov;
4481	auio.uio_iovcnt = 1;
4482	auio.uio_offset = 0;
4483	if (nbytes > INT_MAX) {
4484		error = EINVAL;
4485		goto done;
4486	}
4487	auio.uio_resid = nbytes;
4488	auio.uio_rw = UIO_WRITE;
4489	auio.uio_segflg = UIO_USERSPACE;
4490	auio.uio_td = td;
4491	cnt = nbytes;
4492
4493#ifdef MAC
4494	error = mac_check_vnode_setextattr(td->td_ucred, vp, attrnamespace,
4495	    attrname, &auio);
4496	if (error)
4497		goto done;
4498#endif
4499
4500	error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
4501	    td->td_ucred, td);
4502	cnt -= auio.uio_resid;
4503	td->td_retval[0] = cnt;
4504
4505done:
4506	VOP_UNLOCK(vp, 0, td);
4507	vn_finished_write(mp);
4508	return (error);
4509}
4510
4511int
4512extattr_set_fd(td, uap)
4513	struct thread *td;
4514	struct extattr_set_fd_args /* {
4515		int fd;
4516		int attrnamespace;
4517		const char *attrname;
4518		void *data;
4519		size_t nbytes;
4520	} */ *uap;
4521{
4522	struct file *fp;
4523	char attrname[EXTATTR_MAXNAMELEN];
4524	int vfslocked, error;
4525
4526	AUDIT_ARG(fd, uap->fd);
4527	AUDIT_ARG(value, uap->attrnamespace);
4528	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4529	if (error)
4530		return (error);
4531	AUDIT_ARG(text, attrname);
4532
4533	error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4534	if (error)
4535		return (error);
4536
4537	vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
4538	error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
4539	    attrname, uap->data, uap->nbytes, td);
4540	fdrop(fp, td);
4541	VFS_UNLOCK_GIANT(vfslocked);
4542
4543	return (error);
4544}
4545
4546int
4547extattr_set_file(td, uap)
4548	struct thread *td;
4549	struct extattr_set_file_args /* {
4550		const char *path;
4551		int attrnamespace;
4552		const char *attrname;
4553		void *data;
4554		size_t nbytes;
4555	} */ *uap;
4556{
4557	struct nameidata nd;
4558	char attrname[EXTATTR_MAXNAMELEN];
4559	int vfslocked, error;
4560
4561	AUDIT_ARG(value, uap->attrnamespace);
4562	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4563	if (error)
4564		return (error);
4565	AUDIT_ARG(text, attrname);
4566
4567	NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
4568	    uap->path, td);
4569	error = namei(&nd);
4570	if (error)
4571		return (error);
4572	NDFREE(&nd, NDF_ONLY_PNBUF);
4573
4574	vfslocked = NDHASGIANT(&nd);
4575	error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
4576	    uap->data, uap->nbytes, td);
4577
4578	vrele(nd.ni_vp);
4579	VFS_UNLOCK_GIANT(vfslocked);
4580	return (error);
4581}
4582
4583int
4584extattr_set_link(td, uap)
4585	struct thread *td;
4586	struct extattr_set_link_args /* {
4587		const char *path;
4588		int attrnamespace;
4589		const char *attrname;
4590		void *data;
4591		size_t nbytes;
4592	} */ *uap;
4593{
4594	struct nameidata nd;
4595	char attrname[EXTATTR_MAXNAMELEN];
4596	int vfslocked, error;
4597
4598	AUDIT_ARG(value, uap->attrnamespace);
4599	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4600	if (error)
4601		return (error);
4602	AUDIT_ARG(text, attrname);
4603
4604	NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
4605	    uap->path, td);
4606	error = namei(&nd);
4607	if (error)
4608		return (error);
4609	NDFREE(&nd, NDF_ONLY_PNBUF);
4610
4611	vfslocked = NDHASGIANT(&nd);
4612	error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
4613	    uap->data, uap->nbytes, td);
4614
4615	vrele(nd.ni_vp);
4616	VFS_UNLOCK_GIANT(vfslocked);
4617	return (error);
4618}
4619
4620/*-
4621 * Get a named extended attribute on a file or directory
4622 *
4623 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4624 *            kernelspace string pointer "attrname", userspace buffer
4625 *            pointer "data", buffer length "nbytes", thread "td".
4626 * Returns: 0 on success, an error number otherwise
4627 * Locks: none
4628 * References: vp must be a valid reference for the duration of the call
4629 */
4630static int
4631extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4632    void *data, size_t nbytes, struct thread *td)
4633{
4634	struct uio auio, *auiop;
4635	struct iovec aiov;
4636	ssize_t cnt;
4637	size_t size, *sizep;
4638	int error;
4639
4640	VFS_ASSERT_GIANT(vp->v_mount);
4641	VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4642	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4643
4644	/*
4645	 * Slightly unusual semantics: if the user provides a NULL data
4646	 * pointer, they don't want to receive the data, just the
4647	 * maximum read length.
4648	 */
4649	auiop = NULL;
4650	sizep = NULL;
4651	cnt = 0;
4652	if (data != NULL) {
4653		aiov.iov_base = data;
4654		aiov.iov_len = nbytes;
4655		auio.uio_iov = &aiov;
4656		auio.uio_iovcnt = 1;
4657		auio.uio_offset = 0;
4658		if (nbytes > INT_MAX) {
4659			error = EINVAL;
4660			goto done;
4661		}
4662		auio.uio_resid = nbytes;
4663		auio.uio_rw = UIO_READ;
4664		auio.uio_segflg = UIO_USERSPACE;
4665		auio.uio_td = td;
4666		auiop = &auio;
4667		cnt = nbytes;
4668	} else
4669		sizep = &size;
4670
4671#ifdef MAC
4672	error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace,
4673	    attrname, &auio);
4674	if (error)
4675		goto done;
4676#endif
4677
4678	error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
4679	    td->td_ucred, td);
4680
4681	if (auiop != NULL) {
4682		cnt -= auio.uio_resid;
4683		td->td_retval[0] = cnt;
4684	} else
4685		td->td_retval[0] = size;
4686
4687done:
4688	VOP_UNLOCK(vp, 0, td);
4689	return (error);
4690}
4691
4692int
4693extattr_get_fd(td, uap)
4694	struct thread *td;
4695	struct extattr_get_fd_args /* {
4696		int fd;
4697		int attrnamespace;
4698		const char *attrname;
4699		void *data;
4700		size_t nbytes;
4701	} */ *uap;
4702{
4703	struct file *fp;
4704	char attrname[EXTATTR_MAXNAMELEN];
4705	int vfslocked, error;
4706
4707	AUDIT_ARG(fd, uap->fd);
4708	AUDIT_ARG(value, uap->attrnamespace);
4709	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4710	if (error)
4711		return (error);
4712	AUDIT_ARG(text, attrname);
4713
4714	error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4715	if (error)
4716		return (error);
4717
4718	vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
4719	error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
4720	    attrname, uap->data, uap->nbytes, td);
4721
4722	fdrop(fp, td);
4723	VFS_UNLOCK_GIANT(vfslocked);
4724	return (error);
4725}
4726
4727int
4728extattr_get_file(td, uap)
4729	struct thread *td;
4730	struct extattr_get_file_args /* {
4731		const char *path;
4732		int attrnamespace;
4733		const char *attrname;
4734		void *data;
4735		size_t nbytes;
4736	} */ *uap;
4737{
4738	struct nameidata nd;
4739	char attrname[EXTATTR_MAXNAMELEN];
4740	int vfslocked, error;
4741
4742	AUDIT_ARG(value, uap->attrnamespace);
4743	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4744	if (error)
4745		return (error);
4746	AUDIT_ARG(text, attrname);
4747
4748	NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
4749	    uap->path, td);
4750	error = namei(&nd);
4751	if (error)
4752		return (error);
4753	NDFREE(&nd, NDF_ONLY_PNBUF);
4754
4755	vfslocked = NDHASGIANT(&nd);
4756	error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4757	    uap->data, uap->nbytes, td);
4758
4759	vrele(nd.ni_vp);
4760	VFS_UNLOCK_GIANT(vfslocked);
4761	return (error);
4762}
4763
4764int
4765extattr_get_link(td, uap)
4766	struct thread *td;
4767	struct extattr_get_link_args /* {
4768		const char *path;
4769		int attrnamespace;
4770		const char *attrname;
4771		void *data;
4772		size_t nbytes;
4773	} */ *uap;
4774{
4775	struct nameidata nd;
4776	char attrname[EXTATTR_MAXNAMELEN];
4777	int vfslocked, error;
4778
4779	AUDIT_ARG(value, uap->attrnamespace);
4780	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4781	if (error)
4782		return (error);
4783	AUDIT_ARG(text, attrname);
4784
4785	NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
4786	    uap->path, td);
4787	error = namei(&nd);
4788	if (error)
4789		return (error);
4790	NDFREE(&nd, NDF_ONLY_PNBUF);
4791
4792	vfslocked = NDHASGIANT(&nd);
4793	error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
4794	    uap->data, uap->nbytes, td);
4795
4796	vrele(nd.ni_vp);
4797	VFS_UNLOCK_GIANT(vfslocked);
4798	return (error);
4799}
4800
4801/*
4802 * extattr_delete_vp(): Delete a named extended attribute on a file or
4803 *                      directory
4804 *
4805 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
4806 *            kernelspace string pointer "attrname", proc "p"
4807 * Returns: 0 on success, an error number otherwise
4808 * Locks: none
4809 * References: vp must be a valid reference for the duration of the call
4810 */
4811static int
4812extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
4813    struct thread *td)
4814{
4815	struct mount *mp;
4816	int error;
4817
4818	VFS_ASSERT_GIANT(vp->v_mount);
4819	error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4820	if (error)
4821		return (error);
4822	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
4823	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4824
4825#ifdef MAC
4826	error = mac_check_vnode_deleteextattr(td->td_ucred, vp, attrnamespace,
4827	    attrname);
4828	if (error)
4829		goto done;
4830#endif
4831
4832	error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, td->td_ucred,
4833	    td);
4834	if (error == EOPNOTSUPP)
4835		error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
4836		    td->td_ucred, td);
4837#ifdef MAC
4838done:
4839#endif
4840	VOP_UNLOCK(vp, 0, td);
4841	vn_finished_write(mp);
4842	return (error);
4843}
4844
4845int
4846extattr_delete_fd(td, uap)
4847	struct thread *td;
4848	struct extattr_delete_fd_args /* {
4849		int fd;
4850		int attrnamespace;
4851		const char *attrname;
4852	} */ *uap;
4853{
4854	struct file *fp;
4855	char attrname[EXTATTR_MAXNAMELEN];
4856	int vfslocked, error;
4857
4858	AUDIT_ARG(fd, uap->fd);
4859	AUDIT_ARG(value, uap->attrnamespace);
4860	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4861	if (error)
4862		return (error);
4863	AUDIT_ARG(text, attrname);
4864
4865	error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
4866	if (error)
4867		return (error);
4868
4869	vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
4870	error = extattr_delete_vp(fp->f_vnode, uap->attrnamespace,
4871	    attrname, td);
4872	fdrop(fp, td);
4873	VFS_UNLOCK_GIANT(vfslocked);
4874	return (error);
4875}
4876
4877int
4878extattr_delete_file(td, uap)
4879	struct thread *td;
4880	struct extattr_delete_file_args /* {
4881		const char *path;
4882		int attrnamespace;
4883		const char *attrname;
4884	} */ *uap;
4885{
4886	struct nameidata nd;
4887	char attrname[EXTATTR_MAXNAMELEN];
4888	int vfslocked, error;
4889
4890	AUDIT_ARG(value, uap->attrnamespace);
4891	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4892	if (error)
4893		return(error);
4894	AUDIT_ARG(text, attrname);
4895
4896	NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
4897	    uap->path, td);
4898	error = namei(&nd);
4899	if (error)
4900		return(error);
4901	NDFREE(&nd, NDF_ONLY_PNBUF);
4902
4903	vfslocked = NDHASGIANT(&nd);
4904	error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4905	vrele(nd.ni_vp);
4906	VFS_UNLOCK_GIANT(vfslocked);
4907	return(error);
4908}
4909
4910int
4911extattr_delete_link(td, uap)
4912	struct thread *td;
4913	struct extattr_delete_link_args /* {
4914		const char *path;
4915		int attrnamespace;
4916		const char *attrname;
4917	} */ *uap;
4918{
4919	struct nameidata nd;
4920	char attrname[EXTATTR_MAXNAMELEN];
4921	int vfslocked, error;
4922
4923	AUDIT_ARG(value, uap->attrnamespace);
4924	error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
4925	if (error)
4926		return(error);
4927	AUDIT_ARG(text, attrname);
4928
4929	NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
4930	    uap->path, td);
4931	error = namei(&nd);
4932	if (error)
4933		return(error);
4934	NDFREE(&nd, NDF_ONLY_PNBUF);
4935
4936	vfslocked = NDHASGIANT(&nd);
4937	error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
4938	vrele(nd.ni_vp);
4939	VFS_UNLOCK_GIANT(vfslocked);
4940	return(error);
4941}
4942
4943/*-
4944 * Retrieve a list of extended attributes on a file or directory.
4945 *
4946 * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace",
4947 *            userspace buffer pointer "data", buffer length "nbytes",
4948 *            thread "td".
4949 * Returns: 0 on success, an error number otherwise
4950 * Locks: none
4951 * References: vp must be a valid reference for the duration of the call
4952 */
4953static int
4954extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
4955    size_t nbytes, struct thread *td)
4956{
4957	struct uio auio, *auiop;
4958	size_t size, *sizep;
4959	struct iovec aiov;
4960	ssize_t cnt;
4961	int error;
4962
4963	VFS_ASSERT_GIANT(vp->v_mount);
4964	VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
4965	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4966
4967	auiop = NULL;
4968	sizep = NULL;
4969	cnt = 0;
4970	if (data != NULL) {
4971		aiov.iov_base = data;
4972		aiov.iov_len = nbytes;
4973		auio.uio_iov = &aiov;
4974		auio.uio_iovcnt = 1;
4975		auio.uio_offset = 0;
4976		if (nbytes > INT_MAX) {
4977			error = EINVAL;
4978			goto done;
4979		}
4980		auio.uio_resid = nbytes;
4981		auio.uio_rw = UIO_READ;
4982		auio.uio_segflg = UIO_USERSPACE;
4983		auio.uio_td = td;
4984		auiop = &auio;
4985		cnt = nbytes;
4986	} else
4987		sizep = &size;
4988
4989#ifdef MAC
4990	error = mac_check_vnode_listextattr(td->td_ucred, vp, attrnamespace);
4991	if (error)
4992		goto done;
4993#endif
4994
4995	error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep,
4996	    td->td_ucred, td);
4997
4998	if (auiop != NULL) {
4999		cnt -= auio.uio_resid;
5000		td->td_retval[0] = cnt;
5001	} else
5002		td->td_retval[0] = size;
5003
5004done:
5005	VOP_UNLOCK(vp, 0, td);
5006	return (error);
5007}
5008
5009
5010int
5011extattr_list_fd(td, uap)
5012	struct thread *td;
5013	struct extattr_list_fd_args /* {
5014		int fd;
5015		int attrnamespace;
5016		void *data;
5017		size_t nbytes;
5018	} */ *uap;
5019{
5020	struct file *fp;
5021	int vfslocked, error;
5022
5023	AUDIT_ARG(fd, uap->fd);
5024	AUDIT_ARG(value, uap->attrnamespace);
5025	error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
5026	if (error)
5027		return (error);
5028
5029	vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
5030	error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
5031	    uap->nbytes, td);
5032
5033	fdrop(fp, td);
5034	VFS_UNLOCK_GIANT(vfslocked);
5035	return (error);
5036}
5037
5038int
5039extattr_list_file(td, uap)
5040	struct thread*td;
5041	struct extattr_list_file_args /* {
5042		const char *path;
5043		int attrnamespace;
5044		void *data;
5045		size_t nbytes;
5046	} */ *uap;
5047{
5048	struct nameidata nd;
5049	int vfslocked, error;
5050
5051	AUDIT_ARG(value, uap->attrnamespace);
5052	NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
5053	    uap->path, td);
5054	error = namei(&nd);
5055	if (error)
5056		return (error);
5057	NDFREE(&nd, NDF_ONLY_PNBUF);
5058
5059	vfslocked = NDHASGIANT(&nd);
5060	error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
5061	    uap->nbytes, td);
5062
5063	vrele(nd.ni_vp);
5064	VFS_UNLOCK_GIANT(vfslocked);
5065	return (error);
5066}
5067
5068int
5069extattr_list_link(td, uap)
5070	struct thread*td;
5071	struct extattr_list_link_args /* {
5072		const char *path;
5073		int attrnamespace;
5074		void *data;
5075		size_t nbytes;
5076	} */ *uap;
5077{
5078	struct nameidata nd;
5079	int vfslocked, error;
5080
5081	AUDIT_ARG(value, uap->attrnamespace);
5082	NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
5083	    uap->path, td);
5084	error = namei(&nd);
5085	if (error)
5086		return (error);
5087	NDFREE(&nd, NDF_ONLY_PNBUF);
5088
5089	vfslocked = NDHASGIANT(&nd);
5090	error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
5091	    uap->nbytes, td);
5092
5093	vrele(nd.ni_vp);
5094	VFS_UNLOCK_GIANT(vfslocked);
5095	return (error);
5096}
5097