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