Merge branch 'vendor/LIBARCHIVE' into HEAD
[dragonfly.git] / sys / kern / vfs_syscalls.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  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the University of
21  *      California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *      @(#)vfs_syscalls.c      8.13 (Berkeley) 4/15/94
39  * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $
40  */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/buf.h>
45 #include <sys/conf.h>
46 #include <sys/sysent.h>
47 #include <sys/malloc.h>
48 #include <sys/mount.h>
49 #include <sys/mountctl.h>
50 #include <sys/sysproto.h>
51 #include <sys/filedesc.h>
52 #include <sys/kernel.h>
53 #include <sys/fcntl.h>
54 #include <sys/file.h>
55 #include <sys/linker.h>
56 #include <sys/stat.h>
57 #include <sys/unistd.h>
58 #include <sys/vnode.h>
59 #include <sys/proc.h>
60 #include <sys/priv.h>
61 #include <sys/jail.h>
62 #include <sys/namei.h>
63 #include <sys/nlookup.h>
64 #include <sys/dirent.h>
65 #include <sys/extattr.h>
66 #include <sys/spinlock.h>
67 #include <sys/kern_syscall.h>
68 #include <sys/objcache.h>
69 #include <sys/sysctl.h>
70
71 #include <sys/buf2.h>
72 #include <sys/file2.h>
73 #include <sys/spinlock2.h>
74 #include <sys/mplock2.h>
75
76 #include <vm/vm.h>
77 #include <vm/vm_object.h>
78 #include <vm/vm_page.h>
79
80 #include <machine/limits.h>
81 #include <machine/stdarg.h>
82
83 #include <vfs/union/union.h>
84
85 static void mount_warning(struct mount *mp, const char *ctl, ...)
86                 __printflike(2, 3);
87 static int mount_path(struct proc *p, struct mount *mp, char **rb, char **fb);
88 static int checkvp_chdir (struct vnode *vn, struct thread *td);
89 static void checkdirs (struct nchandle *old_nch, struct nchandle *new_nch);
90 static int chroot_refuse_vdir_fds (struct filedesc *fdp);
91 static int chroot_visible_mnt(struct mount *mp, struct proc *p);
92 static int getutimes (const struct timeval *, struct timespec *);
93 static int setfown (struct vnode *, uid_t, gid_t);
94 static int setfmode (struct vnode *, int);
95 static int setfflags (struct vnode *, int);
96 static int setutimes (struct vnode *, struct vattr *,
97                         const struct timespec *, int);
98 static int      usermount = 0;  /* if 1, non-root can mount fs. */
99
100 int (*union_dircheckp) (struct thread *, struct vnode **, struct file *);
101
102 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "");
103
104 /*
105  * Virtual File System System Calls
106  */
107
108 /*
109  * Mount a file system.
110  *
111  * mount_args(char *type, char *path, int flags, caddr_t data)
112  *
113  * MPALMOSTSAFE
114  */
115 int
116 sys_mount(struct mount_args *uap)
117 {
118         struct thread *td = curthread;
119         struct vnode *vp;
120         struct nchandle nch;
121         struct mount *mp, *nullmp;
122         struct vfsconf *vfsp;
123         int error, flag = 0, flag2 = 0;
124         int hasmount;
125         struct vattr va;
126         struct nlookupdata nd;
127         char fstypename[MFSNAMELEN];
128         struct ucred *cred;
129
130         get_mplock();
131         cred = td->td_ucred;
132         if (jailed(cred)) {
133                 error = EPERM;
134                 goto done;
135         }
136         if (usermount == 0 && (error = priv_check(td, PRIV_ROOT)))
137                 goto done;
138
139         /*
140          * Do not allow NFS export by non-root users.
141          */
142         if (uap->flags & MNT_EXPORTED) {
143                 error = priv_check(td, PRIV_ROOT);
144                 if (error)
145                         goto done;
146         }
147         /*
148          * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users
149          */
150         if (priv_check(td, PRIV_ROOT)) 
151                 uap->flags |= MNT_NOSUID | MNT_NODEV;
152
153         /*
154          * Lookup the requested path and extract the nch and vnode.
155          */
156         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
157         if (error == 0) {
158                 if ((error = nlookup(&nd)) == 0) {
159                         if (nd.nl_nch.ncp->nc_vp == NULL)
160                                 error = ENOENT;
161                 }
162         }
163         if (error) {
164                 nlookup_done(&nd);
165                 goto done;
166         }
167
168         /*
169          * If the target filesystem is resolved via a nullfs mount, then
170          * nd.nl_nch.mount will be pointing to the nullfs mount structure
171          * instead of the target file system. We need it in case we are
172          * doing an update.
173          */
174         nullmp = nd.nl_nch.mount;
175
176         /*
177          * Extract the locked+refd ncp and cleanup the nd structure
178          */
179         nch = nd.nl_nch;
180         cache_zero(&nd.nl_nch);
181         nlookup_done(&nd);
182
183         if ((nch.ncp->nc_flag & NCF_ISMOUNTPT) && cache_findmount(&nch))
184                 hasmount = 1;
185         else
186                 hasmount = 0;
187
188
189         /*
190          * now we have the locked ref'd nch and unreferenced vnode.
191          */
192         vp = nch.ncp->nc_vp;
193         if ((error = vget(vp, LK_EXCLUSIVE)) != 0) {
194                 cache_put(&nch);
195                 goto done;
196         }
197         cache_unlock(&nch);
198
199         /*
200          * Extract the file system type. We need to know this early, to take
201          * appropriate actions if we are dealing with a nullfs.
202          */
203         if ((error = copyinstr(uap->type, fstypename, MFSNAMELEN, NULL)) != 0) {
204                 cache_drop(&nch);
205                 vput(vp);
206                 goto done;
207         }
208
209         /*
210          * Now we have an unlocked ref'd nch and a locked ref'd vp
211          */
212         if (uap->flags & MNT_UPDATE) {
213                 if ((vp->v_flag & (VROOT|VPFSROOT)) == 0) {
214                         cache_drop(&nch);
215                         vput(vp);
216                         error = EINVAL;
217                         goto done;
218                 }
219
220                 if (strncmp(fstypename, "null", 5) == 0) {
221                         KKASSERT(nullmp);
222                         mp = nullmp;
223                 } else {
224                         mp = vp->v_mount;
225                 }
226
227                 flag = mp->mnt_flag;
228                 flag2 = mp->mnt_kern_flag;
229                 /*
230                  * We only allow the filesystem to be reloaded if it
231                  * is currently mounted read-only.
232                  */
233                 if ((uap->flags & MNT_RELOAD) &&
234                     ((mp->mnt_flag & MNT_RDONLY) == 0)) {
235                         cache_drop(&nch);
236                         vput(vp);
237                         error = EOPNOTSUPP;     /* Needs translation */
238                         goto done;
239                 }
240                 /*
241                  * Only root, or the user that did the original mount is
242                  * permitted to update it.
243                  */
244                 if (mp->mnt_stat.f_owner != cred->cr_uid &&
245                     (error = priv_check(td, PRIV_ROOT))) {
246                         cache_drop(&nch);
247                         vput(vp);
248                         goto done;
249                 }
250                 if (vfs_busy(mp, LK_NOWAIT)) {
251                         cache_drop(&nch);
252                         vput(vp);
253                         error = EBUSY;
254                         goto done;
255                 }
256                 if ((vp->v_flag & VMOUNT) != 0 || hasmount) {
257                         cache_drop(&nch);
258                         vfs_unbusy(mp);
259                         vput(vp);
260                         error = EBUSY;
261                         goto done;
262                 }
263                 vsetflags(vp, VMOUNT);
264                 mp->mnt_flag |=
265                     uap->flags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
266                 vn_unlock(vp);
267                 goto update;
268         }
269         /*
270          * If the user is not root, ensure that they own the directory
271          * onto which we are attempting to mount.
272          */
273         if ((error = VOP_GETATTR(vp, &va)) ||
274             (va.va_uid != cred->cr_uid && (error = priv_check(td, PRIV_ROOT)))) {
275                 cache_drop(&nch);
276                 vput(vp);
277                 goto done;
278         }
279         if ((error = vinvalbuf(vp, V_SAVE, 0, 0)) != 0) {
280                 cache_drop(&nch);
281                 vput(vp);
282                 goto done;
283         }
284         if (vp->v_type != VDIR) {
285                 cache_drop(&nch);
286                 vput(vp);
287                 error = ENOTDIR;
288                 goto done;
289         }
290         if (vp->v_mount->mnt_kern_flag & MNTK_NOSTKMNT) {
291                 cache_drop(&nch);
292                 vput(vp);
293                 error = EPERM;
294                 goto done;
295         }
296         vfsp = vfsconf_find_by_name(fstypename);
297         if (vfsp == NULL) {
298                 linker_file_t lf;
299
300                 /* Only load modules for root (very important!) */
301                 if ((error = priv_check(td, PRIV_ROOT)) != 0) {
302                         cache_drop(&nch);
303                         vput(vp);
304                         goto done;
305                 }
306                 error = linker_load_file(fstypename, &lf);
307                 if (error || lf == NULL) {
308                         cache_drop(&nch);
309                         vput(vp);
310                         if (lf == NULL)
311                                 error = ENODEV;
312                         goto done;
313                 }
314                 lf->userrefs++;
315                 /* lookup again, see if the VFS was loaded */
316                 vfsp = vfsconf_find_by_name(fstypename);
317                 if (vfsp == NULL) {
318                         lf->userrefs--;
319                         linker_file_unload(lf);
320                         cache_drop(&nch);
321                         vput(vp);
322                         error = ENODEV;
323                         goto done;
324                 }
325         }
326         if ((vp->v_flag & VMOUNT) != 0 || hasmount) {
327                 cache_drop(&nch);
328                 vput(vp);
329                 error = EBUSY;
330                 goto done;
331         }
332         vsetflags(vp, VMOUNT);
333
334         /*
335          * Allocate and initialize the filesystem.
336          */
337         mp = kmalloc(sizeof(struct mount), M_MOUNT, M_ZERO|M_WAITOK);
338         mount_init(mp);
339         vfs_busy(mp, LK_NOWAIT);
340         mp->mnt_op = vfsp->vfc_vfsops;
341         mp->mnt_vfc = vfsp;
342         vfsp->vfc_refcount++;
343         mp->mnt_stat.f_type = vfsp->vfc_typenum;
344         mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
345         strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
346         mp->mnt_stat.f_owner = cred->cr_uid;
347         vn_unlock(vp);
348 update:
349         /*
350          * Set the mount level flags.
351          */
352         if (uap->flags & MNT_RDONLY)
353                 mp->mnt_flag |= MNT_RDONLY;
354         else if (mp->mnt_flag & MNT_RDONLY)
355                 mp->mnt_kern_flag |= MNTK_WANTRDWR;
356         mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
357             MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOATIME |
358             MNT_NOSYMFOLLOW | MNT_IGNORE |
359             MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
360         mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC |
361             MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_FORCE |
362             MNT_NOSYMFOLLOW | MNT_IGNORE |
363             MNT_NOATIME | MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR);
364         /*
365          * Mount the filesystem.
366          * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
367          * get. 
368          */
369         error = VFS_MOUNT(mp, uap->path, uap->data, cred);
370         if (mp->mnt_flag & MNT_UPDATE) {
371                 if (mp->mnt_kern_flag & MNTK_WANTRDWR)
372                         mp->mnt_flag &= ~MNT_RDONLY;
373                 mp->mnt_flag &=~ (MNT_UPDATE | MNT_RELOAD | MNT_FORCE);
374                 mp->mnt_kern_flag &=~ MNTK_WANTRDWR;
375                 if (error) {
376                         mp->mnt_flag = flag;
377                         mp->mnt_kern_flag = flag2;
378                 }
379                 vfs_unbusy(mp);
380                 vclrflags(vp, VMOUNT);
381                 vrele(vp);
382                 cache_drop(&nch);
383                 goto done;
384         }
385         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
386         /*
387          * Put the new filesystem on the mount list after root.  The mount
388          * point gets its own mnt_ncmountpt (unless the VFS already set one
389          * up) which represents the root of the mount.  The lookup code
390          * detects the mount point going forward and checks the root of
391          * the mount going backwards.
392          *
393          * It is not necessary to invalidate or purge the vnode underneath
394          * because elements under the mount will be given their own glue
395          * namecache record.
396          */
397         if (!error) {
398                 if (mp->mnt_ncmountpt.ncp == NULL) {
399                         /* 
400                          * allocate, then unlock, but leave the ref intact 
401                          */
402                         cache_allocroot(&mp->mnt_ncmountpt, mp, NULL);
403                         cache_unlock(&mp->mnt_ncmountpt);
404                 }
405                 mp->mnt_ncmounton = nch;                /* inherits ref */
406                 nch.ncp->nc_flag |= NCF_ISMOUNTPT;
407
408                 /* XXX get the root of the fs and cache_setvp(mnt_ncmountpt...) */
409                 vclrflags(vp, VMOUNT);
410                 mountlist_insert(mp, MNTINS_LAST);
411                 vn_unlock(vp);
412                 checkdirs(&mp->mnt_ncmounton, &mp->mnt_ncmountpt);
413                 error = vfs_allocate_syncvnode(mp);
414                 vfs_unbusy(mp);
415                 error = VFS_START(mp, 0);
416                 vrele(vp);
417         } else {
418                 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_coherency_ops);
419                 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_journal_ops);
420                 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_norm_ops);
421                 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_spec_ops);
422                 vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_fifo_ops);
423                 vclrflags(vp, VMOUNT);
424                 mp->mnt_vfc->vfc_refcount--;
425                 vfs_unbusy(mp);
426                 kfree(mp, M_MOUNT);
427                 cache_drop(&nch);
428                 vput(vp);
429         }
430 done:
431         rel_mplock();
432         return (error);
433 }
434
435 /*
436  * Scan all active processes to see if any of them have a current
437  * or root directory onto which the new filesystem has just been
438  * mounted. If so, replace them with the new mount point.
439  *
440  * The passed ncp is ref'd and locked (from the mount code) and
441  * must be associated with the vnode representing the root of the
442  * mount point.
443  */
444 struct checkdirs_info {
445         struct nchandle old_nch;
446         struct nchandle new_nch;
447         struct vnode *old_vp;
448         struct vnode *new_vp;
449 };
450
451 static int checkdirs_callback(struct proc *p, void *data);
452
453 static void
454 checkdirs(struct nchandle *old_nch, struct nchandle *new_nch)
455 {
456         struct checkdirs_info info;
457         struct vnode *olddp;
458         struct vnode *newdp;
459         struct mount *mp;
460
461         /*
462          * If the old mount point's vnode has a usecount of 1, it is not
463          * being held as a descriptor anywhere.
464          */
465         olddp = old_nch->ncp->nc_vp;
466         if (olddp == NULL || olddp->v_sysref.refcnt == 1)
467                 return;
468
469         /*
470          * Force the root vnode of the new mount point to be resolved
471          * so we can update any matching processes.
472          */
473         mp = new_nch->mount;
474         if (VFS_ROOT(mp, &newdp))
475                 panic("mount: lost mount");
476         cache_setunresolved(new_nch);
477         cache_setvp(new_nch, newdp);
478
479         /*
480          * Special handling of the root node
481          */
482         if (rootvnode == olddp) {
483                 vref(newdp);
484                 vfs_cache_setroot(newdp, cache_hold(new_nch));
485         }
486
487         /*
488          * Pass newdp separately so the callback does not have to access
489          * it via new_nch->ncp->nc_vp.
490          */
491         info.old_nch = *old_nch;
492         info.new_nch = *new_nch;
493         info.new_vp = newdp;
494         allproc_scan(checkdirs_callback, &info);
495         vput(newdp);
496 }
497
498 /*
499  * NOTE: callback is not MP safe because the scanned process's filedesc
500  * structure can be ripped out from under us, amoung other things.
501  */
502 static int
503 checkdirs_callback(struct proc *p, void *data)
504 {
505         struct checkdirs_info *info = data;
506         struct filedesc *fdp;
507         struct nchandle ncdrop1;
508         struct nchandle ncdrop2;
509         struct vnode *vprele1;
510         struct vnode *vprele2;
511
512         if ((fdp = p->p_fd) != NULL) {
513                 cache_zero(&ncdrop1);
514                 cache_zero(&ncdrop2);
515                 vprele1 = NULL;
516                 vprele2 = NULL;
517
518                 /*
519                  * MPUNSAFE - XXX fdp can be pulled out from under a
520                  * foreign process.
521                  *
522                  * A shared filedesc is ok, we don't have to copy it
523                  * because we are making this change globally.
524                  */
525                 spin_lock(&fdp->fd_spin);
526                 if (fdp->fd_ncdir.mount == info->old_nch.mount &&
527                     fdp->fd_ncdir.ncp == info->old_nch.ncp) {
528                         vprele1 = fdp->fd_cdir;
529                         vref(info->new_vp);
530                         fdp->fd_cdir = info->new_vp;
531                         ncdrop1 = fdp->fd_ncdir;
532                         cache_copy(&info->new_nch, &fdp->fd_ncdir);
533                 }
534                 if (fdp->fd_nrdir.mount == info->old_nch.mount &&
535                     fdp->fd_nrdir.ncp == info->old_nch.ncp) {
536                         vprele2 = fdp->fd_rdir;
537                         vref(info->new_vp);
538                         fdp->fd_rdir = info->new_vp;
539                         ncdrop2 = fdp->fd_nrdir;
540                         cache_copy(&info->new_nch, &fdp->fd_nrdir);
541                 }
542                 spin_unlock(&fdp->fd_spin);
543                 if (ncdrop1.ncp)
544                         cache_drop(&ncdrop1);
545                 if (ncdrop2.ncp)
546                         cache_drop(&ncdrop2);
547                 if (vprele1)
548                         vrele(vprele1);
549                 if (vprele2)
550                         vrele(vprele2);
551         }
552         return(0);
553 }
554
555 /*
556  * Unmount a file system.
557  *
558  * Note: unmount takes a path to the vnode mounted on as argument,
559  * not special file (as before).
560  *
561  * umount_args(char *path, int flags)
562  *
563  * MPALMOSTSAFE
564  */
565 int
566 sys_unmount(struct unmount_args *uap)
567 {
568         struct thread *td = curthread;
569         struct proc *p __debugvar = td->td_proc;
570         struct mount *mp = NULL;
571         struct nlookupdata nd;
572         int error;
573
574         KKASSERT(p);
575         get_mplock();
576         if (td->td_ucred->cr_prison != NULL) {
577                 error = EPERM;
578                 goto done;
579         }
580         if (usermount == 0 && (error = priv_check(td, PRIV_ROOT)))
581                 goto done;
582
583         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
584         if (error == 0)
585                 error = nlookup(&nd);
586         if (error)
587                 goto out;
588
589         mp = nd.nl_nch.mount;
590
591         /*
592          * Only root, or the user that did the original mount is
593          * permitted to unmount this filesystem.
594          */
595         if ((mp->mnt_stat.f_owner != td->td_ucred->cr_uid) &&
596             (error = priv_check(td, PRIV_ROOT)))
597                 goto out;
598
599         /*
600          * Don't allow unmounting the root file system.
601          */
602         if (mp->mnt_flag & MNT_ROOTFS) {
603                 error = EINVAL;
604                 goto out;
605         }
606
607         /*
608          * Must be the root of the filesystem
609          */
610         if (nd.nl_nch.ncp != mp->mnt_ncmountpt.ncp) {
611                 error = EINVAL;
612                 goto out;
613         }
614
615 out:
616         nlookup_done(&nd);
617         if (error == 0)
618                 error = dounmount(mp, uap->flags);
619 done:
620         rel_mplock();
621         return (error);
622 }
623
624 /*
625  * Do the actual file system unmount.
626  */
627 static int
628 dounmount_interlock(struct mount *mp)
629 {
630         if (mp->mnt_kern_flag & MNTK_UNMOUNT)
631                 return (EBUSY);
632         mp->mnt_kern_flag |= MNTK_UNMOUNT;
633         return(0);
634 }
635
636 static int
637 unmount_allproc_cb(struct proc *p, void *arg)
638 {
639         struct mount *mp;
640
641         if (p->p_textnch.ncp == NULL)
642                 return 0;
643
644         mp = (struct mount *)arg;
645         if (p->p_textnch.mount == mp)
646                 cache_drop(&p->p_textnch);
647
648         return 0;
649 }
650
651 int
652 dounmount(struct mount *mp, int flags)
653 {
654         struct namecache *ncp;
655         struct nchandle nch;
656         struct vnode *vp;
657         int error;
658         int async_flag;
659         int lflags;
660         int freeok = 1;
661
662         /*
663          * Exclusive access for unmounting purposes
664          */
665         if ((error = mountlist_interlock(dounmount_interlock, mp)) != 0)
666                 return (error);
667
668         /*
669          * Allow filesystems to detect that a forced unmount is in progress.
670          */
671         if (flags & MNT_FORCE)
672                 mp->mnt_kern_flag |= MNTK_UNMOUNTF;
673         lflags = LK_EXCLUSIVE | ((flags & MNT_FORCE) ? 0 : LK_NOWAIT);
674         error = lockmgr(&mp->mnt_lock, lflags);
675         if (error) {
676                 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
677                 if (mp->mnt_kern_flag & MNTK_MWAIT)
678                         wakeup(mp);
679                 return (error);
680         }
681
682         if (mp->mnt_flag & MNT_EXPUBLIC)
683                 vfs_setpublicfs(NULL, NULL, NULL);
684
685         vfs_msync(mp, MNT_WAIT);
686         async_flag = mp->mnt_flag & MNT_ASYNC;
687         mp->mnt_flag &=~ MNT_ASYNC;
688
689         /*
690          * If this filesystem isn't aliasing other filesystems,
691          * try to invalidate any remaining namecache entries and
692          * check the count afterwords.
693          */
694         if ((mp->mnt_kern_flag & MNTK_NCALIASED) == 0) {
695                 cache_lock(&mp->mnt_ncmountpt);
696                 cache_inval(&mp->mnt_ncmountpt, CINV_DESTROY|CINV_CHILDREN);
697                 cache_unlock(&mp->mnt_ncmountpt);
698
699                 if ((ncp = mp->mnt_ncmountpt.ncp) != NULL &&
700                     (ncp->nc_refs != 1 || TAILQ_FIRST(&ncp->nc_list))) {
701                         allproc_scan(&unmount_allproc_cb, mp);
702                 }
703
704                 if ((ncp = mp->mnt_ncmountpt.ncp) != NULL &&
705                     (ncp->nc_refs != 1 || TAILQ_FIRST(&ncp->nc_list))) {
706
707                         if ((flags & MNT_FORCE) == 0) {
708                                 error = EBUSY;
709                                 mount_warning(mp, "Cannot unmount: "
710                                                   "%d namecache "
711                                                   "references still "
712                                                   "present",
713                                                   ncp->nc_refs - 1);
714                         } else {
715                                 mount_warning(mp, "Forced unmount: "
716                                                   "%d namecache "
717                                                   "references still "
718                                                   "present",
719                                                   ncp->nc_refs - 1);
720                                 freeok = 0;
721                         }
722                 }
723         }
724
725         /*
726          * nchandle records ref the mount structure.  Expect a count of 1
727          * (our mount->mnt_ncmountpt).
728          */
729         if (mp->mnt_refs != 1) {
730                 if ((flags & MNT_FORCE) == 0) {
731                         mount_warning(mp, "Cannot unmount: "
732                                           "%d process references still "
733                                           "present", mp->mnt_refs);
734                         error = EBUSY;
735                 } else {
736                         mount_warning(mp, "Forced unmount: "
737                                           "%d process references still "
738                                           "present", mp->mnt_refs);
739                         freeok = 0;
740                 }
741         }
742
743         /*
744          * Decomission our special mnt_syncer vnode.  This also stops
745          * the vnlru code.  If we are unable to unmount we recommission
746          * the vnode.
747          */
748         if (error == 0) {
749                 if ((vp = mp->mnt_syncer) != NULL) {
750                         mp->mnt_syncer = NULL;
751                         vrele(vp);
752                 }
753                 if (((mp->mnt_flag & MNT_RDONLY) ||
754                      (error = VFS_SYNC(mp, MNT_WAIT)) == 0) ||
755                     (flags & MNT_FORCE)) {
756                         error = VFS_UNMOUNT(mp, flags);
757                 }
758         }
759         if (error) {
760                 if (mp->mnt_syncer == NULL)
761                         vfs_allocate_syncvnode(mp);
762                 mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
763                 mp->mnt_flag |= async_flag;
764                 lockmgr(&mp->mnt_lock, LK_RELEASE);
765                 if (mp->mnt_kern_flag & MNTK_MWAIT)
766                         wakeup(mp);
767                 return (error);
768         }
769         /*
770          * Clean up any journals still associated with the mount after
771          * filesystem activity has ceased.
772          */
773         journal_remove_all_journals(mp, 
774             ((flags & MNT_FORCE) ? MC_JOURNAL_STOP_IMM : 0));
775
776         mountlist_remove(mp);
777
778         /*
779          * Remove any installed vnode ops here so the individual VFSs don't
780          * have to.
781          */
782         vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_coherency_ops);
783         vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_journal_ops);
784         vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_norm_ops);
785         vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_spec_ops);
786         vfs_rm_vnodeops(mp, NULL, &mp->mnt_vn_fifo_ops);
787
788         if (mp->mnt_ncmountpt.ncp != NULL) {
789                 nch = mp->mnt_ncmountpt;
790                 cache_zero(&mp->mnt_ncmountpt);
791                 cache_clrmountpt(&nch);
792                 cache_drop(&nch);
793         }
794         if (mp->mnt_ncmounton.ncp != NULL) {
795                 nch = mp->mnt_ncmounton;
796                 cache_zero(&mp->mnt_ncmounton);
797                 cache_clrmountpt(&nch);
798                 cache_drop(&nch);
799         }
800
801         mp->mnt_vfc->vfc_refcount--;
802         if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
803                 panic("unmount: dangling vnode");
804         lockmgr(&mp->mnt_lock, LK_RELEASE);
805         if (mp->mnt_kern_flag & MNTK_MWAIT)
806                 wakeup(mp);
807         if (freeok)
808                 kfree(mp, M_MOUNT);
809         return (0);
810 }
811
812 static
813 void
814 mount_warning(struct mount *mp, const char *ctl, ...)
815 {
816         char *ptr;
817         char *buf;
818         __va_list va;
819
820         __va_start(va, ctl);
821         if (cache_fullpath(NULL, &mp->mnt_ncmounton, &ptr, &buf, 0) == 0) {
822                 kprintf("unmount(%s): ", ptr);
823                 kvprintf(ctl, va);
824                 kprintf("\n");
825                 kfree(buf, M_TEMP);
826         } else {
827                 kprintf("unmount(%p", mp);
828                 if (mp->mnt_ncmounton.ncp && mp->mnt_ncmounton.ncp->nc_name)
829                         kprintf(",%s", mp->mnt_ncmounton.ncp->nc_name);
830                 kprintf("): ");
831                 kvprintf(ctl, va);
832                 kprintf("\n");
833         }
834         __va_end(va);
835 }
836
837 /*
838  * Shim cache_fullpath() to handle the case where a process is chrooted into
839  * a subdirectory of a mount.  In this case if the root mount matches the
840  * process root directory's mount we have to specify the process's root
841  * directory instead of the mount point, because the mount point might
842  * be above the root directory.
843  */
844 static
845 int
846 mount_path(struct proc *p, struct mount *mp, char **rb, char **fb)
847 {
848         struct nchandle *nch;
849
850         if (p && p->p_fd->fd_nrdir.mount == mp)
851                 nch = &p->p_fd->fd_nrdir;
852         else
853                 nch = &mp->mnt_ncmountpt;
854         return(cache_fullpath(p, nch, rb, fb, 0));
855 }
856
857 /*
858  * Sync each mounted filesystem.
859  */
860
861 #ifdef DEBUG
862 static int syncprt = 0;
863 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, "");
864 #endif /* DEBUG */
865
866 static int sync_callback(struct mount *mp, void *data);
867
868 /*
869  * MPALMOSTSAFE
870  */
871 int
872 sys_sync(struct sync_args *uap)
873 {
874         get_mplock();
875         mountlist_scan(sync_callback, NULL, MNTSCAN_FORWARD);
876 #ifdef DEBUG
877         /*
878          * print out buffer pool stat information on each sync() call.
879          */
880         if (syncprt)
881                 vfs_bufstats();
882 #endif /* DEBUG */
883         rel_mplock();
884         return (0);
885 }
886
887 static
888 int
889 sync_callback(struct mount *mp, void *data __unused)
890 {
891         int asyncflag;
892
893         if ((mp->mnt_flag & MNT_RDONLY) == 0) {
894                 asyncflag = mp->mnt_flag & MNT_ASYNC;
895                 mp->mnt_flag &= ~MNT_ASYNC;
896                 vfs_msync(mp, MNT_NOWAIT);
897                 VFS_SYNC(mp, MNT_NOWAIT);
898                 mp->mnt_flag |= asyncflag;
899         }
900         return(0);
901 }
902
903 /* XXX PRISON: could be per prison flag */
904 static int prison_quotas;
905 #if 0
906 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, "");
907 #endif
908
909 /*
910  *  quotactl_args(char *path, int fcmd, int uid, caddr_t arg)
911  *
912  * Change filesystem quotas.
913  *
914  * MPALMOSTSAFE
915  */
916 int
917 sys_quotactl(struct quotactl_args *uap)
918 {
919         struct nlookupdata nd;
920         struct thread *td;
921         struct proc *p;
922         struct mount *mp;
923         int error;
924
925         get_mplock();
926         td = curthread;
927         p = td->td_proc;
928         if (td->td_ucred->cr_prison && !prison_quotas) {
929                 error = EPERM;
930                 goto done;
931         }
932
933         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
934         if (error == 0)
935                 error = nlookup(&nd);
936         if (error == 0) {
937                 mp = nd.nl_nch.mount;
938                 error = VFS_QUOTACTL(mp, uap->cmd, uap->uid,
939                                     uap->arg, nd.nl_cred);
940         }
941         nlookup_done(&nd);
942 done:
943         rel_mplock();
944         return (error);
945 }
946
947 /*
948  * mountctl(char *path, int op, int fd, const void *ctl, int ctllen,
949  *              void *buf, int buflen)
950  *
951  * This function operates on a mount point and executes the specified
952  * operation using the specified control data, and possibly returns data.
953  *
954  * The actual number of bytes stored in the result buffer is returned, 0
955  * if none, otherwise an error is returned.
956  *
957  * MPALMOSTSAFE
958  */
959 int
960 sys_mountctl(struct mountctl_args *uap)
961 {
962         struct thread *td = curthread;
963         struct proc *p = td->td_proc;
964         struct file *fp;
965         void *ctl = NULL;
966         void *buf = NULL;
967         char *path = NULL;
968         int error;
969
970         /*
971          * Sanity and permissions checks.  We must be root.
972          */
973         KKASSERT(p);
974         if (td->td_ucred->cr_prison != NULL)
975                 return (EPERM);
976         if ((uap->op != MOUNTCTL_MOUNTFLAGS) &&
977             (error = priv_check(td, PRIV_ROOT)) != 0)
978                 return (error);
979
980         /*
981          * Argument length checks
982          */
983         if (uap->ctllen < 0 || uap->ctllen > 1024)
984                 return (EINVAL);
985         if (uap->buflen < 0 || uap->buflen > 16 * 1024)
986                 return (EINVAL);
987         if (uap->path == NULL)
988                 return (EINVAL);
989
990         /*
991          * Allocate the necessary buffers and copyin data
992          */
993         path = objcache_get(namei_oc, M_WAITOK);
994         error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
995         if (error)
996                 goto done;
997
998         if (uap->ctllen) {
999                 ctl = kmalloc(uap->ctllen + 1, M_TEMP, M_WAITOK|M_ZERO);
1000                 error = copyin(uap->ctl, ctl, uap->ctllen);
1001                 if (error)
1002                         goto done;
1003         }
1004         if (uap->buflen)
1005                 buf = kmalloc(uap->buflen + 1, M_TEMP, M_WAITOK|M_ZERO);
1006
1007         /*
1008          * Validate the descriptor
1009          */
1010         if (uap->fd >= 0) {
1011                 fp = holdfp(p->p_fd, uap->fd, -1);
1012                 if (fp == NULL) {
1013                         error = EBADF;
1014                         goto done;
1015                 }
1016         } else {
1017                 fp = NULL;
1018         }
1019
1020         /*
1021          * Execute the internal kernel function and clean up.
1022          */
1023         get_mplock();
1024         error = kern_mountctl(path, uap->op, fp, ctl, uap->ctllen, buf, uap->buflen, &uap->sysmsg_result);
1025         rel_mplock();
1026         if (fp)
1027                 fdrop(fp);
1028         if (error == 0 && uap->sysmsg_result > 0)
1029                 error = copyout(buf, uap->buf, uap->sysmsg_result);
1030 done:
1031         if (path)
1032                 objcache_put(namei_oc, path);
1033         if (ctl)
1034                 kfree(ctl, M_TEMP);
1035         if (buf)
1036                 kfree(buf, M_TEMP);
1037         return (error);
1038 }
1039
1040 /*
1041  * Execute a mount control operation by resolving the path to a mount point
1042  * and calling vop_mountctl().  
1043  *
1044  * Use the mount point from the nch instead of the vnode so nullfs mounts
1045  * can properly spike the VOP.
1046  */
1047 int
1048 kern_mountctl(const char *path, int op, struct file *fp, 
1049                 const void *ctl, int ctllen, 
1050                 void *buf, int buflen, int *res)
1051 {
1052         struct vnode *vp;
1053         struct mount *mp;
1054         struct nlookupdata nd;
1055         int error;
1056
1057         *res = 0;
1058         vp = NULL;
1059         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW);
1060         if (error == 0)
1061                 error = nlookup(&nd);
1062         if (error == 0)
1063                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
1064         mp = nd.nl_nch.mount;
1065         nlookup_done(&nd);
1066         if (error)
1067                 return (error);
1068         vn_unlock(vp);
1069
1070         /*
1071          * Must be the root of the filesystem
1072          */
1073         if ((vp->v_flag & (VROOT|VPFSROOT)) == 0) {
1074                 vrele(vp);
1075                 return (EINVAL);
1076         }
1077         error = vop_mountctl(mp->mnt_vn_use_ops, vp, op, fp, ctl, ctllen,
1078                              buf, buflen, res);
1079         vrele(vp);
1080         return (error);
1081 }
1082
1083 int
1084 kern_statfs(struct nlookupdata *nd, struct statfs *buf)
1085 {
1086         struct thread *td = curthread;
1087         struct proc *p = td->td_proc;
1088         struct mount *mp;
1089         struct statfs *sp;
1090         char *fullpath, *freepath;
1091         int error;
1092
1093         if ((error = nlookup(nd)) != 0)
1094                 return (error);
1095         mp = nd->nl_nch.mount;
1096         sp = &mp->mnt_stat;
1097         if ((error = VFS_STATFS(mp, sp, nd->nl_cred)) != 0)
1098                 return (error);
1099
1100         error = mount_path(p, mp, &fullpath, &freepath);
1101         if (error)
1102                 return(error);
1103         bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
1104         strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
1105         kfree(freepath, M_TEMP);
1106
1107         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1108         bcopy(sp, buf, sizeof(*buf));
1109         /* Only root should have access to the fsid's. */
1110         if (priv_check(td, PRIV_ROOT))
1111                 buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0;
1112         return (0);
1113 }
1114
1115 /*
1116  * statfs_args(char *path, struct statfs *buf)
1117  *
1118  * Get filesystem statistics.
1119  *
1120  * MPALMOSTSAFE
1121  */
1122 int
1123 sys_statfs(struct statfs_args *uap)
1124 {
1125         struct nlookupdata nd;
1126         struct statfs buf;
1127         int error;
1128
1129         get_mplock();
1130         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
1131         if (error == 0)
1132                 error = kern_statfs(&nd, &buf);
1133         nlookup_done(&nd);
1134         if (error == 0)
1135                 error = copyout(&buf, uap->buf, sizeof(*uap->buf));
1136         rel_mplock();
1137         return (error);
1138 }
1139
1140 /*
1141  * MPALMOSTSAFE
1142  */
1143 int
1144 kern_fstatfs(int fd, struct statfs *buf)
1145 {
1146         struct thread *td = curthread;
1147         struct proc *p = td->td_proc;
1148         struct file *fp;
1149         struct mount *mp;
1150         struct statfs *sp;
1151         char *fullpath, *freepath;
1152         int error;
1153
1154         KKASSERT(p);
1155         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
1156                 return (error);
1157         get_mplock();
1158         mp = ((struct vnode *)fp->f_data)->v_mount;
1159         if (mp == NULL) {
1160                 error = EBADF;
1161                 goto done;
1162         }
1163         if (fp->f_cred == NULL) {
1164                 error = EINVAL;
1165                 goto done;
1166         }
1167         sp = &mp->mnt_stat;
1168         if ((error = VFS_STATFS(mp, sp, fp->f_cred)) != 0)
1169                 goto done;
1170
1171         if ((error = mount_path(p, mp, &fullpath, &freepath)) != 0)
1172                 goto done;
1173         bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
1174         strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
1175         kfree(freepath, M_TEMP);
1176
1177         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1178         bcopy(sp, buf, sizeof(*buf));
1179
1180         /* Only root should have access to the fsid's. */
1181         if (priv_check(td, PRIV_ROOT))
1182                 buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0;
1183         error = 0;
1184 done:
1185         rel_mplock();
1186         fdrop(fp);
1187         return (error);
1188 }
1189
1190 /*
1191  * fstatfs_args(int fd, struct statfs *buf)
1192  *
1193  * Get filesystem statistics.
1194  *
1195  * MPSAFE
1196  */
1197 int
1198 sys_fstatfs(struct fstatfs_args *uap)
1199 {
1200         struct statfs buf;
1201         int error;
1202
1203         error = kern_fstatfs(uap->fd, &buf);
1204
1205         if (error == 0)
1206                 error = copyout(&buf, uap->buf, sizeof(*uap->buf));
1207         return (error);
1208 }
1209
1210 int
1211 kern_statvfs(struct nlookupdata *nd, struct statvfs *buf)
1212 {
1213         struct mount *mp;
1214         struct statvfs *sp;
1215         int error;
1216
1217         if ((error = nlookup(nd)) != 0)
1218                 return (error);
1219         mp = nd->nl_nch.mount;
1220         sp = &mp->mnt_vstat;
1221         if ((error = VFS_STATVFS(mp, sp, nd->nl_cred)) != 0)
1222                 return (error);
1223
1224         sp->f_flag = 0;
1225         if (mp->mnt_flag & MNT_RDONLY)
1226                 sp->f_flag |= ST_RDONLY;
1227         if (mp->mnt_flag & MNT_NOSUID)
1228                 sp->f_flag |= ST_NOSUID;
1229         bcopy(sp, buf, sizeof(*buf));
1230         return (0);
1231 }
1232
1233 /*
1234  * statfs_args(char *path, struct statfs *buf)
1235  *
1236  * Get filesystem statistics.
1237  *
1238  * MPALMOSTSAFE
1239  */
1240 int
1241 sys_statvfs(struct statvfs_args *uap)
1242 {
1243         struct nlookupdata nd;
1244         struct statvfs buf;
1245         int error;
1246
1247         get_mplock();
1248         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
1249         if (error == 0)
1250                 error = kern_statvfs(&nd, &buf);
1251         nlookup_done(&nd);
1252         if (error == 0)
1253                 error = copyout(&buf, uap->buf, sizeof(*uap->buf));
1254         rel_mplock();
1255         return (error);
1256 }
1257
1258 int
1259 kern_fstatvfs(int fd, struct statvfs *buf)
1260 {
1261         struct thread *td = curthread;
1262         struct proc *p = td->td_proc;
1263         struct file *fp;
1264         struct mount *mp;
1265         struct statvfs *sp;
1266         int error;
1267
1268         KKASSERT(p);
1269         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
1270                 return (error);
1271         mp = ((struct vnode *)fp->f_data)->v_mount;
1272         if (mp == NULL) {
1273                 error = EBADF;
1274                 goto done;
1275         }
1276         if (fp->f_cred == NULL) {
1277                 error = EINVAL;
1278                 goto done;
1279         }
1280         sp = &mp->mnt_vstat;
1281         if ((error = VFS_STATVFS(mp, sp, fp->f_cred)) != 0)
1282                 goto done;
1283
1284         sp->f_flag = 0;
1285         if (mp->mnt_flag & MNT_RDONLY)
1286                 sp->f_flag |= ST_RDONLY;
1287         if (mp->mnt_flag & MNT_NOSUID)
1288                 sp->f_flag |= ST_NOSUID;
1289
1290         bcopy(sp, buf, sizeof(*buf));
1291         error = 0;
1292 done:
1293         fdrop(fp);
1294         return (error);
1295 }
1296
1297 /*
1298  * fstatfs_args(int fd, struct statfs *buf)
1299  *
1300  * Get filesystem statistics.
1301  *
1302  * MPALMOSTSAFE
1303  */
1304 int
1305 sys_fstatvfs(struct fstatvfs_args *uap)
1306 {
1307         struct statvfs buf;
1308         int error;
1309
1310         get_mplock();
1311         error = kern_fstatvfs(uap->fd, &buf);
1312         rel_mplock();
1313
1314         if (error == 0)
1315                 error = copyout(&buf, uap->buf, sizeof(*uap->buf));
1316         return (error);
1317 }
1318
1319 /*
1320  * getfsstat_args(struct statfs *buf, long bufsize, int flags)
1321  *
1322  * Get statistics on all filesystems.
1323  */
1324
1325 struct getfsstat_info {
1326         struct statfs *sfsp;
1327         long count;
1328         long maxcount;
1329         int error;
1330         int flags;
1331         struct thread *td;
1332 };
1333
1334 static int getfsstat_callback(struct mount *, void *);
1335
1336 /*
1337  * MPALMOSTSAFE
1338  */
1339 int
1340 sys_getfsstat(struct getfsstat_args *uap)
1341 {
1342         struct thread *td = curthread;
1343         struct getfsstat_info info;
1344
1345         bzero(&info, sizeof(info));
1346
1347         info.maxcount = uap->bufsize / sizeof(struct statfs);
1348         info.sfsp = uap->buf;
1349         info.count = 0;
1350         info.flags = uap->flags;
1351         info.td = td;
1352
1353         get_mplock();
1354         mountlist_scan(getfsstat_callback, &info, MNTSCAN_FORWARD);
1355         rel_mplock();
1356         if (info.sfsp && info.count > info.maxcount)
1357                 uap->sysmsg_result = info.maxcount;
1358         else
1359                 uap->sysmsg_result = info.count;
1360         return (info.error);
1361 }
1362
1363 static int
1364 getfsstat_callback(struct mount *mp, void *data)
1365 {
1366         struct getfsstat_info *info = data;
1367         struct statfs *sp;
1368         char *freepath;
1369         char *fullpath;
1370         int error;
1371
1372         if (info->sfsp && info->count < info->maxcount) {
1373                 if (info->td->td_proc &&
1374                     !chroot_visible_mnt(mp, info->td->td_proc)) {
1375                         return(0);
1376                 }
1377                 sp = &mp->mnt_stat;
1378
1379                 /*
1380                  * If MNT_NOWAIT or MNT_LAZY is specified, do not
1381                  * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
1382                  * overrides MNT_WAIT.
1383                  */
1384                 if (((info->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
1385                     (info->flags & MNT_WAIT)) &&
1386                     (error = VFS_STATFS(mp, sp, info->td->td_ucred))) {
1387                         return(0);
1388                 }
1389                 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1390
1391                 error = mount_path(info->td->td_proc, mp, &fullpath, &freepath);
1392                 if (error) {
1393                         info->error = error;
1394                         return(-1);
1395                 }
1396                 bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
1397                 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
1398                 kfree(freepath, M_TEMP);
1399
1400                 error = copyout(sp, info->sfsp, sizeof(*sp));
1401                 if (error) {
1402                         info->error = error;
1403                         return (-1);
1404                 }
1405                 ++info->sfsp;
1406         }
1407         info->count++;
1408         return(0);
1409 }
1410
1411 /*
1412  * getvfsstat_args(struct statfs *buf, struct statvfs *vbuf,
1413                    long bufsize, int flags)
1414  *
1415  * Get statistics on all filesystems.
1416  */
1417
1418 struct getvfsstat_info {
1419         struct statfs *sfsp;
1420         struct statvfs *vsfsp;
1421         long count;
1422         long maxcount;
1423         int error;
1424         int flags;
1425         struct thread *td;
1426 };
1427
1428 static int getvfsstat_callback(struct mount *, void *);
1429
1430 /*
1431  * MPALMOSTSAFE
1432  */
1433 int
1434 sys_getvfsstat(struct getvfsstat_args *uap)
1435 {
1436         struct thread *td = curthread;
1437         struct getvfsstat_info info;
1438
1439         bzero(&info, sizeof(info));
1440
1441         info.maxcount = uap->vbufsize / sizeof(struct statvfs);
1442         info.sfsp = uap->buf;
1443         info.vsfsp = uap->vbuf;
1444         info.count = 0;
1445         info.flags = uap->flags;
1446         info.td = td;
1447
1448         get_mplock();
1449         mountlist_scan(getvfsstat_callback, &info, MNTSCAN_FORWARD);
1450         if (info.vsfsp && info.count > info.maxcount)
1451                 uap->sysmsg_result = info.maxcount;
1452         else
1453                 uap->sysmsg_result = info.count;
1454         rel_mplock();
1455         return (info.error);
1456 }
1457
1458 static int
1459 getvfsstat_callback(struct mount *mp, void *data)
1460 {
1461         struct getvfsstat_info *info = data;
1462         struct statfs *sp;
1463         struct statvfs *vsp;
1464         char *freepath;
1465         char *fullpath;
1466         int error;
1467
1468         if (info->vsfsp && info->count < info->maxcount) {
1469                 if (info->td->td_proc &&
1470                     !chroot_visible_mnt(mp, info->td->td_proc)) {
1471                         return(0);
1472                 }
1473                 sp = &mp->mnt_stat;
1474                 vsp = &mp->mnt_vstat;
1475
1476                 /*
1477                  * If MNT_NOWAIT or MNT_LAZY is specified, do not
1478                  * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY
1479                  * overrides MNT_WAIT.
1480                  */
1481                 if (((info->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
1482                     (info->flags & MNT_WAIT)) &&
1483                     (error = VFS_STATFS(mp, sp, info->td->td_ucred))) {
1484                         return(0);
1485                 }
1486                 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1487
1488                 if (((info->flags & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
1489                     (info->flags & MNT_WAIT)) &&
1490                     (error = VFS_STATVFS(mp, vsp, info->td->td_ucred))) {
1491                         return(0);
1492                 }
1493                 vsp->f_flag = 0;
1494                 if (mp->mnt_flag & MNT_RDONLY)
1495                         vsp->f_flag |= ST_RDONLY;
1496                 if (mp->mnt_flag & MNT_NOSUID)
1497                         vsp->f_flag |= ST_NOSUID;
1498
1499                 error = mount_path(info->td->td_proc, mp, &fullpath, &freepath);
1500                 if (error) {
1501                         info->error = error;
1502                         return(-1);
1503                 }
1504                 bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
1505                 strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
1506                 kfree(freepath, M_TEMP);
1507
1508                 error = copyout(sp, info->sfsp, sizeof(*sp));
1509                 if (error == 0)
1510                         error = copyout(vsp, info->vsfsp, sizeof(*vsp));
1511                 if (error) {
1512                         info->error = error;
1513                         return (-1);
1514                 }
1515                 ++info->sfsp;
1516                 ++info->vsfsp;
1517         }
1518         info->count++;
1519         return(0);
1520 }
1521
1522
1523 /*
1524  * fchdir_args(int fd)
1525  *
1526  * Change current working directory to a given file descriptor.
1527  *
1528  * MPALMOSTSAFE
1529  */
1530 int
1531 sys_fchdir(struct fchdir_args *uap)
1532 {
1533         struct thread *td = curthread;
1534         struct proc *p = td->td_proc;
1535         struct filedesc *fdp = p->p_fd;
1536         struct vnode *vp, *ovp;
1537         struct mount *mp;
1538         struct file *fp;
1539         struct nchandle nch, onch, tnch;
1540         int error;
1541
1542         if ((error = holdvnode(fdp, uap->fd, &fp)) != 0)
1543                 return (error);
1544         get_mplock();
1545         vp = (struct vnode *)fp->f_data;
1546         vref(vp);
1547         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1548         if (fp->f_nchandle.ncp == NULL)
1549                 error = ENOTDIR;
1550         else
1551                 error = checkvp_chdir(vp, td);
1552         if (error) {
1553                 vput(vp);
1554                 goto done;
1555         }
1556         cache_copy(&fp->f_nchandle, &nch);
1557
1558         /*
1559          * If the ncp has become a mount point, traverse through
1560          * the mount point.
1561          */
1562
1563         while (!error && (nch.ncp->nc_flag & NCF_ISMOUNTPT) &&
1564                (mp = cache_findmount(&nch)) != NULL
1565         ) {
1566                 error = nlookup_mp(mp, &tnch);
1567                 if (error == 0) {
1568                         cache_unlock(&tnch);    /* leave ref intact */
1569                         vput(vp);
1570                         vp = tnch.ncp->nc_vp;
1571                         error = vget(vp, LK_SHARED);
1572                         KKASSERT(error == 0);
1573                         cache_drop(&nch);
1574                         nch = tnch;
1575                 }
1576         }
1577         if (error == 0) {
1578                 ovp = fdp->fd_cdir;
1579                 onch = fdp->fd_ncdir;
1580                 vn_unlock(vp);          /* leave ref intact */
1581                 fdp->fd_cdir = vp;
1582                 fdp->fd_ncdir = nch;
1583                 cache_drop(&onch);
1584                 vrele(ovp);
1585         } else {
1586                 cache_drop(&nch);
1587                 vput(vp);
1588         }
1589         fdrop(fp);
1590 done:
1591         rel_mplock();
1592         return (error);
1593 }
1594
1595 int
1596 kern_chdir(struct nlookupdata *nd)
1597 {
1598         struct thread *td = curthread;
1599         struct proc *p = td->td_proc;
1600         struct filedesc *fdp = p->p_fd;
1601         struct vnode *vp, *ovp;
1602         struct nchandle onch;
1603         int error;
1604
1605         if ((error = nlookup(nd)) != 0)
1606                 return (error);
1607         if ((vp = nd->nl_nch.ncp->nc_vp) == NULL)
1608                 return (ENOENT);
1609         if ((error = vget(vp, LK_SHARED)) != 0)
1610                 return (error);
1611
1612         error = checkvp_chdir(vp, td);
1613         vn_unlock(vp);
1614         if (error == 0) {
1615                 ovp = fdp->fd_cdir;
1616                 onch = fdp->fd_ncdir;
1617                 cache_unlock(&nd->nl_nch);      /* leave reference intact */
1618                 fdp->fd_ncdir = nd->nl_nch;
1619                 fdp->fd_cdir = vp;
1620                 cache_drop(&onch);
1621                 vrele(ovp);
1622                 cache_zero(&nd->nl_nch);
1623         } else {
1624                 vrele(vp);
1625         }
1626         return (error);
1627 }
1628
1629 /*
1630  * chdir_args(char *path)
1631  *
1632  * Change current working directory (``.'').
1633  *
1634  * MPALMOSTSAFE
1635  */
1636 int
1637 sys_chdir(struct chdir_args *uap)
1638 {
1639         struct nlookupdata nd;
1640         int error;
1641
1642         get_mplock();
1643         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
1644         if (error == 0)
1645                 error = kern_chdir(&nd);
1646         nlookup_done(&nd);
1647         rel_mplock();
1648         return (error);
1649 }
1650
1651 /*
1652  * Helper function for raised chroot(2) security function:  Refuse if
1653  * any filedescriptors are open directories.
1654  */
1655 static int
1656 chroot_refuse_vdir_fds(struct filedesc *fdp)
1657 {
1658         struct vnode *vp;
1659         struct file *fp;
1660         int error;
1661         int fd;
1662
1663         for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
1664                 if ((error = holdvnode(fdp, fd, &fp)) != 0)
1665                         continue;
1666                 vp = (struct vnode *)fp->f_data;
1667                 if (vp->v_type != VDIR) {
1668                         fdrop(fp);
1669                         continue;
1670                 }
1671                 fdrop(fp);
1672                 return(EPERM);
1673         }
1674         return (0);
1675 }
1676
1677 /*
1678  * This sysctl determines if we will allow a process to chroot(2) if it
1679  * has a directory open:
1680  *      0: disallowed for all processes.
1681  *      1: allowed for processes that were not already chroot(2)'ed.
1682  *      2: allowed for all processes.
1683  */
1684
1685 static int chroot_allow_open_directories = 1;
1686
1687 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
1688      &chroot_allow_open_directories, 0, "");
1689
1690 /*
1691  * chroot to the specified namecache entry.  We obtain the vp from the
1692  * namecache data.  The passed ncp must be locked and referenced and will
1693  * remain locked and referenced on return.
1694  */
1695 int
1696 kern_chroot(struct nchandle *nch)
1697 {
1698         struct thread *td = curthread;
1699         struct proc *p = td->td_proc;
1700         struct filedesc *fdp = p->p_fd;
1701         struct vnode *vp;
1702         int error;
1703
1704         /*
1705          * Only privileged user can chroot
1706          */
1707         error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT, 0);
1708         if (error)
1709                 return (error);
1710
1711         /*
1712          * Disallow open directory descriptors (fchdir() breakouts).
1713          */
1714         if (chroot_allow_open_directories == 0 ||
1715            (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) {
1716                 if ((error = chroot_refuse_vdir_fds(fdp)) != 0)
1717                         return (error);
1718         }
1719         if ((vp = nch->ncp->nc_vp) == NULL)
1720                 return (ENOENT);
1721
1722         if ((error = vget(vp, LK_SHARED)) != 0)
1723                 return (error);
1724
1725         /*
1726          * Check the validity of vp as a directory to change to and 
1727          * associate it with rdir/jdir.
1728          */
1729         error = checkvp_chdir(vp, td);
1730         vn_unlock(vp);                  /* leave reference intact */
1731         if (error == 0) {
1732                 vrele(fdp->fd_rdir);
1733                 fdp->fd_rdir = vp;      /* reference inherited by fd_rdir */
1734                 cache_drop(&fdp->fd_nrdir);
1735                 cache_copy(nch, &fdp->fd_nrdir);
1736                 if (fdp->fd_jdir == NULL) {
1737                         fdp->fd_jdir = vp;
1738                         vref(fdp->fd_jdir);
1739                         cache_copy(nch, &fdp->fd_njdir);
1740                 }
1741         } else {
1742                 vrele(vp);
1743         }
1744         return (error);
1745 }
1746
1747 /*
1748  * chroot_args(char *path)
1749  *
1750  * Change notion of root (``/'') directory.
1751  *
1752  * MPALMOSTSAFE
1753  */
1754 int
1755 sys_chroot(struct chroot_args *uap)
1756 {
1757         struct thread *td __debugvar = curthread;
1758         struct nlookupdata nd;
1759         int error;
1760
1761         KKASSERT(td->td_proc);
1762         get_mplock();
1763         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
1764         if (error == 0) {
1765                 nd.nl_flags |= NLC_EXEC;
1766                 error = nlookup(&nd);
1767                 if (error == 0)
1768                         error = kern_chroot(&nd.nl_nch);
1769         }
1770         nlookup_done(&nd);
1771         rel_mplock();
1772         return(error);
1773 }
1774
1775 int
1776 sys_chroot_kernel(struct chroot_kernel_args *uap)
1777 {
1778         struct thread *td = curthread;
1779         struct nlookupdata nd;
1780         struct nchandle *nch;
1781         struct vnode *vp;
1782         int error;
1783
1784         get_mplock();
1785         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
1786         if (error)
1787                 goto error_nond;
1788
1789         error = nlookup(&nd);
1790         if (error)
1791                 goto error_out;
1792
1793         nch = &nd.nl_nch;
1794
1795         error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT, 0);
1796         if (error)
1797                 goto error_out;
1798
1799         if ((vp = nch->ncp->nc_vp) == NULL) {
1800                 error = ENOENT;
1801                 goto error_out;
1802         }
1803
1804         if ((error = cache_vref(nch, nd.nl_cred, &vp)) != 0)
1805                 goto error_out;
1806
1807         kprintf("chroot_kernel: set new rootnch/rootvnode to %s\n", uap->path);
1808         vfs_cache_setroot(vp, cache_hold(nch));
1809
1810 error_out:
1811         nlookup_done(&nd);
1812 error_nond:
1813         rel_mplock();
1814         return(error);
1815 }
1816
1817 /*
1818  * Common routine for chroot and chdir.  Given a locked, referenced vnode,
1819  * determine whether it is legal to chdir to the vnode.  The vnode's state
1820  * is not changed by this call.
1821  */
1822 int
1823 checkvp_chdir(struct vnode *vp, struct thread *td)
1824 {
1825         int error;
1826
1827         if (vp->v_type != VDIR)
1828                 error = ENOTDIR;
1829         else
1830                 error = VOP_EACCESS(vp, VEXEC, td->td_ucred);
1831         return (error);
1832 }
1833
1834 /*
1835  * MPSAFE
1836  */
1837 int
1838 kern_open(struct nlookupdata *nd, int oflags, int mode, int *res)
1839 {
1840         struct thread *td = curthread;
1841         struct proc *p = td->td_proc;
1842         struct lwp *lp = td->td_lwp;
1843         struct filedesc *fdp = p->p_fd;
1844         int cmode, flags;
1845         struct file *nfp;
1846         struct file *fp;
1847         struct vnode *vp;
1848         int type, indx, error;
1849         struct flock lf;
1850
1851         if ((oflags & O_ACCMODE) == O_ACCMODE)
1852                 return (EINVAL);
1853         flags = FFLAGS(oflags);
1854         error = falloc(lp, &nfp, NULL);
1855         if (error)
1856                 return (error);
1857         fp = nfp;
1858         cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT;
1859
1860         /*
1861          * XXX p_dupfd is a real mess.  It allows a device to return a
1862          * file descriptor to be duplicated rather then doing the open
1863          * itself.
1864          */
1865         lp->lwp_dupfd = -1;
1866
1867         /*
1868          * Call vn_open() to do the lookup and assign the vnode to the 
1869          * file pointer.  vn_open() does not change the ref count on fp
1870          * and the vnode, on success, will be inherited by the file pointer
1871          * and unlocked.
1872          */
1873         nd->nl_flags |= NLC_LOCKVP;
1874         error = vn_open(nd, fp, flags, cmode);
1875         nlookup_done(nd);
1876         if (error) {
1877                 /*
1878                  * handle special fdopen() case.  bleh.  dupfdopen() is
1879                  * responsible for dropping the old contents of ofiles[indx]
1880                  * if it succeeds.
1881                  *
1882                  * Note that fsetfd() will add a ref to fp which represents
1883                  * the fd_files[] assignment.  We must still drop our
1884                  * reference.
1885                  */
1886                 if ((error == ENODEV || error == ENXIO) && lp->lwp_dupfd >= 0) {
1887                         if (fdalloc(p, 0, &indx) == 0) {
1888                                 error = dupfdopen(fdp, indx, lp->lwp_dupfd, flags, error);
1889                                 if (error == 0) {
1890                                         *res = indx;
1891                                         fdrop(fp);      /* our ref */
1892                                         return (0);
1893                                 }
1894                                 fsetfd(fdp, NULL, indx);
1895                         }
1896                 }
1897                 fdrop(fp);      /* our ref */
1898                 if (error == ERESTART)
1899                         error = EINTR;
1900                 return (error);
1901         }
1902
1903         /*
1904          * ref the vnode for ourselves so it can't be ripped out from under
1905          * is.  XXX need an ND flag to request that the vnode be returned
1906          * anyway.
1907          *
1908          * Reserve a file descriptor but do not assign it until the open
1909          * succeeds.
1910          */
1911         vp = (struct vnode *)fp->f_data;
1912         vref(vp);
1913         if ((error = fdalloc(p, 0, &indx)) != 0) {
1914                 fdrop(fp);
1915                 vrele(vp);
1916                 return (error);
1917         }
1918
1919         /*
1920          * If no error occurs the vp will have been assigned to the file
1921          * pointer.
1922          */
1923         lp->lwp_dupfd = 0;
1924
1925         if (flags & (O_EXLOCK | O_SHLOCK)) {
1926                 lf.l_whence = SEEK_SET;
1927                 lf.l_start = 0;
1928                 lf.l_len = 0;
1929                 if (flags & O_EXLOCK)
1930                         lf.l_type = F_WRLCK;
1931                 else
1932                         lf.l_type = F_RDLCK;
1933                 if (flags & FNONBLOCK)
1934                         type = 0;
1935                 else
1936                         type = F_WAIT;
1937
1938                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
1939                         /*
1940                          * lock request failed.  Clean up the reserved
1941                          * descriptor.
1942                          */
1943                         vrele(vp);
1944                         fsetfd(fdp, NULL, indx);
1945                         fdrop(fp);
1946                         return (error);
1947                 }
1948                 fp->f_flag |= FHASLOCK;
1949         }
1950 #if 0
1951         /*
1952          * Assert that all regular file vnodes were created with a object.
1953          */
1954         KASSERT(vp->v_type != VREG || vp->v_object != NULL,
1955                 ("open: regular file has no backing object after vn_open"));
1956 #endif
1957
1958         vrele(vp);
1959
1960         /*
1961          * release our private reference, leaving the one associated with the
1962          * descriptor table intact.
1963          */
1964         fsetfd(fdp, fp, indx);
1965         fdrop(fp);
1966         *res = indx;
1967         return (0);
1968 }
1969
1970 /*
1971  * open_args(char *path, int flags, int mode)
1972  *
1973  * Check permissions, allocate an open file structure,
1974  * and call the device open routine if any.
1975  *
1976  * MPALMOSTSAFE
1977  */
1978 int
1979 sys_open(struct open_args *uap)
1980 {
1981         struct nlookupdata nd;
1982         int error;
1983
1984         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
1985         if (error == 0) {
1986                 error = kern_open(&nd, uap->flags,
1987                                     uap->mode, &uap->sysmsg_result);
1988         }
1989         nlookup_done(&nd);
1990         return (error);
1991 }
1992
1993 /*
1994  * openat_args(int fd, char *path, int flags, int mode)
1995  *
1996  * MPALMOSTSAFE
1997  */
1998 int
1999 sys_openat(struct openat_args *uap)
2000 {
2001         struct nlookupdata nd;
2002         int error;
2003         struct file *fp;
2004
2005         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
2006         if (error == 0) {
2007                 error = kern_open(&nd, uap->flags, uap->mode, 
2008                                         &uap->sysmsg_result);
2009         }
2010         nlookup_done_at(&nd, fp);
2011         return (error);
2012 }
2013
2014 int
2015 kern_mknod(struct nlookupdata *nd, int mode, int rmajor, int rminor)
2016 {
2017         struct thread *td = curthread;
2018         struct proc *p = td->td_proc;
2019         struct vnode *vp;
2020         struct vattr vattr;
2021         int error;
2022         int whiteout = 0;
2023
2024         KKASSERT(p);
2025
2026         VATTR_NULL(&vattr);
2027         vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask;
2028         vattr.va_rmajor = rmajor;
2029         vattr.va_rminor = rminor;
2030
2031         switch (mode & S_IFMT) {
2032         case S_IFMT:    /* used by badsect to flag bad sectors */
2033                 error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_BAD, 0);
2034                 vattr.va_type = VBAD;
2035                 break;
2036         case S_IFCHR:
2037                 error = priv_check(td, PRIV_VFS_MKNOD_DEV);
2038                 vattr.va_type = VCHR;
2039                 break;
2040         case S_IFBLK:
2041                 error = priv_check(td, PRIV_VFS_MKNOD_DEV);
2042                 vattr.va_type = VBLK;
2043                 break;
2044         case S_IFWHT:
2045                 error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_WHT, 0);
2046                 whiteout = 1;
2047                 break;
2048         case S_IFDIR:   /* special directories support for HAMMER */
2049                 error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_DIR, 0);
2050                 vattr.va_type = VDIR;
2051                 break;
2052         default:
2053                 error = EINVAL;
2054                 break;
2055         }
2056
2057         if (error)
2058                 return (error);
2059
2060         bwillinode(1);
2061         nd->nl_flags |= NLC_CREATE | NLC_REFDVP;
2062         if ((error = nlookup(nd)) != 0)
2063                 return (error);
2064         if (nd->nl_nch.ncp->nc_vp)
2065                 return (EEXIST);
2066         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2067                 return (error);
2068
2069         if (whiteout) {
2070                 error = VOP_NWHITEOUT(&nd->nl_nch, nd->nl_dvp,
2071                                       nd->nl_cred, NAMEI_CREATE);
2072         } else {
2073                 vp = NULL;
2074                 error = VOP_NMKNOD(&nd->nl_nch, nd->nl_dvp,
2075                                    &vp, nd->nl_cred, &vattr);
2076                 if (error == 0)
2077                         vput(vp);
2078         }
2079         return (error);
2080 }
2081
2082 /*
2083  * mknod_args(char *path, int mode, int dev)
2084  *
2085  * Create a special file.
2086  *
2087  * MPALMOSTSAFE
2088  */
2089 int
2090 sys_mknod(struct mknod_args *uap)
2091 {
2092         struct nlookupdata nd;
2093         int error;
2094
2095         get_mplock();
2096         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2097         if (error == 0) {
2098                 error = kern_mknod(&nd, uap->mode,
2099                                    umajor(uap->dev), uminor(uap->dev));
2100         }
2101         nlookup_done(&nd);
2102         rel_mplock();
2103         return (error);
2104 }
2105
2106 /*
2107  * mknodat_args(int fd, char *path, mode_t mode, dev_t dev)
2108  *
2109  * Create a special file.  The path is relative to the directory associated
2110  * with fd.
2111  *
2112  * MPALMOSTSAFE
2113  */
2114 int
2115 sys_mknodat(struct mknodat_args *uap)
2116 {
2117         struct nlookupdata nd;
2118         struct file *fp;
2119         int error;
2120
2121         get_mplock();
2122         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
2123         if (error == 0) {
2124                 error = kern_mknod(&nd, uap->mode,
2125                                    umajor(uap->dev), uminor(uap->dev));
2126         }
2127         nlookup_done_at(&nd, fp);
2128         rel_mplock();
2129         return (error);
2130 }
2131
2132 int
2133 kern_mkfifo(struct nlookupdata *nd, int mode)
2134 {
2135         struct thread *td = curthread;
2136         struct proc *p = td->td_proc;
2137         struct vattr vattr;
2138         struct vnode *vp;
2139         int error;
2140
2141         bwillinode(1);
2142
2143         nd->nl_flags |= NLC_CREATE | NLC_REFDVP;
2144         if ((error = nlookup(nd)) != 0)
2145                 return (error);
2146         if (nd->nl_nch.ncp->nc_vp)
2147                 return (EEXIST);
2148         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2149                 return (error);
2150
2151         VATTR_NULL(&vattr);
2152         vattr.va_type = VFIFO;
2153         vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask;
2154         vp = NULL;
2155         error = VOP_NMKNOD(&nd->nl_nch, nd->nl_dvp, &vp, nd->nl_cred, &vattr);
2156         if (error == 0)
2157                 vput(vp);
2158         return (error);
2159 }
2160
2161 /*
2162  * mkfifo_args(char *path, int mode)
2163  *
2164  * Create a named pipe.
2165  *
2166  * MPALMOSTSAFE
2167  */
2168 int
2169 sys_mkfifo(struct mkfifo_args *uap)
2170 {
2171         struct nlookupdata nd;
2172         int error;
2173
2174         get_mplock();
2175         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2176         if (error == 0)
2177                 error = kern_mkfifo(&nd, uap->mode);
2178         nlookup_done(&nd);
2179         rel_mplock();
2180         return (error);
2181 }
2182
2183 /*
2184  * mkfifoat_args(int fd, char *path, mode_t mode)
2185  *
2186  * Create a named pipe.  The path is relative to the directory associated
2187  * with fd.
2188  *
2189  * MPALMOSTSAFE
2190  */
2191 int
2192 sys_mkfifoat(struct mkfifoat_args *uap)
2193 {
2194         struct nlookupdata nd;
2195         struct file *fp;
2196         int error;
2197
2198         get_mplock();
2199         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
2200         if (error == 0)
2201                 error = kern_mkfifo(&nd, uap->mode);
2202         nlookup_done_at(&nd, fp);
2203         rel_mplock();
2204         return (error);
2205 }
2206
2207 static int hardlink_check_uid = 0;
2208 SYSCTL_INT(_security, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
2209     &hardlink_check_uid, 0, 
2210     "Unprivileged processes cannot create hard links to files owned by other "
2211     "users");
2212 static int hardlink_check_gid = 0;
2213 SYSCTL_INT(_security, OID_AUTO, hardlink_check_gid, CTLFLAG_RW,
2214     &hardlink_check_gid, 0,
2215     "Unprivileged processes cannot create hard links to files owned by other "
2216     "groups");
2217
2218 static int
2219 can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
2220 {
2221         struct vattr va;
2222         int error;
2223
2224         /*
2225          * Shortcut if disabled
2226          */
2227         if (hardlink_check_uid == 0 && hardlink_check_gid == 0)
2228                 return (0);
2229
2230         /*
2231          * Privileged user can always hardlink
2232          */
2233         if (priv_check_cred(cred, PRIV_VFS_LINK, 0) == 0)
2234                 return (0);
2235
2236         /*
2237          * Otherwise only if the originating file is owned by the
2238          * same user or group.  Note that any group is allowed if
2239          * the file is owned by the caller.
2240          */
2241         error = VOP_GETATTR(vp, &va);
2242         if (error != 0)
2243                 return (error);
2244         
2245         if (hardlink_check_uid) {
2246                 if (cred->cr_uid != va.va_uid)
2247                         return (EPERM);
2248         }
2249         
2250         if (hardlink_check_gid) {
2251                 if (cred->cr_uid != va.va_uid && !groupmember(va.va_gid, cred))
2252                         return (EPERM);
2253         }
2254
2255         return (0);
2256 }
2257
2258 int
2259 kern_link(struct nlookupdata *nd, struct nlookupdata *linknd)
2260 {
2261         struct thread *td = curthread;
2262         struct vnode *vp;
2263         int error;
2264
2265         /*
2266          * Lookup the source and obtained a locked vnode.
2267          *
2268          * You may only hardlink a file which you have write permission
2269          * on or which you own.
2270          *
2271          * XXX relookup on vget failure / race ?
2272          */
2273         bwillinode(1);
2274         nd->nl_flags |= NLC_WRITE | NLC_OWN | NLC_HLINK;
2275         if ((error = nlookup(nd)) != 0)
2276                 return (error);
2277         vp = nd->nl_nch.ncp->nc_vp;
2278         KKASSERT(vp != NULL);
2279         if (vp->v_type == VDIR)
2280                 return (EPERM);         /* POSIX */
2281         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2282                 return (error);
2283         if ((error = vget(vp, LK_EXCLUSIVE)) != 0)
2284                 return (error);
2285
2286         /*
2287          * Unlock the source so we can lookup the target without deadlocking
2288          * (XXX vp is locked already, possible other deadlock?).  The target
2289          * must not exist.
2290          */
2291         KKASSERT(nd->nl_flags & NLC_NCPISLOCKED);
2292         nd->nl_flags &= ~NLC_NCPISLOCKED;
2293         cache_unlock(&nd->nl_nch);
2294         vn_unlock(vp);
2295
2296         linknd->nl_flags |= NLC_CREATE | NLC_REFDVP;
2297         if ((error = nlookup(linknd)) != 0) {
2298                 vrele(vp);
2299                 return (error);
2300         }
2301         if (linknd->nl_nch.ncp->nc_vp) {
2302                 vrele(vp);
2303                 return (EEXIST);
2304         }
2305         if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) {
2306                 vrele(vp);
2307                 return (error);
2308         }
2309
2310         /*
2311          * Finally run the new API VOP.
2312          */
2313         error = can_hardlink(vp, td, td->td_ucred);
2314         if (error == 0) {
2315                 error = VOP_NLINK(&linknd->nl_nch, linknd->nl_dvp,
2316                                   vp, linknd->nl_cred);
2317         }
2318         vput(vp);
2319         return (error);
2320 }
2321
2322 /*
2323  * link_args(char *path, char *link)
2324  *
2325  * Make a hard file link.
2326  *
2327  * MPALMOSTSAFE
2328  */
2329 int
2330 sys_link(struct link_args *uap)
2331 {
2332         struct nlookupdata nd, linknd;
2333         int error;
2334
2335         get_mplock();
2336         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2337         if (error == 0) {
2338                 error = nlookup_init(&linknd, uap->link, UIO_USERSPACE, 0);
2339                 if (error == 0)
2340                         error = kern_link(&nd, &linknd);
2341                 nlookup_done(&linknd);
2342         }
2343         nlookup_done(&nd);
2344         rel_mplock();
2345         return (error);
2346 }
2347
2348 int
2349 kern_symlink(struct nlookupdata *nd, char *path, int mode)
2350 {
2351         struct vattr vattr;
2352         struct vnode *vp;
2353         struct vnode *dvp;
2354         int error;
2355
2356         bwillinode(1);
2357         nd->nl_flags |= NLC_CREATE | NLC_REFDVP;
2358         if ((error = nlookup(nd)) != 0)
2359                 return (error);
2360         if (nd->nl_nch.ncp->nc_vp)
2361                 return (EEXIST);
2362         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2363                 return (error);
2364         dvp = nd->nl_dvp;
2365         VATTR_NULL(&vattr);
2366         vattr.va_mode = mode;
2367         error = VOP_NSYMLINK(&nd->nl_nch, dvp, &vp, nd->nl_cred, &vattr, path);
2368         if (error == 0)
2369                 vput(vp);
2370         return (error);
2371 }
2372
2373 /*
2374  * symlink(char *path, char *link)
2375  *
2376  * Make a symbolic link.
2377  *
2378  * MPALMOSTSAFE
2379  */
2380 int
2381 sys_symlink(struct symlink_args *uap)
2382 {
2383         struct thread *td = curthread;
2384         struct nlookupdata nd;
2385         char *path;
2386         int error;
2387         int mode;
2388
2389         path = objcache_get(namei_oc, M_WAITOK);
2390         error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
2391         if (error == 0) {
2392                 get_mplock();
2393                 error = nlookup_init(&nd, uap->link, UIO_USERSPACE, 0);
2394                 if (error == 0) {
2395                         mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
2396                         error = kern_symlink(&nd, path, mode);
2397                 }
2398                 nlookup_done(&nd);
2399                 rel_mplock();
2400         }
2401         objcache_put(namei_oc, path);
2402         return (error);
2403 }
2404
2405 /*
2406  * symlinkat_args(char *path1, int fd, char *path2)
2407  *
2408  * Make a symbolic link.  The path2 argument is relative to the directory
2409  * associated with fd.
2410  *
2411  * MPALMOSTSAFE
2412  */
2413 int
2414 sys_symlinkat(struct symlinkat_args *uap)
2415 {
2416         struct thread *td = curthread;
2417         struct nlookupdata nd;
2418         struct file *fp;
2419         char *path1;
2420         int error;
2421         int mode;
2422
2423         path1 = objcache_get(namei_oc, M_WAITOK);
2424         error = copyinstr(uap->path1, path1, MAXPATHLEN, NULL);
2425         if (error == 0) {
2426                 get_mplock();
2427                 error = nlookup_init_at(&nd, &fp, uap->fd, uap->path2,
2428                     UIO_USERSPACE, 0);
2429                 if (error == 0) {
2430                         mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
2431                         error = kern_symlink(&nd, path1, mode);
2432                 }
2433                 nlookup_done_at(&nd, fp);
2434                 rel_mplock();
2435         }
2436         objcache_put(namei_oc, path1);
2437         return (error);
2438 }
2439
2440 /*
2441  * undelete_args(char *path)
2442  *
2443  * Delete a whiteout from the filesystem.
2444  *
2445  * MPALMOSTSAFE
2446  */
2447 int
2448 sys_undelete(struct undelete_args *uap)
2449 {
2450         struct nlookupdata nd;
2451         int error;
2452
2453         get_mplock();
2454         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2455         bwillinode(1);
2456         nd.nl_flags |= NLC_DELETE | NLC_REFDVP;
2457         if (error == 0)
2458                 error = nlookup(&nd);
2459         if (error == 0)
2460                 error = ncp_writechk(&nd.nl_nch);
2461         if (error == 0) {
2462                 error = VOP_NWHITEOUT(&nd.nl_nch, nd.nl_dvp, nd.nl_cred,
2463                                       NAMEI_DELETE);
2464         }
2465         nlookup_done(&nd);
2466         rel_mplock();
2467         return (error);
2468 }
2469
2470 int
2471 kern_unlink(struct nlookupdata *nd)
2472 {
2473         int error;
2474
2475         bwillinode(1);
2476         nd->nl_flags |= NLC_DELETE | NLC_REFDVP;
2477         if ((error = nlookup(nd)) != 0)
2478                 return (error);
2479         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2480                 return (error);
2481         error = VOP_NREMOVE(&nd->nl_nch, nd->nl_dvp, nd->nl_cred);
2482         return (error);
2483 }
2484
2485 /*
2486  * unlink_args(char *path)
2487  *
2488  * Delete a name from the filesystem.
2489  *
2490  * MPALMOSTSAFE
2491  */
2492 int
2493 sys_unlink(struct unlink_args *uap)
2494 {
2495         struct nlookupdata nd;
2496         int error;
2497
2498         get_mplock();
2499         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2500         if (error == 0)
2501                 error = kern_unlink(&nd);
2502         nlookup_done(&nd);
2503         rel_mplock();
2504         return (error);
2505 }
2506
2507
2508 /*
2509  * unlinkat_args(int fd, char *path, int flags)
2510  *
2511  * Delete the file or directory entry pointed to by fd/path.
2512  *
2513  * MPALMOSTSAFE
2514  */
2515 int
2516 sys_unlinkat(struct unlinkat_args *uap)
2517 {
2518         struct nlookupdata nd;
2519         struct file *fp;
2520         int error;
2521
2522         if (uap->flags & ~AT_REMOVEDIR)
2523                 return (EINVAL);
2524
2525         get_mplock();
2526         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
2527         if (error == 0) {
2528                 if (uap->flags & AT_REMOVEDIR)
2529                         error = kern_rmdir(&nd);
2530                 else
2531                         error = kern_unlink(&nd);
2532         }
2533         nlookup_done_at(&nd, fp);
2534         rel_mplock();
2535         return (error);
2536 }
2537
2538 /*
2539  * MPALMOSTSAFE
2540  */
2541 int
2542 kern_lseek(int fd, off_t offset, int whence, off_t *res)
2543 {
2544         struct thread *td = curthread;
2545         struct proc *p = td->td_proc;
2546         struct file *fp;
2547         struct vnode *vp;
2548         struct vattr vattr;
2549         off_t new_offset;
2550         int error;
2551
2552         fp = holdfp(p->p_fd, fd, -1);
2553         if (fp == NULL)
2554                 return (EBADF);
2555         if (fp->f_type != DTYPE_VNODE) {
2556                 error = ESPIPE;
2557                 goto done;
2558         }
2559         vp = (struct vnode *)fp->f_data;
2560
2561         switch (whence) {
2562         case L_INCR:
2563                 spin_lock(&fp->f_spin);
2564                 new_offset = fp->f_offset + offset;
2565                 error = 0;
2566                 break;
2567         case L_XTND:
2568                 get_mplock();
2569                 error = VOP_GETATTR(vp, &vattr);
2570                 rel_mplock();
2571                 spin_lock(&fp->f_spin);
2572                 new_offset = offset + vattr.va_size;
2573                 break;
2574         case L_SET:
2575                 new_offset = offset;
2576                 error = 0;
2577                 spin_lock(&fp->f_spin);
2578                 break;
2579         default:
2580                 new_offset = 0;
2581                 error = EINVAL;
2582                 spin_lock(&fp->f_spin);
2583                 break;
2584         }
2585
2586         /*
2587          * Validate the seek position.  Negative offsets are not allowed
2588          * for regular files or directories.
2589          *
2590          * Normally we would also not want to allow negative offsets for
2591          * character and block-special devices.  However kvm addresses
2592          * on 64 bit architectures might appear to be negative and must
2593          * be allowed.
2594          */
2595         if (error == 0) {
2596                 if (new_offset < 0 &&
2597                     (vp->v_type == VREG || vp->v_type == VDIR)) {
2598                         error = EINVAL;
2599                 } else {
2600                         fp->f_offset = new_offset;
2601                 }
2602         }
2603         *res = fp->f_offset;
2604         spin_unlock(&fp->f_spin);
2605 done:
2606         fdrop(fp);
2607         return (error);
2608 }
2609
2610 /*
2611  * lseek_args(int fd, int pad, off_t offset, int whence)
2612  *
2613  * Reposition read/write file offset.
2614  *
2615  * MPSAFE
2616  */
2617 int
2618 sys_lseek(struct lseek_args *uap)
2619 {
2620         int error;
2621
2622         error = kern_lseek(uap->fd, uap->offset, uap->whence,
2623                            &uap->sysmsg_offset);
2624
2625         return (error);
2626 }
2627
2628 /*
2629  * Check if current process can access given file.  amode is a bitmask of *_OK
2630  * access bits.  flags is a bitmask of AT_* flags.
2631  */
2632 int
2633 kern_access(struct nlookupdata *nd, int amode, int flags)
2634 {
2635         struct vnode *vp;
2636         int error, mode;
2637
2638         if (flags & ~AT_EACCESS)
2639                 return (EINVAL);
2640         if ((error = nlookup(nd)) != 0)
2641                 return (error);
2642 retry:
2643         error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, &vp);
2644         if (error)
2645                 return (error);
2646
2647         /* Flags == 0 means only check for existence. */
2648         if (amode) {
2649                 mode = 0;
2650                 if (amode & R_OK)
2651                         mode |= VREAD;
2652                 if (amode & W_OK)
2653                         mode |= VWRITE;
2654                 if (amode & X_OK)
2655                         mode |= VEXEC;
2656                 if ((mode & VWRITE) == 0 || 
2657                     (error = vn_writechk(vp, &nd->nl_nch)) == 0)
2658                         error = VOP_ACCESS_FLAGS(vp, mode, flags, nd->nl_cred);
2659
2660                 /*
2661                  * If the file handle is stale we have to re-resolve the
2662                  * entry.  This is a hack at the moment.
2663                  */
2664                 if (error == ESTALE) {
2665                         vput(vp);
2666                         cache_setunresolved(&nd->nl_nch);
2667                         error = cache_resolve(&nd->nl_nch, nd->nl_cred);
2668                         if (error == 0) {
2669                                 vp = NULL;
2670                                 goto retry;
2671                         }
2672                         return(error);
2673                 }
2674         }
2675         vput(vp);
2676         return (error);
2677 }
2678
2679 /*
2680  * access_args(char *path, int flags)
2681  *
2682  * Check access permissions.
2683  *
2684  * MPALMOSTSAFE
2685  */
2686 int
2687 sys_access(struct access_args *uap)
2688 {
2689         struct nlookupdata nd;
2690         int error;
2691
2692         get_mplock();
2693         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2694         if (error == 0)
2695                 error = kern_access(&nd, uap->flags, 0);
2696         nlookup_done(&nd);
2697         rel_mplock();
2698         return (error);
2699 }
2700
2701
2702 /*
2703  * faccessat_args(int fd, char *path, int amode, int flags)
2704  *
2705  * Check access permissions.
2706  *
2707  * MPALMOSTSAFE
2708  */
2709 int
2710 sys_faccessat(struct faccessat_args *uap)
2711 {
2712         struct nlookupdata nd;
2713         struct file *fp;
2714         int error;
2715
2716         get_mplock();
2717         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 
2718                                 NLC_FOLLOW);
2719         if (error == 0)
2720                 error = kern_access(&nd, uap->amode, uap->flags);
2721         nlookup_done_at(&nd, fp);
2722         rel_mplock();
2723         return (error);
2724 }
2725
2726
2727 /*
2728  * MPSAFE
2729  */
2730 int
2731 kern_stat(struct nlookupdata *nd, struct stat *st)
2732 {
2733         int error;
2734         struct vnode *vp;
2735         thread_t td;
2736
2737         if ((error = nlookup(nd)) != 0)
2738                 return (error);
2739 again:
2740         if ((vp = nd->nl_nch.ncp->nc_vp) == NULL)
2741                 return (ENOENT);
2742
2743         td = curthread;
2744         if ((error = vget(vp, LK_SHARED)) != 0)
2745                 return (error);
2746         error = vn_stat(vp, st, nd->nl_cred);
2747
2748         /*
2749          * If the file handle is stale we have to re-resolve the entry.  This
2750          * is a hack at the moment.
2751          */
2752         if (error == ESTALE) {
2753                 vput(vp);
2754                 cache_setunresolved(&nd->nl_nch);
2755                 error = cache_resolve(&nd->nl_nch, nd->nl_cred);
2756                 if (error == 0)
2757                         goto again;
2758         } else {
2759                 vput(vp);
2760         }
2761         return (error);
2762 }
2763
2764 /*
2765  * stat_args(char *path, struct stat *ub)
2766  *
2767  * Get file status; this version follows links.
2768  *
2769  * MPSAFE
2770  */
2771 int
2772 sys_stat(struct stat_args *uap)
2773 {
2774         struct nlookupdata nd;
2775         struct stat st;
2776         int error;
2777
2778         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2779         if (error == 0) {
2780                 error = kern_stat(&nd, &st);
2781                 if (error == 0)
2782                         error = copyout(&st, uap->ub, sizeof(*uap->ub));
2783         }
2784         nlookup_done(&nd);
2785         return (error);
2786 }
2787
2788 /*
2789  * lstat_args(char *path, struct stat *ub)
2790  *
2791  * Get file status; this version does not follow links.
2792  *
2793  * MPALMOSTSAFE
2794  */
2795 int
2796 sys_lstat(struct lstat_args *uap)
2797 {
2798         struct nlookupdata nd;
2799         struct stat st;
2800         int error;
2801
2802         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2803         if (error == 0) {
2804                 error = kern_stat(&nd, &st);
2805                 if (error == 0)
2806                         error = copyout(&st, uap->ub, sizeof(*uap->ub));
2807         }
2808         nlookup_done(&nd);
2809         return (error);
2810 }
2811
2812 /*
2813  * fstatat_args(int fd, char *path, struct stat *sb, int flags)
2814  *
2815  * Get status of file pointed to by fd/path.
2816  *
2817  * MPALMOSTSAFE
2818  */
2819 int
2820 sys_fstatat(struct fstatat_args *uap)
2821 {
2822         struct nlookupdata nd;
2823         struct stat st;
2824         int error;
2825         int flags;
2826         struct file *fp;
2827
2828         if (uap->flags & ~AT_SYMLINK_NOFOLLOW)
2829                 return (EINVAL);
2830
2831         flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
2832
2833         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 
2834                                 UIO_USERSPACE, flags);
2835         if (error == 0) {
2836                 error = kern_stat(&nd, &st);
2837                 if (error == 0)
2838                         error = copyout(&st, uap->sb, sizeof(*uap->sb));
2839         }
2840         nlookup_done_at(&nd, fp);
2841         return (error);
2842 }
2843
2844 /*
2845  * pathconf_Args(char *path, int name)
2846  *
2847  * Get configurable pathname variables.
2848  *
2849  * MPALMOSTSAFE
2850  */
2851 int
2852 sys_pathconf(struct pathconf_args *uap)
2853 {
2854         struct nlookupdata nd;
2855         struct vnode *vp;
2856         int error;
2857
2858         vp = NULL;
2859         get_mplock();
2860         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2861         if (error == 0)
2862                 error = nlookup(&nd);
2863         if (error == 0)
2864                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
2865         nlookup_done(&nd);
2866         if (error == 0) {
2867                 error = VOP_PATHCONF(vp, uap->name, &uap->sysmsg_reg);
2868                 vput(vp);
2869         }
2870         rel_mplock();
2871         return (error);
2872 }
2873
2874 /*
2875  * XXX: daver
2876  * kern_readlink isn't properly split yet.  There is a copyin burried
2877  * in VOP_READLINK().
2878  */
2879 int
2880 kern_readlink(struct nlookupdata *nd, char *buf, int count, int *res)
2881 {
2882         struct thread *td = curthread;
2883         struct vnode *vp;
2884         struct iovec aiov;
2885         struct uio auio;
2886         int error;
2887
2888         if ((error = nlookup(nd)) != 0)
2889                 return (error);
2890         error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, &vp);
2891         if (error)
2892                 return (error);
2893         if (vp->v_type != VLNK) {
2894                 error = EINVAL;
2895         } else {
2896                 aiov.iov_base = buf;
2897                 aiov.iov_len = count;
2898                 auio.uio_iov = &aiov;
2899                 auio.uio_iovcnt = 1;
2900                 auio.uio_offset = 0;
2901                 auio.uio_rw = UIO_READ;
2902                 auio.uio_segflg = UIO_USERSPACE;
2903                 auio.uio_td = td;
2904                 auio.uio_resid = count;
2905                 error = VOP_READLINK(vp, &auio, td->td_ucred);
2906         }
2907         vput(vp);
2908         *res = count - auio.uio_resid;
2909         return (error);
2910 }
2911
2912 /*
2913  * readlink_args(char *path, char *buf, int count)
2914  *
2915  * Return target name of a symbolic link.
2916  *
2917  * MPALMOSTSAFE
2918  */
2919 int
2920 sys_readlink(struct readlink_args *uap)
2921 {
2922         struct nlookupdata nd;
2923         int error;
2924
2925         get_mplock();
2926         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2927         if (error == 0) {
2928                 error = kern_readlink(&nd, uap->buf, uap->count,
2929                                         &uap->sysmsg_result);
2930         }
2931         nlookup_done(&nd);
2932         rel_mplock();
2933         return (error);
2934 }
2935
2936 /*
2937  * readlinkat_args(int fd, char *path, char *buf, size_t bufsize)
2938  *
2939  * Return target name of a symbolic link.  The path is relative to the
2940  * directory associated with fd.
2941  *
2942  * MPALMOSTSAFE
2943  */
2944 int
2945 sys_readlinkat(struct readlinkat_args *uap)
2946 {
2947         struct nlookupdata nd;
2948         struct file *fp;
2949         int error;
2950
2951         get_mplock();
2952         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
2953         if (error == 0) {
2954                 error = kern_readlink(&nd, uap->buf, uap->bufsize,
2955                                         &uap->sysmsg_result);
2956         }
2957         nlookup_done_at(&nd, fp);
2958         rel_mplock();
2959         return (error);
2960 }
2961
2962 static int
2963 setfflags(struct vnode *vp, int flags)
2964 {
2965         struct thread *td = curthread;
2966         int error;
2967         struct vattr vattr;
2968
2969         /*
2970          * Prevent non-root users from setting flags on devices.  When
2971          * a device is reused, users can retain ownership of the device
2972          * if they are allowed to set flags and programs assume that
2973          * chown can't fail when done as root.
2974          */
2975         if ((vp->v_type == VCHR || vp->v_type == VBLK) && 
2976             ((error = priv_check_cred(td->td_ucred, PRIV_VFS_CHFLAGS_DEV, 0)) != 0))
2977                 return (error);
2978
2979         /*
2980          * note: vget is required for any operation that might mod the vnode
2981          * so VINACTIVE is properly cleared.
2982          */
2983         if ((error = vget(vp, LK_EXCLUSIVE)) == 0) {
2984                 VATTR_NULL(&vattr);
2985                 vattr.va_flags = flags;
2986                 error = VOP_SETATTR(vp, &vattr, td->td_ucred);
2987                 vput(vp);
2988         }
2989         return (error);
2990 }
2991
2992 /*
2993  * chflags(char *path, int flags)
2994  *
2995  * Change flags of a file given a path name.
2996  *
2997  * MPALMOSTSAFE
2998  */
2999 int
3000 sys_chflags(struct chflags_args *uap)
3001 {
3002         struct nlookupdata nd;
3003         struct vnode *vp;
3004         int error;
3005
3006         vp = NULL;
3007         get_mplock();
3008         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3009         if (error == 0)
3010                 error = nlookup(&nd);
3011         if (error == 0)
3012                 error = ncp_writechk(&nd.nl_nch);
3013         if (error == 0)
3014                 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
3015         nlookup_done(&nd);
3016         if (error == 0) {
3017                 error = setfflags(vp, uap->flags);
3018                 vrele(vp);
3019         }
3020         rel_mplock();
3021         return (error);
3022 }
3023
3024 /*
3025  * lchflags(char *path, int flags)
3026  *
3027  * Change flags of a file given a path name, but don't follow symlinks.
3028  *
3029  * MPALMOSTSAFE
3030  */
3031 int
3032 sys_lchflags(struct lchflags_args *uap)
3033 {
3034         struct nlookupdata nd;
3035         struct vnode *vp;
3036         int error;
3037
3038         vp = NULL;
3039         get_mplock();
3040         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3041         if (error == 0)
3042                 error = nlookup(&nd);
3043         if (error == 0)
3044                 error = ncp_writechk(&nd.nl_nch);
3045         if (error == 0)
3046                 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
3047         nlookup_done(&nd);
3048         if (error == 0) {
3049                 error = setfflags(vp, uap->flags);
3050                 vrele(vp);
3051         }
3052         rel_mplock();
3053         return (error);
3054 }
3055
3056 /*
3057  * fchflags_args(int fd, int flags)
3058  *
3059  * Change flags of a file given a file descriptor.
3060  *
3061  * MPALMOSTSAFE
3062  */
3063 int
3064 sys_fchflags(struct fchflags_args *uap)
3065 {
3066         struct thread *td = curthread;
3067         struct proc *p = td->td_proc;
3068         struct file *fp;
3069         int error;
3070
3071         if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
3072                 return (error);
3073         get_mplock();
3074         if (fp->f_nchandle.ncp)
3075                 error = ncp_writechk(&fp->f_nchandle);
3076         if (error == 0)
3077                 error = setfflags((struct vnode *) fp->f_data, uap->flags);
3078         rel_mplock();
3079         fdrop(fp);
3080         return (error);
3081 }
3082
3083 static int
3084 setfmode(struct vnode *vp, int mode)
3085 {
3086         struct thread *td = curthread;
3087         int error;
3088         struct vattr vattr;
3089
3090         /*
3091          * note: vget is required for any operation that might mod the vnode
3092          * so VINACTIVE is properly cleared.
3093          */
3094         if ((error = vget(vp, LK_EXCLUSIVE)) == 0) {
3095                 VATTR_NULL(&vattr);
3096                 vattr.va_mode = mode & ALLPERMS;
3097                 error = VOP_SETATTR(vp, &vattr, td->td_ucred);
3098                 vput(vp);
3099         }
3100         return error;
3101 }
3102
3103 int
3104 kern_chmod(struct nlookupdata *nd, int mode)
3105 {
3106         struct vnode *vp;
3107         int error;
3108
3109         if ((error = nlookup(nd)) != 0)
3110                 return (error);
3111         if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
3112                 return (error);
3113         if ((error = ncp_writechk(&nd->nl_nch)) == 0)
3114                 error = setfmode(vp, mode);
3115         vrele(vp);
3116         return (error);
3117 }
3118
3119 /*
3120  * chmod_args(char *path, int mode)
3121  *
3122  * Change mode of a file given path name.
3123  *
3124  * MPALMOSTSAFE
3125  */
3126 int
3127 sys_chmod(struct chmod_args *uap)
3128 {
3129         struct nlookupdata nd;
3130         int error;
3131
3132         get_mplock();
3133         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3134         if (error == 0)
3135                 error = kern_chmod(&nd, uap->mode);
3136         nlookup_done(&nd);
3137         rel_mplock();
3138         return (error);
3139 }
3140
3141 /*
3142  * lchmod_args(char *path, int mode)
3143  *
3144  * Change mode of a file given path name (don't follow links.)
3145  *
3146  * MPALMOSTSAFE
3147  */
3148 int
3149 sys_lchmod(struct lchmod_args *uap)
3150 {
3151         struct nlookupdata nd;
3152         int error;
3153
3154         get_mplock();
3155         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3156         if (error == 0)
3157                 error = kern_chmod(&nd, uap->mode);
3158         nlookup_done(&nd);
3159         rel_mplock();
3160         return (error);
3161 }
3162
3163 /*
3164  * fchmod_args(int fd, int mode)
3165  *
3166  * Change mode of a file given a file descriptor.
3167  *
3168  * MPALMOSTSAFE
3169  */
3170 int
3171 sys_fchmod(struct fchmod_args *uap)
3172 {
3173         struct thread *td = curthread;
3174         struct proc *p = td->td_proc;
3175         struct file *fp;
3176         int error;
3177
3178         if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
3179                 return (error);
3180         get_mplock();
3181         if (fp->f_nchandle.ncp)
3182                 error = ncp_writechk(&fp->f_nchandle);
3183         if (error == 0)
3184                 error = setfmode((struct vnode *)fp->f_data, uap->mode);
3185         rel_mplock();
3186         fdrop(fp);
3187         return (error);
3188 }
3189
3190 /*
3191  * fchmodat_args(char *path, int mode)
3192  *
3193  * Change mode of a file pointed to by fd/path.
3194  *
3195  * MPALMOSTSAFE
3196  */
3197 int
3198 sys_fchmodat(struct fchmodat_args *uap)
3199 {
3200         struct nlookupdata nd;
3201         struct file *fp;
3202         int error;
3203         int flags;
3204
3205         if (uap->flags & ~AT_SYMLINK_NOFOLLOW)
3206                 return (EINVAL);
3207         flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
3208
3209         get_mplock();
3210         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 
3211                                 UIO_USERSPACE, flags);
3212         if (error == 0)
3213                 error = kern_chmod(&nd, uap->mode);
3214         nlookup_done_at(&nd, fp);
3215         rel_mplock();
3216         return (error);
3217 }
3218
3219 static int
3220 setfown(struct vnode *vp, uid_t uid, gid_t gid)
3221 {
3222         struct thread *td = curthread;
3223         int error;
3224         struct vattr vattr;
3225
3226         /*
3227          * note: vget is required for any operation that might mod the vnode
3228          * so VINACTIVE is properly cleared.
3229          */
3230         if ((error = vget(vp, LK_EXCLUSIVE)) == 0) {
3231                 VATTR_NULL(&vattr);
3232                 vattr.va_uid = uid;
3233                 vattr.va_gid = gid;
3234                 error = VOP_SETATTR(vp, &vattr, td->td_ucred);
3235                 vput(vp);
3236         }
3237         return error;
3238 }
3239
3240 int
3241 kern_chown(struct nlookupdata *nd, int uid, int gid)
3242 {
3243         struct vnode *vp;
3244         int error;
3245
3246         if ((error = nlookup(nd)) != 0)
3247                 return (error);
3248         if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
3249                 return (error);
3250         if ((error = ncp_writechk(&nd->nl_nch)) == 0)
3251                 error = setfown(vp, uid, gid);
3252         vrele(vp);
3253         return (error);
3254 }
3255
3256 /*
3257  * chown(char *path, int uid, int gid)
3258  *
3259  * Set ownership given a path name.
3260  *
3261  * MPALMOSTSAFE
3262  */
3263 int
3264 sys_chown(struct chown_args *uap)
3265 {
3266         struct nlookupdata nd;
3267         int error;
3268
3269         get_mplock();
3270         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3271         if (error == 0)
3272                 error = kern_chown(&nd, uap->uid, uap->gid);
3273         nlookup_done(&nd);
3274         rel_mplock();
3275         return (error);
3276 }
3277
3278 /*
3279  * lchown_args(char *path, int uid, int gid)
3280  *
3281  * Set ownership given a path name, do not cross symlinks.
3282  *
3283  * MPALMOSTSAFE
3284  */
3285 int
3286 sys_lchown(struct lchown_args *uap)
3287 {
3288         struct nlookupdata nd;
3289         int error;
3290
3291         get_mplock();
3292         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3293         if (error == 0)
3294                 error = kern_chown(&nd, uap->uid, uap->gid);
3295         nlookup_done(&nd);
3296         rel_mplock();
3297         return (error);
3298 }
3299
3300 /*
3301  * fchown_args(int fd, int uid, int gid)
3302  *
3303  * Set ownership given a file descriptor.
3304  *
3305  * MPALMOSTSAFE
3306  */
3307 int
3308 sys_fchown(struct fchown_args *uap)
3309 {
3310         struct thread *td = curthread;
3311         struct proc *p = td->td_proc;
3312         struct file *fp;
3313         int error;
3314
3315         if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
3316                 return (error);
3317         get_mplock();
3318         if (fp->f_nchandle.ncp)
3319                 error = ncp_writechk(&fp->f_nchandle);
3320         if (error == 0)
3321                 error = setfown((struct vnode *)fp->f_data, uap->uid, uap->gid);
3322         rel_mplock();
3323         fdrop(fp);
3324         return (error);
3325 }
3326
3327 /*
3328  * fchownat(int fd, char *path, int uid, int gid, int flags)
3329  *
3330  * Set ownership of file pointed to by fd/path.
3331  *
3332  * MPALMOSTSAFE
3333  */
3334 int
3335 sys_fchownat(struct fchownat_args *uap)
3336 {
3337         struct nlookupdata nd;
3338         struct file *fp;
3339         int error;
3340         int flags;
3341
3342         if (uap->flags & ~AT_SYMLINK_NOFOLLOW)
3343                 return (EINVAL);
3344         flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
3345
3346         get_mplock();
3347         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 
3348                                 UIO_USERSPACE, flags);
3349         if (error == 0)
3350                 error = kern_chown(&nd, uap->uid, uap->gid);
3351         nlookup_done_at(&nd, fp);
3352         rel_mplock();
3353         return (error);
3354 }
3355
3356
3357 static int
3358 getutimes(const struct timeval *tvp, struct timespec *tsp)
3359 {
3360         struct timeval tv[2];
3361
3362         if (tvp == NULL) {
3363                 microtime(&tv[0]);
3364                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
3365                 tsp[1] = tsp[0];
3366         } else {
3367                 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
3368                 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
3369         }
3370         return 0;
3371 }
3372
3373 static int
3374 setutimes(struct vnode *vp, struct vattr *vattr,
3375           const struct timespec *ts, int nullflag)
3376 {
3377         struct thread *td = curthread;
3378         int error;
3379
3380         VATTR_NULL(vattr);
3381         vattr->va_atime = ts[0];
3382         vattr->va_mtime = ts[1];
3383         if (nullflag)
3384                 vattr->va_vaflags |= VA_UTIMES_NULL;
3385         error = VOP_SETATTR(vp, vattr, td->td_ucred);
3386
3387         return error;
3388 }
3389
3390 int
3391 kern_utimes(struct nlookupdata *nd, struct timeval *tptr)
3392 {
3393         struct timespec ts[2];
3394         struct vnode *vp;
3395         struct vattr vattr;
3396         int error;
3397
3398         if ((error = getutimes(tptr, ts)) != 0)
3399                 return (error);
3400
3401         /*
3402          * NOTE: utimes() succeeds for the owner even if the file
3403          * is not user-writable.
3404          */
3405         nd->nl_flags |= NLC_OWN | NLC_WRITE;
3406
3407         if ((error = nlookup(nd)) != 0)
3408                 return (error);
3409         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
3410                 return (error);
3411         if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
3412                 return (error);
3413
3414         /*
3415          * note: vget is required for any operation that might mod the vnode
3416          * so VINACTIVE is properly cleared.
3417          */
3418         if ((error = vn_writechk(vp, &nd->nl_nch)) == 0) {
3419                 error = vget(vp, LK_EXCLUSIVE);
3420                 if (error == 0) {
3421                         error = setutimes(vp, &vattr, ts, (tptr == NULL));
3422                         vput(vp);
3423                 }
3424         }
3425         vrele(vp);
3426         return (error);
3427 }
3428
3429 /*
3430  * utimes_args(char *path, struct timeval *tptr)
3431  *
3432  * Set the access and modification times of a file.
3433  *
3434  * MPALMOSTSAFE
3435  */
3436 int
3437 sys_utimes(struct utimes_args *uap)
3438 {
3439         struct timeval tv[2];
3440         struct nlookupdata nd;
3441         int error;
3442
3443         if (uap->tptr) {
3444                 error = copyin(uap->tptr, tv, sizeof(tv));
3445                 if (error)
3446                         return (error);
3447         }
3448         get_mplock();
3449         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3450         if (error == 0)
3451                 error = kern_utimes(&nd, uap->tptr ? tv : NULL);
3452         nlookup_done(&nd);
3453         rel_mplock();
3454         return (error);
3455 }
3456
3457 /*
3458  * lutimes_args(char *path, struct timeval *tptr)
3459  *
3460  * Set the access and modification times of a file.
3461  *
3462  * MPALMOSTSAFE
3463  */
3464 int
3465 sys_lutimes(struct lutimes_args *uap)
3466 {
3467         struct timeval tv[2];
3468         struct nlookupdata nd;
3469         int error;
3470
3471         if (uap->tptr) {
3472                 error = copyin(uap->tptr, tv, sizeof(tv));
3473                 if (error)
3474                         return (error);
3475         }
3476         get_mplock();
3477         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3478         if (error == 0)
3479                 error = kern_utimes(&nd, uap->tptr ? tv : NULL);
3480         nlookup_done(&nd);
3481         rel_mplock();
3482         return (error);
3483 }
3484
3485 /*
3486  * Set utimes on a file descriptor.  The creds used to open the
3487  * file are used to determine whether the operation is allowed
3488  * or not.
3489  */
3490 int
3491 kern_futimes(int fd, struct timeval *tptr)
3492 {
3493         struct thread *td = curthread;
3494         struct proc *p = td->td_proc;
3495         struct timespec ts[2];
3496         struct file *fp;
3497         struct vnode *vp;
3498         struct vattr vattr;
3499         int error;
3500
3501         error = getutimes(tptr, ts);
3502         if (error)
3503                 return (error);
3504         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
3505                 return (error);
3506         if (fp->f_nchandle.ncp)
3507                 error = ncp_writechk(&fp->f_nchandle);
3508         if (error == 0) {
3509                 vp = fp->f_data;
3510                 error = vget(vp, LK_EXCLUSIVE);
3511                 if (error == 0) {
3512                         error = VOP_GETATTR(vp, &vattr);
3513                         if (error == 0) {
3514                                 error = naccess_va(&vattr, NLC_OWN | NLC_WRITE,
3515                                                    fp->f_cred);
3516                         }
3517                         if (error == 0) {
3518                                 error = setutimes(vp, &vattr, ts,
3519                                                   (tptr == NULL));
3520                         }
3521                         vput(vp);
3522                 }
3523         }
3524         fdrop(fp);
3525         return (error);
3526 }
3527
3528 /*
3529  * futimes_args(int fd, struct timeval *tptr)
3530  *
3531  * Set the access and modification times of a file.
3532  *
3533  * MPALMOSTSAFE
3534  */
3535 int
3536 sys_futimes(struct futimes_args *uap)
3537 {
3538         struct timeval tv[2];
3539         int error;
3540
3541         if (uap->tptr) {
3542                 error = copyin(uap->tptr, tv, sizeof(tv));
3543                 if (error)
3544                         return (error);
3545         }
3546         get_mplock();
3547         error = kern_futimes(uap->fd, uap->tptr ? tv : NULL);
3548         rel_mplock();
3549
3550         return (error);
3551 }
3552
3553 int
3554 kern_truncate(struct nlookupdata *nd, off_t length)
3555 {
3556         struct vnode *vp;
3557         struct vattr vattr;
3558         int error;
3559
3560         if (length < 0)
3561                 return(EINVAL);
3562         nd->nl_flags |= NLC_WRITE | NLC_TRUNCATE;
3563         if ((error = nlookup(nd)) != 0)
3564                 return (error);
3565         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
3566                 return (error);
3567         if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
3568                 return (error);
3569         if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) {
3570                 vrele(vp);
3571                 return (error);
3572         }
3573         if (vp->v_type == VDIR) {
3574                 error = EISDIR;
3575         } else if ((error = vn_writechk(vp, &nd->nl_nch)) == 0) {
3576                 VATTR_NULL(&vattr);
3577                 vattr.va_size = length;
3578                 error = VOP_SETATTR(vp, &vattr, nd->nl_cred);
3579         }
3580         vput(vp);
3581         return (error);
3582 }
3583
3584 /*
3585  * truncate(char *path, int pad, off_t length)
3586  *
3587  * Truncate a file given its path name.
3588  *
3589  * MPALMOSTSAFE
3590  */
3591 int
3592 sys_truncate(struct truncate_args *uap)
3593 {
3594         struct nlookupdata nd;
3595         int error;
3596
3597         get_mplock();
3598         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3599         if (error == 0)
3600                 error = kern_truncate(&nd, uap->length);
3601         nlookup_done(&nd);
3602         rel_mplock();
3603         return error;
3604 }
3605
3606 int
3607 kern_ftruncate(int fd, off_t length)
3608 {
3609         struct thread *td = curthread;
3610         struct proc *p = td->td_proc;
3611         struct vattr vattr;
3612         struct vnode *vp;
3613         struct file *fp;
3614         int error;
3615
3616         if (length < 0)
3617                 return(EINVAL);
3618         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
3619                 return (error);
3620         if (fp->f_nchandle.ncp) {
3621                 error = ncp_writechk(&fp->f_nchandle);
3622                 if (error)
3623                         goto done;
3624         }
3625         if ((fp->f_flag & FWRITE) == 0) {
3626                 error = EINVAL;
3627                 goto done;
3628         }
3629         if (fp->f_flag & FAPPENDONLY) { /* inode was set s/uapnd */
3630                 error = EINVAL;
3631                 goto done;
3632         }
3633         vp = (struct vnode *)fp->f_data;
3634         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3635         if (vp->v_type == VDIR) {
3636                 error = EISDIR;
3637         } else if ((error = vn_writechk(vp, NULL)) == 0) {
3638                 VATTR_NULL(&vattr);
3639                 vattr.va_size = length;
3640                 error = VOP_SETATTR(vp, &vattr, fp->f_cred);
3641         }
3642         vn_unlock(vp);
3643 done:
3644         fdrop(fp);
3645         return (error);
3646 }
3647
3648 /*
3649  * ftruncate_args(int fd, int pad, off_t length)
3650  *
3651  * Truncate a file given a file descriptor.
3652  *
3653  * MPALMOSTSAFE
3654  */
3655 int
3656 sys_ftruncate(struct ftruncate_args *uap)
3657 {
3658         int error;
3659
3660         get_mplock();
3661         error = kern_ftruncate(uap->fd, uap->length);
3662         rel_mplock();
3663
3664         return (error);
3665 }
3666
3667 /*
3668  * fsync(int fd)
3669  *
3670  * Sync an open file.
3671  *
3672  * MPALMOSTSAFE
3673  */
3674 int
3675 sys_fsync(struct fsync_args *uap)
3676 {
3677         struct thread *td = curthread;
3678         struct proc *p = td->td_proc;
3679         struct vnode *vp;
3680         struct file *fp;
3681         vm_object_t obj;
3682         int error;
3683
3684         if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
3685                 return (error);
3686         get_mplock();
3687         vp = (struct vnode *)fp->f_data;
3688         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3689         if ((obj = vp->v_object) != NULL)
3690                 vm_object_page_clean(obj, 0, 0, 0);
3691         error = VOP_FSYNC(vp, MNT_WAIT, VOP_FSYNC_SYSCALL);
3692         if (error == 0 && vp->v_mount)
3693                 error = buf_fsync(vp);
3694         vn_unlock(vp);
3695         rel_mplock();
3696         fdrop(fp);
3697
3698         return (error);
3699 }
3700
3701 int
3702 kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond)
3703 {
3704         struct nchandle fnchd;
3705         struct nchandle tnchd;
3706         struct namecache *ncp;
3707         struct vnode *fdvp;
3708         struct vnode *tdvp;
3709         struct mount *mp;
3710         int error;
3711
3712         bwillinode(1);
3713         fromnd->nl_flags |= NLC_REFDVP | NLC_RENAME_SRC;
3714         if ((error = nlookup(fromnd)) != 0)
3715                 return (error);
3716         if ((fnchd.ncp = fromnd->nl_nch.ncp->nc_parent) == NULL)
3717                 return (ENOENT);
3718         fnchd.mount = fromnd->nl_nch.mount;
3719         cache_hold(&fnchd);
3720
3721         /*
3722          * unlock the source nch so we can lookup the target nch without
3723          * deadlocking.  The target may or may not exist so we do not check
3724          * for a target vp like kern_mkdir() and other creation functions do.
3725          *
3726          * The source and target directories are ref'd and rechecked after
3727          * everything is relocked to determine if the source or target file
3728          * has been renamed.
3729          */
3730         KKASSERT(fromnd->nl_flags & NLC_NCPISLOCKED);
3731         fromnd->nl_flags &= ~NLC_NCPISLOCKED;
3732         cache_unlock(&fromnd->nl_nch);
3733
3734         tond->nl_flags |= NLC_RENAME_DST | NLC_REFDVP;
3735         if ((error = nlookup(tond)) != 0) {
3736                 cache_drop(&fnchd);
3737                 return (error);
3738         }
3739         if ((tnchd.ncp = tond->nl_nch.ncp->nc_parent) == NULL) {
3740                 cache_drop(&fnchd);
3741                 return (ENOENT);
3742         }
3743         tnchd.mount = tond->nl_nch.mount;
3744         cache_hold(&tnchd);
3745
3746         /*
3747          * If the source and target are the same there is nothing to do
3748          */
3749         if (fromnd->nl_nch.ncp == tond->nl_nch.ncp) {
3750                 cache_drop(&fnchd);
3751                 cache_drop(&tnchd);
3752                 return (0);
3753         }
3754
3755         /*
3756          * Mount points cannot be renamed or overwritten
3757          */
3758         if ((fromnd->nl_nch.ncp->nc_flag | tond->nl_nch.ncp->nc_flag) &
3759             NCF_ISMOUNTPT
3760         ) {
3761                 cache_drop(&fnchd);
3762                 cache_drop(&tnchd);
3763                 return (EINVAL);
3764         }
3765
3766         /*
3767          * Relock the source ncp.  cache_relock() will deal with any
3768          * deadlocks against the already-locked tond and will also
3769          * make sure both are resolved.
3770          *
3771          * NOTE AFTER RELOCKING: The source or target ncp may have become
3772          * invalid while they were unlocked, nc_vp and nc_mount could
3773          * be NULL.
3774          */
3775         cache_relock(&fromnd->nl_nch, fromnd->nl_cred,
3776                      &tond->nl_nch, tond->nl_cred);
3777         fromnd->nl_flags |= NLC_NCPISLOCKED;
3778
3779         /*
3780          * make sure the parent directories linkages are the same
3781          */
3782         if (fnchd.ncp != fromnd->nl_nch.ncp->nc_parent ||
3783             tnchd.ncp != tond->nl_nch.ncp->nc_parent) {
3784                 cache_drop(&fnchd);
3785                 cache_drop(&tnchd);
3786                 return (ENOENT);
3787         }
3788
3789         /*
3790          * Both the source and target must be within the same filesystem and
3791          * in the same filesystem as their parent directories within the
3792          * namecache topology.
3793          *
3794          * NOTE: fromnd's nc_mount or nc_vp could be NULL.
3795          */
3796         mp = fnchd.mount;
3797         if (mp != tnchd.mount || mp != fromnd->nl_nch.mount ||
3798             mp != tond->nl_nch.mount) {
3799                 cache_drop(&fnchd);
3800                 cache_drop(&tnchd);
3801                 return (EXDEV);
3802         }
3803
3804         /*
3805          * Make sure the mount point is writable
3806          */
3807         if ((error = ncp_writechk(&tond->nl_nch)) != 0) {
3808                 cache_drop(&fnchd);
3809                 cache_drop(&tnchd);
3810                 return (error);
3811         }
3812
3813         /*
3814          * If the target exists and either the source or target is a directory,
3815          * then both must be directories.
3816          *
3817          * Due to relocking of the source, fromnd->nl_nch.ncp->nc_vp might h
3818          * have become NULL.
3819          */
3820         if (tond->nl_nch.ncp->nc_vp) {
3821                 if (fromnd->nl_nch.ncp->nc_vp == NULL) {
3822                         error = ENOENT;
3823                 } else if (fromnd->nl_nch.ncp->nc_vp->v_type == VDIR) {
3824                         if (tond->nl_nch.ncp->nc_vp->v_type != VDIR)
3825                                 error = ENOTDIR;
3826                 } else if (tond->nl_nch.ncp->nc_vp->v_type == VDIR) {
3827                         error = EISDIR;
3828                 }
3829         }
3830
3831         /*
3832          * You cannot rename a source into itself or a subdirectory of itself.
3833          * We check this by travsersing the target directory upwards looking
3834          * for a match against the source.
3835          *
3836          * XXX MPSAFE
3837          */
3838         if (error == 0) {
3839                 for (ncp = tnchd.ncp; ncp; ncp = ncp->nc_parent) {
3840                         if (fromnd->nl_nch.ncp == ncp) {
3841                                 error = EINVAL;
3842                                 break;
3843                         }
3844                 }
3845         }
3846
3847         cache_drop(&fnchd);
3848         cache_drop(&tnchd);
3849
3850         /*
3851          * Even though the namespaces are different, they may still represent
3852          * hardlinks to the same file.  The filesystem might have a hard time
3853          * with this so we issue a NREMOVE of the source instead of a NRENAME
3854          * when we detect the situation.
3855          */
3856         if (error == 0) {
3857                 fdvp = fromnd->nl_dvp;
3858                 tdvp = tond->nl_dvp;
3859                 if (fdvp == NULL || tdvp == NULL) {
3860                         error = EPERM;
3861                 } else if (fromnd->nl_nch.ncp->nc_vp == tond->nl_nch.ncp->nc_vp) {
3862                         error = VOP_NREMOVE(&fromnd->nl_nch, fdvp,
3863                                             fromnd->nl_cred);
3864                 } else {
3865                         error = VOP_NRENAME(&fromnd->nl_nch, &tond->nl_nch, 
3866                                             fdvp, tdvp, tond->nl_cred);
3867                 }
3868         }
3869         return (error);
3870 }
3871
3872 /*
3873  * rename_args(char *from, char *to)
3874  *
3875  * Rename files.  Source and destination must either both be directories,
3876  * or both not be directories.  If target is a directory, it must be empty.
3877  *
3878  * MPALMOSTSAFE
3879  */
3880 int
3881 sys_rename(struct rename_args *uap)
3882 {
3883         struct nlookupdata fromnd, tond;
3884         int error;
3885
3886         get_mplock();
3887         error = nlookup_init(&fromnd, uap->from, UIO_USERSPACE, 0);
3888         if (error == 0) {
3889                 error = nlookup_init(&tond, uap->to, UIO_USERSPACE, 0);
3890                 if (error == 0)
3891                         error = kern_rename(&fromnd, &tond);
3892                 nlookup_done(&tond);
3893         }
3894         nlookup_done(&fromnd);
3895         rel_mplock();
3896         return (error);
3897 }
3898
3899 /*
3900  * renameat_args(int oldfd, char *old, int newfd, char *new)
3901  *
3902  * Rename files using paths relative to the directories associated with
3903  * oldfd and newfd.  Source and destination must either both be directories,
3904  * or both not be directories.  If target is a directory, it must be empty.
3905  *
3906  * MPALMOSTSAFE
3907  */
3908 int
3909 sys_renameat(struct renameat_args *uap)
3910 {
3911         struct nlookupdata oldnd, newnd;
3912         struct file *oldfp, *newfp;
3913         int error;
3914
3915         get_mplock();
3916         error = nlookup_init_at(&oldnd, &oldfp, uap->oldfd, uap->old,
3917             UIO_USERSPACE, 0);
3918         if (error == 0) {
3919                 error = nlookup_init_at(&newnd, &newfp, uap->newfd, uap->new,
3920                     UIO_USERSPACE, 0);
3921                 if (error == 0)
3922                         error = kern_rename(&oldnd, &newnd);
3923                 nlookup_done_at(&newnd, newfp);
3924         }
3925         nlookup_done_at(&oldnd, oldfp);
3926         rel_mplock();
3927         return (error);
3928 }
3929
3930 int
3931 kern_mkdir(struct nlookupdata *nd, int mode)
3932 {
3933         struct thread *td = curthread;
3934         struct proc *p = td->td_proc;
3935         struct vnode *vp;
3936         struct vattr vattr;
3937         int error;
3938
3939         bwillinode(1);
3940         nd->nl_flags |= NLC_WILLBEDIR | NLC_CREATE | NLC_REFDVP;
3941         if ((error = nlookup(nd)) != 0)
3942                 return (error);
3943
3944         if (nd->nl_nch.ncp->nc_vp)
3945                 return (EEXIST);
3946         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
3947                 return (error);
3948         VATTR_NULL(&vattr);
3949         vattr.va_type = VDIR;
3950         vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
3951
3952         vp = NULL;
3953         error = VOP_NMKDIR(&nd->nl_nch, nd->nl_dvp, &vp, td->td_ucred, &vattr);
3954         if (error == 0)
3955                 vput(vp);
3956         return (error);
3957 }
3958
3959 /*
3960  * mkdir_args(char *path, int mode)
3961  *
3962  * Make a directory file.
3963  *
3964  * MPALMOSTSAFE
3965  */
3966 int
3967 sys_mkdir(struct mkdir_args *uap)
3968 {
3969         struct nlookupdata nd;
3970         int error;
3971
3972         get_mplock();
3973         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3974         if (error == 0)
3975                 error = kern_mkdir(&nd, uap->mode);
3976         nlookup_done(&nd);
3977         rel_mplock();
3978         return (error);
3979 }
3980
3981 /*
3982  * mkdirat_args(int fd, char *path, mode_t mode)
3983  *
3984  * Make a directory file.  The path is relative to the directory associated
3985  * with fd.
3986  *
3987  * MPALMOSTSAFE
3988  */
3989 int
3990 sys_mkdirat(struct mkdirat_args *uap)
3991 {
3992         struct nlookupdata nd;
3993         struct file *fp;
3994         int error;
3995
3996         get_mplock();
3997         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
3998         if (error == 0)
3999                 error = kern_mkdir(&nd, uap->mode);
4000         nlookup_done_at(&nd, fp);
4001         rel_mplock();
4002         return (error);
4003 }
4004
4005 int
4006 kern_rmdir(struct nlookupdata *nd)
4007 {
4008         int error;
4009
4010         bwillinode(1);
4011         nd->nl_flags |= NLC_DELETE | NLC_REFDVP;
4012         if ((error = nlookup(nd)) != 0)
4013                 return (error);
4014
4015         /*
4016          * Do not allow directories representing mount points to be
4017          * deleted, even if empty.  Check write perms on mount point
4018          * in case the vnode is aliased (aka nullfs).
4019          */
4020         if (nd->nl_nch.ncp->nc_flag & (NCF_ISMOUNTPT))
4021                 return (EINVAL);
4022         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
4023                 return (error);
4024         error = VOP_NRMDIR(&nd->nl_nch, nd->nl_dvp, nd->nl_cred);
4025         return (error);
4026 }
4027
4028 /*
4029  * rmdir_args(char *path)
4030  *
4031  * Remove a directory file.
4032  *
4033  * MPALMOSTSAFE
4034  */
4035 int
4036 sys_rmdir(struct rmdir_args *uap)
4037 {
4038         struct nlookupdata nd;
4039         int error;
4040
4041         get_mplock();
4042         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
4043         if (error == 0)
4044                 error = kern_rmdir(&nd);
4045         nlookup_done(&nd);
4046         rel_mplock();
4047         return (error);
4048 }
4049
4050 int
4051 kern_getdirentries(int fd, char *buf, u_int count, long *basep, int *res,
4052     enum uio_seg direction)
4053 {
4054         struct thread *td = curthread;
4055         struct proc *p = td->td_proc;
4056         struct vnode *vp;
4057         struct file *fp;
4058         struct uio auio;
4059         struct iovec aiov;
4060         off_t loff;
4061         int error, eofflag;
4062
4063         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
4064                 return (error);
4065         if ((fp->f_flag & FREAD) == 0) {
4066                 error = EBADF;
4067                 goto done;
4068         }
4069         vp = (struct vnode *)fp->f_data;
4070 unionread:
4071         if (vp->v_type != VDIR) {
4072                 error = EINVAL;
4073                 goto done;
4074         }
4075         aiov.iov_base = buf;
4076         aiov.iov_len = count;
4077         auio.uio_iov = &aiov;
4078         auio.uio_iovcnt = 1;
4079         auio.uio_rw = UIO_READ;
4080         auio.uio_segflg = direction;
4081         auio.uio_td = td;
4082         auio.uio_resid = count;
4083         loff = auio.uio_offset = fp->f_offset;
4084         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
4085         fp->f_offset = auio.uio_offset;
4086         if (error)
4087                 goto done;
4088         if (count == auio.uio_resid) {
4089                 if (union_dircheckp) {
4090                         error = union_dircheckp(td, &vp, fp);
4091                         if (error == -1)
4092                                 goto unionread;
4093                         if (error)
4094                                 goto done;
4095                 }
4096 #if 0
4097                 if ((vp->v_flag & VROOT) &&
4098                     (vp->v_mount->mnt_flag & MNT_UNION)) {
4099                         struct vnode *tvp = vp;
4100                         vp = vp->v_mount->mnt_vnodecovered;
4101                         vref(vp);
4102                         fp->f_data = vp;
4103                         fp->f_offset = 0;
4104                         vrele(tvp);
4105                         goto unionread;
4106                 }
4107 #endif
4108         }
4109
4110         /*
4111          * WARNING!  *basep may not be wide enough to accomodate the
4112          * seek offset.   XXX should we hack this to return the upper 32 bits
4113          * for offsets greater then 4G?
4114          */
4115         if (basep) {
4116                 *basep = (long)loff;
4117         }
4118         *res = count - auio.uio_resid;
4119 done:
4120         fdrop(fp);
4121         return (error);
4122 }
4123
4124 /*
4125  * getdirentries_args(int fd, char *buf, u_int conut, long *basep)
4126  *
4127  * Read a block of directory entries in a file system independent format.
4128  *
4129  * MPALMOSTSAFE
4130  */
4131 int
4132 sys_getdirentries(struct getdirentries_args *uap)
4133 {
4134         long base;
4135         int error;
4136
4137         get_mplock();
4138         error = kern_getdirentries(uap->fd, uap->buf, uap->count, &base,
4139                                    &uap->sysmsg_result, UIO_USERSPACE);
4140         rel_mplock();
4141
4142         if (error == 0 && uap->basep)
4143                 error = copyout(&base, uap->basep, sizeof(*uap->basep));
4144         return (error);
4145 }
4146
4147 /*
4148  * getdents_args(int fd, char *buf, size_t count)
4149  *
4150  * MPALMOSTSAFE
4151  */
4152 int
4153 sys_getdents(struct getdents_args *uap)
4154 {
4155         int error;
4156
4157         get_mplock();
4158         error = kern_getdirentries(uap->fd, uap->buf, uap->count, NULL,
4159                                    &uap->sysmsg_result, UIO_USERSPACE);
4160         rel_mplock();
4161
4162         return (error);
4163 }
4164
4165 /*
4166  * Set the mode mask for creation of filesystem nodes.
4167  *
4168  * umask(int newmask)
4169  *
4170  * MPSAFE
4171  */
4172 int
4173 sys_umask(struct umask_args *uap)
4174 {
4175         struct thread *td = curthread;
4176         struct proc *p = td->td_proc;
4177         struct filedesc *fdp;
4178
4179         fdp = p->p_fd;
4180         uap->sysmsg_result = fdp->fd_cmask;
4181         fdp->fd_cmask = uap->newmask & ALLPERMS;
4182         return (0);
4183 }
4184
4185 /*
4186  * revoke(char *path)
4187  *
4188  * Void all references to file by ripping underlying filesystem
4189  * away from vnode.
4190  *
4191  * MPALMOSTSAFE
4192  */
4193 int
4194 sys_revoke(struct revoke_args *uap)
4195 {
4196         struct nlookupdata nd;
4197         struct vattr vattr;
4198         struct vnode *vp;
4199         struct ucred *cred;
4200         int error;
4201
4202         vp = NULL;
4203         get_mplock();
4204         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4205         if (error == 0)
4206                 error = nlookup(&nd);
4207         if (error == 0)
4208                 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
4209         cred = crhold(nd.nl_cred);
4210         nlookup_done(&nd);
4211         if (error == 0) {
4212                 if (error == 0)
4213                         error = VOP_GETATTR(vp, &vattr);
4214                 if (error == 0 && cred->cr_uid != vattr.va_uid)
4215                         error = priv_check_cred(cred, PRIV_VFS_REVOKE, 0);
4216                 if (error == 0 && (vp->v_type == VCHR || vp->v_type == VBLK)) {
4217                         if (vcount(vp) > 0)
4218                                 error = vrevoke(vp, cred);
4219                 } else if (error == 0) {
4220                         error = vrevoke(vp, cred);
4221                 }
4222                 vrele(vp);
4223         }
4224         if (cred)
4225                 crfree(cred);
4226         rel_mplock();
4227         return (error);
4228 }
4229
4230 /*
4231  * getfh_args(char *fname, fhandle_t *fhp)
4232  *
4233  * Get (NFS) file handle
4234  *
4235  * NOTE: We use the fsid of the covering mount, even if it is a nullfs
4236  * mount.  This allows nullfs mounts to be explicitly exported. 
4237  *
4238  * WARNING: nullfs mounts of HAMMER PFS ROOTs are safe.
4239  *
4240  *          nullfs mounts of subdirectories are not safe.  That is, it will
4241  *          work, but you do not really have protection against access to
4242  *          the related parent directories.
4243  *
4244  * MPALMOSTSAFE
4245  */
4246 int
4247 sys_getfh(struct getfh_args *uap)
4248 {
4249         struct thread *td = curthread;
4250         struct nlookupdata nd;
4251         fhandle_t fh;
4252         struct vnode *vp;
4253         struct mount *mp;
4254         int error;
4255
4256         /*
4257          * Must be super user
4258          */
4259         if ((error = priv_check(td, PRIV_ROOT)) != 0)
4260                 return (error);
4261
4262         vp = NULL;
4263         get_mplock();
4264         error = nlookup_init(&nd, uap->fname, UIO_USERSPACE, NLC_FOLLOW);
4265         if (error == 0)
4266                 error = nlookup(&nd);
4267         if (error == 0)
4268                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
4269         mp = nd.nl_nch.mount;
4270         nlookup_done(&nd);
4271         if (error == 0) {
4272                 bzero(&fh, sizeof(fh));
4273                 fh.fh_fsid = mp->mnt_stat.f_fsid;
4274                 error = VFS_VPTOFH(vp, &fh.fh_fid);
4275                 vput(vp);
4276                 if (error == 0)
4277                         error = copyout(&fh, uap->fhp, sizeof(fh));
4278         }
4279         rel_mplock();
4280         return (error);
4281 }
4282
4283 /*
4284  * fhopen_args(const struct fhandle *u_fhp, int flags)
4285  *
4286  * syscall for the rpc.lockd to use to translate a NFS file handle into
4287  * an open descriptor.
4288  *
4289  * warning: do not remove the priv_check() call or this becomes one giant
4290  * security hole.
4291  *
4292  * MPALMOSTSAFE
4293  */
4294 int
4295 sys_fhopen(struct fhopen_args *uap)
4296 {
4297         struct thread *td = curthread;
4298         struct filedesc *fdp = td->td_proc->p_fd;
4299         struct mount *mp;
4300         struct vnode *vp;
4301         struct fhandle fhp;
4302         struct vattr vat;
4303         struct vattr *vap = &vat;
4304         struct flock lf;
4305         int fmode, mode, error, type;
4306         struct file *nfp; 
4307         struct file *fp;
4308         int indx;
4309
4310         /*
4311          * Must be super user
4312          */
4313         error = priv_check(td, PRIV_ROOT);
4314         if (error)
4315                 return (error);
4316
4317         fmode = FFLAGS(uap->flags);
4318
4319         /*
4320          * Why not allow a non-read/write open for our lockd?
4321          */
4322         if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
4323                 return (EINVAL);
4324         error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
4325         if (error)
4326                 return(error);
4327
4328         /*
4329          * Find the mount point
4330          */
4331         get_mplock();
4332         mp = vfs_getvfs(&fhp.fh_fsid);
4333         if (mp == NULL) {
4334                 error = ESTALE;
4335                 goto  done;
4336         }
4337         /* now give me my vnode, it gets returned to me locked */
4338         error = VFS_FHTOVP(mp, NULL, &fhp.fh_fid, &vp);
4339         if (error)
4340                 goto done;
4341         /*
4342          * from now on we have to make sure not
4343          * to forget about the vnode
4344          * any error that causes an abort must vput(vp) 
4345          * just set error = err and 'goto bad;'.
4346          */
4347
4348         /* 
4349          * from vn_open 
4350          */
4351         if (vp->v_type == VLNK) {
4352                 error = EMLINK;
4353                 goto bad;
4354         }
4355         if (vp->v_type == VSOCK) {
4356                 error = EOPNOTSUPP;
4357                 goto bad;
4358         }
4359         mode = 0;
4360         if (fmode & (FWRITE | O_TRUNC)) {
4361                 if (vp->v_type == VDIR) {
4362                         error = EISDIR;
4363                         goto bad;
4364                 }
4365                 error = vn_writechk(vp, NULL);
4366                 if (error)
4367                         goto bad;
4368                 mode |= VWRITE;
4369         }
4370         if (fmode & FREAD)
4371                 mode |= VREAD;
4372         if (mode) {
4373                 error = VOP_ACCESS(vp, mode, td->td_ucred);
4374                 if (error)
4375                         goto bad;
4376         }
4377         if (fmode & O_TRUNC) {
4378                 vn_unlock(vp);                          /* XXX */
4379                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);   /* XXX */
4380                 VATTR_NULL(vap);
4381                 vap->va_size = 0;
4382                 error = VOP_SETATTR(vp, vap, td->td_ucred);
4383                 if (error)
4384                         goto bad;
4385         }
4386
4387         /*
4388          * VOP_OPEN needs the file pointer so it can potentially override
4389          * it.
4390          *
4391          * WARNING! no f_nchandle will be associated when fhopen()ing a
4392          * directory.  XXX
4393          */
4394         if ((error = falloc(td->td_lwp, &nfp, &indx)) != 0)
4395                 goto bad;
4396         fp = nfp;
4397
4398         error = VOP_OPEN(vp, fmode, td->td_ucred, fp);
4399         if (error) {
4400                 /*
4401                  * setting f_ops this way prevents VOP_CLOSE from being
4402                  * called or fdrop() releasing the vp from v_data.   Since
4403                  * the VOP_OPEN failed we don't want to VOP_CLOSE.
4404                  */
4405                 fp->f_ops = &badfileops;
4406                 fp->f_data = NULL;
4407                 goto bad_drop;
4408         }
4409
4410         /*
4411          * The fp is given its own reference, we still have our ref and lock.
4412          *
4413          * Assert that all regular files must be created with a VM object.
4414          */
4415         if (vp->v_type == VREG && vp->v_object == NULL) {
4416                 kprintf("fhopen: regular file did not have VM object: %p\n", vp);
4417                 goto bad_drop;
4418         }
4419
4420         /*
4421          * The open was successful.  Handle any locking requirements.
4422          */
4423         if (fmode & (O_EXLOCK | O_SHLOCK)) {
4424                 lf.l_whence = SEEK_SET;
4425                 lf.l_start = 0;
4426                 lf.l_len = 0;
4427                 if (fmode & O_EXLOCK)
4428                         lf.l_type = F_WRLCK;
4429                 else
4430                         lf.l_type = F_RDLCK;
4431                 if (fmode & FNONBLOCK)
4432                         type = 0;
4433                 else
4434                         type = F_WAIT;
4435                 vn_unlock(vp);
4436                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
4437                         /*
4438                          * release our private reference.
4439                          */
4440                         fsetfd(fdp, NULL, indx);
4441                         fdrop(fp);
4442                         vrele(vp);
4443                         goto done;
4444                 }
4445                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
4446                 fp->f_flag |= FHASLOCK;
4447         }
4448
4449         /*
4450          * Clean up.  Associate the file pointer with the previously
4451          * reserved descriptor and return it.
4452          */
4453         vput(vp);
4454         rel_mplock();
4455         fsetfd(fdp, fp, indx);
4456         fdrop(fp);
4457         uap->sysmsg_result = indx;
4458         return (0);
4459
4460 bad_drop:
4461         fsetfd(fdp, NULL, indx);
4462         fdrop(fp);
4463 bad:
4464         vput(vp);
4465 done:
4466         rel_mplock();
4467         return (error);
4468 }
4469
4470 /*
4471  * fhstat_args(struct fhandle *u_fhp, struct stat *sb)
4472  *
4473  * MPALMOSTSAFE
4474  */
4475 int
4476 sys_fhstat(struct fhstat_args *uap)
4477 {
4478         struct thread *td = curthread;
4479         struct stat sb;
4480         fhandle_t fh;
4481         struct mount *mp;
4482         struct vnode *vp;
4483         int error;
4484
4485         /*
4486          * Must be super user
4487          */
4488         error = priv_check(td, PRIV_ROOT);
4489         if (error)
4490                 return (error);
4491         
4492         error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4493         if (error)
4494                 return (error);
4495
4496         get_mplock();
4497         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
4498                 error = ESTALE;
4499         if (error == 0) {
4500                 if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp)) == 0) {
4501                         error = vn_stat(vp, &sb, td->td_ucred);
4502                         vput(vp);
4503                 }
4504         }
4505         rel_mplock();
4506         if (error == 0)
4507                 error = copyout(&sb, uap->sb, sizeof(sb));
4508         return (error);
4509 }
4510
4511 /*
4512  * fhstatfs_args(struct fhandle *u_fhp, struct statfs *buf)
4513  *
4514  * MPALMOSTSAFE
4515  */
4516 int
4517 sys_fhstatfs(struct fhstatfs_args *uap)
4518 {
4519         struct thread *td = curthread;
4520         struct proc *p = td->td_proc;
4521         struct statfs *sp;
4522         struct mount *mp;
4523         struct vnode *vp;
4524         struct statfs sb;
4525         char *fullpath, *freepath;
4526         fhandle_t fh;
4527         int error;
4528
4529         /*
4530          * Must be super user
4531          */
4532         if ((error = priv_check(td, PRIV_ROOT)))
4533                 return (error);
4534
4535         if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
4536                 return (error);
4537
4538         get_mplock();
4539
4540         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
4541                 error = ESTALE;
4542                 goto done;
4543         }
4544         if (p != NULL && !chroot_visible_mnt(mp, p)) {
4545                 error = ESTALE;
4546                 goto done;
4547         }
4548
4549         if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp)) != 0)
4550                 goto done;
4551         mp = vp->v_mount;
4552         sp = &mp->mnt_stat;
4553         vput(vp);
4554         if ((error = VFS_STATFS(mp, sp, td->td_ucred)) != 0)
4555                 goto done;
4556
4557         error = mount_path(p, mp, &fullpath, &freepath);
4558         if (error)
4559                 goto done;
4560         bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
4561         strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
4562         kfree(freepath, M_TEMP);
4563
4564         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
4565         if (priv_check(td, PRIV_ROOT)) {
4566                 bcopy(sp, &sb, sizeof(sb));
4567                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
4568                 sp = &sb;
4569         }
4570         error = copyout(sp, uap->buf, sizeof(*sp));
4571 done:
4572         rel_mplock();
4573         return (error);
4574 }
4575
4576 /*
4577  * fhstatvfs_args(struct fhandle *u_fhp, struct statvfs *buf)
4578  *
4579  * MPALMOSTSAFE
4580  */
4581 int
4582 sys_fhstatvfs(struct fhstatvfs_args *uap)
4583 {
4584         struct thread *td = curthread;
4585         struct proc *p = td->td_proc;
4586         struct statvfs *sp;
4587         struct mount *mp;
4588         struct vnode *vp;
4589         fhandle_t fh;
4590         int error;
4591
4592         /*
4593          * Must be super user
4594          */
4595         if ((error = priv_check(td, PRIV_ROOT)))
4596                 return (error);
4597
4598         if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
4599                 return (error);
4600
4601         get_mplock();
4602
4603         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
4604                 error = ESTALE;
4605                 goto done;
4606         }
4607         if (p != NULL && !chroot_visible_mnt(mp, p)) {
4608                 error = ESTALE;
4609                 goto done;
4610         }
4611
4612         if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp)))
4613                 goto done;
4614         mp = vp->v_mount;
4615         sp = &mp->mnt_vstat;
4616         vput(vp);
4617         if ((error = VFS_STATVFS(mp, sp, td->td_ucred)) != 0)
4618                 goto done;
4619
4620         sp->f_flag = 0;
4621         if (mp->mnt_flag & MNT_RDONLY)
4622                 sp->f_flag |= ST_RDONLY;
4623         if (mp->mnt_flag & MNT_NOSUID)
4624                 sp->f_flag |= ST_NOSUID;
4625         error = copyout(sp, uap->buf, sizeof(*sp));
4626 done:
4627         rel_mplock();
4628         return (error);
4629 }
4630
4631
4632 /*
4633  * Syscall to push extended attribute configuration information into the
4634  * VFS.  Accepts a path, which it converts to a mountpoint, as well as
4635  * a command (int cmd), and attribute name and misc data.  For now, the
4636  * attribute name is left in userspace for consumption by the VFS_op.
4637  * It will probably be changed to be copied into sysspace by the
4638  * syscall in the future, once issues with various consumers of the
4639  * attribute code have raised their hands.
4640  *
4641  * Currently this is used only by UFS Extended Attributes.
4642  *
4643  * MPALMOSTSAFE
4644  */
4645 int
4646 sys_extattrctl(struct extattrctl_args *uap)
4647 {
4648         struct nlookupdata nd;
4649         struct vnode *vp;
4650         char attrname[EXTATTR_MAXNAMELEN];
4651         int error;
4652         size_t size;
4653
4654         get_mplock();
4655
4656         attrname[0] = 0;
4657         vp = NULL;
4658         error = 0;
4659
4660         if (error == 0 && uap->filename) {
4661                 error = nlookup_init(&nd, uap->filename, UIO_USERSPACE,
4662                                      NLC_FOLLOW);
4663                 if (error == 0)
4664                         error = nlookup(&nd);
4665                 if (error == 0)
4666                         error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
4667                 nlookup_done(&nd);
4668         }
4669
4670         if (error == 0 && uap->attrname) {
4671                 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
4672                                   &size);
4673         }
4674
4675         if (error == 0) {
4676                 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4677                 if (error == 0)
4678                         error = nlookup(&nd);
4679                 if (error == 0)
4680                         error = ncp_writechk(&nd.nl_nch);
4681                 if (error == 0) {
4682                         error = VFS_EXTATTRCTL(nd.nl_nch.mount, uap->cmd, vp,
4683                                                uap->attrnamespace,
4684                                                uap->attrname, nd.nl_cred);
4685                 }
4686                 nlookup_done(&nd);
4687         }
4688
4689         rel_mplock();
4690
4691         return (error);
4692 }
4693
4694 /*
4695  * Syscall to get a named extended attribute on a file or directory.
4696  *
4697  * MPALMOSTSAFE
4698  */
4699 int
4700 sys_extattr_set_file(struct extattr_set_file_args *uap)
4701 {
4702         char attrname[EXTATTR_MAXNAMELEN];
4703         struct nlookupdata nd;
4704         struct vnode *vp;
4705         struct uio auio;
4706         struct iovec aiov;
4707         int error;
4708
4709         error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN);
4710         if (error)
4711                 return (error);
4712
4713         vp = NULL;
4714         get_mplock();
4715
4716         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4717         if (error == 0)
4718                 error = nlookup(&nd);
4719         if (error == 0)
4720                 error = ncp_writechk(&nd.nl_nch);
4721         if (error == 0)
4722                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
4723         if (error) {
4724                 nlookup_done(&nd);
4725                 rel_mplock();
4726                 return (error);
4727         }
4728
4729         bzero(&auio, sizeof(auio));
4730         aiov.iov_base = uap->data;
4731         aiov.iov_len = uap->nbytes;
4732         auio.uio_iov = &aiov;
4733         auio.uio_iovcnt = 1;
4734         auio.uio_offset = 0;
4735         auio.uio_resid = uap->nbytes;
4736         auio.uio_rw = UIO_WRITE;
4737         auio.uio_td = curthread;
4738
4739         error = VOP_SETEXTATTR(vp, uap->attrnamespace, attrname,
4740                                &auio, nd.nl_cred);
4741
4742         vput(vp);
4743         nlookup_done(&nd);
4744         rel_mplock();
4745         return (error);
4746 }
4747
4748 /*
4749  * Syscall to get a named extended attribute on a file or directory.
4750  *
4751  * MPALMOSTSAFE
4752  */
4753 int
4754 sys_extattr_get_file(struct extattr_get_file_args *uap)
4755 {
4756         char attrname[EXTATTR_MAXNAMELEN];
4757         struct nlookupdata nd;
4758         struct uio auio;
4759         struct iovec aiov;
4760         struct vnode *vp;
4761         int error;
4762
4763         error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN);
4764         if (error)
4765                 return (error);
4766
4767         vp = NULL;
4768         get_mplock();
4769
4770         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4771         if (error == 0)
4772                 error = nlookup(&nd);
4773         if (error == 0)
4774                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
4775         if (error) {
4776                 nlookup_done(&nd);
4777                 rel_mplock();
4778                 return (error);
4779         }
4780
4781         bzero(&auio, sizeof(auio));
4782         aiov.iov_base = uap->data;
4783         aiov.iov_len = uap->nbytes;
4784         auio.uio_iov = &aiov;
4785         auio.uio_iovcnt = 1;
4786         auio.uio_offset = 0;
4787         auio.uio_resid = uap->nbytes;
4788         auio.uio_rw = UIO_READ;
4789         auio.uio_td = curthread;
4790
4791         error = VOP_GETEXTATTR(vp, uap->attrnamespace, attrname,
4792                                 &auio, nd.nl_cred);
4793         uap->sysmsg_result = uap->nbytes - auio.uio_resid;
4794
4795         vput(vp);
4796         nlookup_done(&nd);
4797         rel_mplock();
4798         return(error);
4799 }
4800
4801 /*
4802  * Syscall to delete a named extended attribute from a file or directory.
4803  * Accepts attribute name.  The real work happens in VOP_SETEXTATTR().
4804  *
4805  * MPALMOSTSAFE
4806  */
4807 int
4808 sys_extattr_delete_file(struct extattr_delete_file_args *uap)
4809 {
4810         char attrname[EXTATTR_MAXNAMELEN];
4811         struct nlookupdata nd;
4812         struct vnode *vp;
4813         int error;
4814
4815         error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN);
4816         if (error)
4817                 return(error);
4818
4819         get_mplock();
4820         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4821         if (error == 0)
4822                 error = nlookup(&nd);
4823         if (error == 0)
4824                 error = ncp_writechk(&nd.nl_nch);
4825         if (error == 0) {
4826                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
4827                 if (error == 0) {
4828                         error = VOP_SETEXTATTR(vp, uap->attrnamespace,
4829                                                attrname, NULL, nd.nl_cred);
4830                         vput(vp);
4831                 }
4832         }
4833         nlookup_done(&nd);
4834         rel_mplock();
4835         return(error);
4836 }
4837
4838 /*
4839  * Determine if the mount is visible to the process.
4840  */
4841 static int
4842 chroot_visible_mnt(struct mount *mp, struct proc *p)
4843 {
4844         struct nchandle nch;
4845
4846         /*
4847          * Traverse from the mount point upwards.  If we hit the process
4848          * root then the mount point is visible to the process.
4849          */
4850         nch = mp->mnt_ncmountpt;
4851         while (nch.ncp) {
4852                 if (nch.mount == p->p_fd->fd_nrdir.mount &&
4853                     nch.ncp == p->p_fd->fd_nrdir.ncp) {
4854                         return(1);
4855                 }
4856                 if (nch.ncp == nch.mount->mnt_ncmountpt.ncp) {
4857                         nch = nch.mount->mnt_ncmounton;
4858                 } else {
4859                         nch.ncp = nch.ncp->nc_parent;
4860                 }
4861         }
4862
4863         /*
4864          * If the mount point is not visible to the process, but the
4865          * process root is in a subdirectory of the mount, return
4866          * TRUE anyway.
4867          */
4868         if (p->p_fd->fd_nrdir.mount == mp)
4869                 return(1);
4870
4871         return(0);
4872 }
4873