3ab94e21120f74208444a79f327b4765d3aaafef
[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  * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.135 2008/11/11 00:55:49 pavalos Exp $
41  */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/buf.h>
46 #include <sys/conf.h>
47 #include <sys/sysent.h>
48 #include <sys/malloc.h>
49 #include <sys/mount.h>
50 #include <sys/mountctl.h>
51 #include <sys/sysproto.h>
52 #include <sys/filedesc.h>
53 #include <sys/kernel.h>
54 #include <sys/fcntl.h>
55 #include <sys/file.h>
56 #include <sys/linker.h>
57 #include <sys/stat.h>
58 #include <sys/unistd.h>
59 #include <sys/vnode.h>
60 #include <sys/proc.h>
61 #include <sys/priv.h>
62 #include <sys/jail.h>
63 #include <sys/namei.h>
64 #include <sys/nlookup.h>
65 #include <sys/dirent.h>
66 #include <sys/extattr.h>
67 #include <sys/spinlock.h>
68 #include <sys/kern_syscall.h>
69 #include <sys/objcache.h>
70 #include <sys/sysctl.h>
71
72 #include <sys/buf2.h>
73 #include <sys/file2.h>
74 #include <sys/spinlock2.h>
75 #include <sys/mplock2.h>
76
77 #include <vm/vm.h>
78 #include <vm/vm_object.h>
79 #include <vm/vm_page.h>
80
81 #include <machine/limits.h>
82 #include <machine/stdarg.h>
83
84 #include <vfs/union/union.h>
85
86 static void mount_warning(struct mount *mp, const char *ctl, ...);
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_wr(&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_wr(&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         CACHE_MPLOCK_DECLARE;
1982         struct nlookupdata nd;
1983         int error;
1984
1985         CACHE_GETMPLOCK1();
1986         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
1987         if (error == 0) {
1988                 error = kern_open(&nd, uap->flags,
1989                                     uap->mode, &uap->sysmsg_result);
1990         }
1991         nlookup_done(&nd);
1992         CACHE_RELMPLOCK();
1993         return (error);
1994 }
1995
1996 /*
1997  * openat_args(int fd, char *path, int flags, int mode)
1998  *
1999  * MPALMOSTSAFE
2000  */
2001 int
2002 sys_openat(struct openat_args *uap)
2003 {
2004         CACHE_MPLOCK_DECLARE;
2005         struct nlookupdata nd;
2006         int error;
2007         struct file *fp;
2008
2009         CACHE_GETMPLOCK1();
2010         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
2011         if (error == 0) {
2012                 error = kern_open(&nd, uap->flags, uap->mode, 
2013                                         &uap->sysmsg_result);
2014         }
2015         nlookup_done_at(&nd, fp);
2016         CACHE_RELMPLOCK();
2017         return (error);
2018 }
2019
2020 int
2021 kern_mknod(struct nlookupdata *nd, int mode, int rmajor, int rminor)
2022 {
2023         struct thread *td = curthread;
2024         struct proc *p = td->td_proc;
2025         struct vnode *vp;
2026         struct vattr vattr;
2027         int error;
2028         int whiteout = 0;
2029
2030         KKASSERT(p);
2031
2032         VATTR_NULL(&vattr);
2033         vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask;
2034         vattr.va_rmajor = rmajor;
2035         vattr.va_rminor = rminor;
2036
2037         switch (mode & S_IFMT) {
2038         case S_IFMT:    /* used by badsect to flag bad sectors */
2039                 error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_BAD, 0);
2040                 vattr.va_type = VBAD;
2041                 break;
2042         case S_IFCHR:
2043                 error = priv_check(td, PRIV_VFS_MKNOD_DEV);
2044                 vattr.va_type = VCHR;
2045                 break;
2046         case S_IFBLK:
2047                 error = priv_check(td, PRIV_VFS_MKNOD_DEV);
2048                 vattr.va_type = VBLK;
2049                 break;
2050         case S_IFWHT:
2051                 error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_WHT, 0);
2052                 whiteout = 1;
2053                 break;
2054         case S_IFDIR:   /* special directories support for HAMMER */
2055                 error = priv_check_cred(td->td_ucred, PRIV_VFS_MKNOD_DIR, 0);
2056                 vattr.va_type = VDIR;
2057                 break;
2058         default:
2059                 error = EINVAL;
2060                 break;
2061         }
2062
2063         if (error)
2064                 return (error);
2065
2066         bwillinode(1);
2067         nd->nl_flags |= NLC_CREATE | NLC_REFDVP;
2068         if ((error = nlookup(nd)) != 0)
2069                 return (error);
2070         if (nd->nl_nch.ncp->nc_vp)
2071                 return (EEXIST);
2072         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2073                 return (error);
2074
2075         if (whiteout) {
2076                 error = VOP_NWHITEOUT(&nd->nl_nch, nd->nl_dvp,
2077                                       nd->nl_cred, NAMEI_CREATE);
2078         } else {
2079                 vp = NULL;
2080                 error = VOP_NMKNOD(&nd->nl_nch, nd->nl_dvp,
2081                                    &vp, nd->nl_cred, &vattr);
2082                 if (error == 0)
2083                         vput(vp);
2084         }
2085         return (error);
2086 }
2087
2088 /*
2089  * mknod_args(char *path, int mode, int dev)
2090  *
2091  * Create a special file.
2092  *
2093  * MPALMOSTSAFE
2094  */
2095 int
2096 sys_mknod(struct mknod_args *uap)
2097 {
2098         struct nlookupdata nd;
2099         int error;
2100
2101         get_mplock();
2102         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2103         if (error == 0) {
2104                 error = kern_mknod(&nd, uap->mode,
2105                                    umajor(uap->dev), uminor(uap->dev));
2106         }
2107         nlookup_done(&nd);
2108         rel_mplock();
2109         return (error);
2110 }
2111
2112 int
2113 kern_mkfifo(struct nlookupdata *nd, int mode)
2114 {
2115         struct thread *td = curthread;
2116         struct proc *p = td->td_proc;
2117         struct vattr vattr;
2118         struct vnode *vp;
2119         int error;
2120
2121         bwillinode(1);
2122
2123         nd->nl_flags |= NLC_CREATE | NLC_REFDVP;
2124         if ((error = nlookup(nd)) != 0)
2125                 return (error);
2126         if (nd->nl_nch.ncp->nc_vp)
2127                 return (EEXIST);
2128         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2129                 return (error);
2130
2131         VATTR_NULL(&vattr);
2132         vattr.va_type = VFIFO;
2133         vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask;
2134         vp = NULL;
2135         error = VOP_NMKNOD(&nd->nl_nch, nd->nl_dvp, &vp, nd->nl_cred, &vattr);
2136         if (error == 0)
2137                 vput(vp);
2138         return (error);
2139 }
2140
2141 /*
2142  * mkfifo_args(char *path, int mode)
2143  *
2144  * Create a named pipe.
2145  *
2146  * MPALMOSTSAFE
2147  */
2148 int
2149 sys_mkfifo(struct mkfifo_args *uap)
2150 {
2151         struct nlookupdata nd;
2152         int error;
2153
2154         get_mplock();
2155         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2156         if (error == 0)
2157                 error = kern_mkfifo(&nd, uap->mode);
2158         nlookup_done(&nd);
2159         rel_mplock();
2160         return (error);
2161 }
2162
2163 static int hardlink_check_uid = 0;
2164 SYSCTL_INT(_security, OID_AUTO, hardlink_check_uid, CTLFLAG_RW,
2165     &hardlink_check_uid, 0, 
2166     "Unprivileged processes cannot create hard links to files owned by other "
2167     "users");
2168 static int hardlink_check_gid = 0;
2169 SYSCTL_INT(_security, OID_AUTO, hardlink_check_gid, CTLFLAG_RW,
2170     &hardlink_check_gid, 0,
2171     "Unprivileged processes cannot create hard links to files owned by other "
2172     "groups");
2173
2174 static int
2175 can_hardlink(struct vnode *vp, struct thread *td, struct ucred *cred)
2176 {
2177         struct vattr va;
2178         int error;
2179
2180         /*
2181          * Shortcut if disabled
2182          */
2183         if (hardlink_check_uid == 0 && hardlink_check_gid == 0)
2184                 return (0);
2185
2186         /*
2187          * Privileged user can always hardlink
2188          */
2189         if (priv_check_cred(cred, PRIV_VFS_LINK, 0) == 0)
2190                 return (0);
2191
2192         /*
2193          * Otherwise only if the originating file is owned by the
2194          * same user or group.  Note that any group is allowed if
2195          * the file is owned by the caller.
2196          */
2197         error = VOP_GETATTR(vp, &va);
2198         if (error != 0)
2199                 return (error);
2200         
2201         if (hardlink_check_uid) {
2202                 if (cred->cr_uid != va.va_uid)
2203                         return (EPERM);
2204         }
2205         
2206         if (hardlink_check_gid) {
2207                 if (cred->cr_uid != va.va_uid && !groupmember(va.va_gid, cred))
2208                         return (EPERM);
2209         }
2210
2211         return (0);
2212 }
2213
2214 int
2215 kern_link(struct nlookupdata *nd, struct nlookupdata *linknd)
2216 {
2217         struct thread *td = curthread;
2218         struct vnode *vp;
2219         int error;
2220
2221         /*
2222          * Lookup the source and obtained a locked vnode.
2223          *
2224          * You may only hardlink a file which you have write permission
2225          * on or which you own.
2226          *
2227          * XXX relookup on vget failure / race ?
2228          */
2229         bwillinode(1);
2230         nd->nl_flags |= NLC_WRITE | NLC_OWN | NLC_HLINK;
2231         if ((error = nlookup(nd)) != 0)
2232                 return (error);
2233         vp = nd->nl_nch.ncp->nc_vp;
2234         KKASSERT(vp != NULL);
2235         if (vp->v_type == VDIR)
2236                 return (EPERM);         /* POSIX */
2237         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2238                 return (error);
2239         if ((error = vget(vp, LK_EXCLUSIVE)) != 0)
2240                 return (error);
2241
2242         /*
2243          * Unlock the source so we can lookup the target without deadlocking
2244          * (XXX vp is locked already, possible other deadlock?).  The target
2245          * must not exist.
2246          */
2247         KKASSERT(nd->nl_flags & NLC_NCPISLOCKED);
2248         nd->nl_flags &= ~NLC_NCPISLOCKED;
2249         cache_unlock(&nd->nl_nch);
2250         vn_unlock(vp);
2251
2252         linknd->nl_flags |= NLC_CREATE | NLC_REFDVP;
2253         if ((error = nlookup(linknd)) != 0) {
2254                 vrele(vp);
2255                 return (error);
2256         }
2257         if (linknd->nl_nch.ncp->nc_vp) {
2258                 vrele(vp);
2259                 return (EEXIST);
2260         }
2261         if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) {
2262                 vrele(vp);
2263                 return (error);
2264         }
2265
2266         /*
2267          * Finally run the new API VOP.
2268          */
2269         error = can_hardlink(vp, td, td->td_ucred);
2270         if (error == 0) {
2271                 error = VOP_NLINK(&linknd->nl_nch, linknd->nl_dvp,
2272                                   vp, linknd->nl_cred);
2273         }
2274         vput(vp);
2275         return (error);
2276 }
2277
2278 /*
2279  * link_args(char *path, char *link)
2280  *
2281  * Make a hard file link.
2282  *
2283  * MPALMOSTSAFE
2284  */
2285 int
2286 sys_link(struct link_args *uap)
2287 {
2288         struct nlookupdata nd, linknd;
2289         int error;
2290
2291         get_mplock();
2292         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2293         if (error == 0) {
2294                 error = nlookup_init(&linknd, uap->link, UIO_USERSPACE, 0);
2295                 if (error == 0)
2296                         error = kern_link(&nd, &linknd);
2297                 nlookup_done(&linknd);
2298         }
2299         nlookup_done(&nd);
2300         rel_mplock();
2301         return (error);
2302 }
2303
2304 int
2305 kern_symlink(struct nlookupdata *nd, char *path, int mode)
2306 {
2307         struct vattr vattr;
2308         struct vnode *vp;
2309         struct vnode *dvp;
2310         int error;
2311
2312         bwillinode(1);
2313         nd->nl_flags |= NLC_CREATE | NLC_REFDVP;
2314         if ((error = nlookup(nd)) != 0)
2315                 return (error);
2316         if (nd->nl_nch.ncp->nc_vp)
2317                 return (EEXIST);
2318         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2319                 return (error);
2320         dvp = nd->nl_dvp;
2321         VATTR_NULL(&vattr);
2322         vattr.va_mode = mode;
2323         error = VOP_NSYMLINK(&nd->nl_nch, dvp, &vp, nd->nl_cred, &vattr, path);
2324         if (error == 0)
2325                 vput(vp);
2326         return (error);
2327 }
2328
2329 /*
2330  * symlink(char *path, char *link)
2331  *
2332  * Make a symbolic link.
2333  *
2334  * MPALMOSTSAFE
2335  */
2336 int
2337 sys_symlink(struct symlink_args *uap)
2338 {
2339         struct thread *td = curthread;
2340         struct nlookupdata nd;
2341         char *path;
2342         int error;
2343         int mode;
2344
2345         path = objcache_get(namei_oc, M_WAITOK);
2346         error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
2347         if (error == 0) {
2348                 get_mplock();
2349                 error = nlookup_init(&nd, uap->link, UIO_USERSPACE, 0);
2350                 if (error == 0) {
2351                         mode = ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask;
2352                         error = kern_symlink(&nd, path, mode);
2353                 }
2354                 nlookup_done(&nd);
2355                 rel_mplock();
2356         }
2357         objcache_put(namei_oc, path);
2358         return (error);
2359 }
2360
2361 /*
2362  * undelete_args(char *path)
2363  *
2364  * Delete a whiteout from the filesystem.
2365  *
2366  * MPALMOSTSAFE
2367  */
2368 int
2369 sys_undelete(struct undelete_args *uap)
2370 {
2371         struct nlookupdata nd;
2372         int error;
2373
2374         get_mplock();
2375         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2376         bwillinode(1);
2377         nd.nl_flags |= NLC_DELETE | NLC_REFDVP;
2378         if (error == 0)
2379                 error = nlookup(&nd);
2380         if (error == 0)
2381                 error = ncp_writechk(&nd.nl_nch);
2382         if (error == 0) {
2383                 error = VOP_NWHITEOUT(&nd.nl_nch, nd.nl_dvp, nd.nl_cred,
2384                                       NAMEI_DELETE);
2385         }
2386         nlookup_done(&nd);
2387         rel_mplock();
2388         return (error);
2389 }
2390
2391 int
2392 kern_unlink(struct nlookupdata *nd)
2393 {
2394         int error;
2395
2396         bwillinode(1);
2397         nd->nl_flags |= NLC_DELETE | NLC_REFDVP;
2398         if ((error = nlookup(nd)) != 0)
2399                 return (error);
2400         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
2401                 return (error);
2402         error = VOP_NREMOVE(&nd->nl_nch, nd->nl_dvp, nd->nl_cred);
2403         return (error);
2404 }
2405
2406 /*
2407  * unlink_args(char *path)
2408  *
2409  * Delete a name from the filesystem.
2410  *
2411  * MPALMOSTSAFE
2412  */
2413 int
2414 sys_unlink(struct unlink_args *uap)
2415 {
2416         struct nlookupdata nd;
2417         int error;
2418
2419         get_mplock();
2420         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2421         if (error == 0)
2422                 error = kern_unlink(&nd);
2423         nlookup_done(&nd);
2424         rel_mplock();
2425         return (error);
2426 }
2427
2428
2429 /*
2430  * unlinkat_args(int fd, char *path, int flags)
2431  *
2432  * Delete the file or directory entry pointed to by fd/path.
2433  *
2434  * MPALMOSTSAFE
2435  */
2436 int
2437 sys_unlinkat(struct unlinkat_args *uap)
2438 {
2439         struct nlookupdata nd;
2440         struct file *fp;
2441         int error;
2442
2443         if (uap->flags & ~AT_REMOVEDIR)
2444                 return (EINVAL);
2445
2446         get_mplock();
2447         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 0);
2448         if (error == 0) {
2449                 if (uap->flags & AT_REMOVEDIR)
2450                         error = kern_rmdir(&nd);
2451                 else
2452                         error = kern_unlink(&nd);
2453         }
2454         nlookup_done_at(&nd, fp);
2455         rel_mplock();
2456         return (error);
2457 }
2458
2459 /*
2460  * MPALMOSTSAFE
2461  */
2462 int
2463 kern_lseek(int fd, off_t offset, int whence, off_t *res)
2464 {
2465         struct thread *td = curthread;
2466         struct proc *p = td->td_proc;
2467         struct file *fp;
2468         struct vnode *vp;
2469         struct vattr vattr;
2470         off_t new_offset;
2471         int error;
2472
2473         fp = holdfp(p->p_fd, fd, -1);
2474         if (fp == NULL)
2475                 return (EBADF);
2476         if (fp->f_type != DTYPE_VNODE) {
2477                 error = ESPIPE;
2478                 goto done;
2479         }
2480         vp = (struct vnode *)fp->f_data;
2481
2482         switch (whence) {
2483         case L_INCR:
2484                 spin_lock_wr(&fp->f_spin);
2485                 new_offset = fp->f_offset + offset;
2486                 error = 0;
2487                 break;
2488         case L_XTND:
2489                 get_mplock();
2490                 error = VOP_GETATTR(vp, &vattr);
2491                 rel_mplock();
2492                 spin_lock_wr(&fp->f_spin);
2493                 new_offset = offset + vattr.va_size;
2494                 break;
2495         case L_SET:
2496                 new_offset = offset;
2497                 error = 0;
2498                 spin_lock_wr(&fp->f_spin);
2499                 break;
2500         default:
2501                 new_offset = 0;
2502                 error = EINVAL;
2503                 spin_lock_wr(&fp->f_spin);
2504                 break;
2505         }
2506
2507         /*
2508          * Validate the seek position.  Negative offsets are not allowed
2509          * for regular files or directories.
2510          *
2511          * Normally we would also not want to allow negative offsets for
2512          * character and block-special devices.  However kvm addresses
2513          * on 64 bit architectures might appear to be negative and must
2514          * be allowed.
2515          */
2516         if (error == 0) {
2517                 if (new_offset < 0 &&
2518                     (vp->v_type == VREG || vp->v_type == VDIR)) {
2519                         error = EINVAL;
2520                 } else {
2521                         fp->f_offset = new_offset;
2522                 }
2523         }
2524         *res = fp->f_offset;
2525         spin_unlock_wr(&fp->f_spin);
2526 done:
2527         fdrop(fp);
2528         return (error);
2529 }
2530
2531 /*
2532  * lseek_args(int fd, int pad, off_t offset, int whence)
2533  *
2534  * Reposition read/write file offset.
2535  *
2536  * MPSAFE
2537  */
2538 int
2539 sys_lseek(struct lseek_args *uap)
2540 {
2541         int error;
2542
2543         error = kern_lseek(uap->fd, uap->offset, uap->whence,
2544                            &uap->sysmsg_offset);
2545
2546         return (error);
2547 }
2548
2549 /*
2550  * Check if current process can access given file.  amode is a bitmask of *_OK
2551  * access bits.  flags is a bitmask of AT_* flags.
2552  */
2553 int
2554 kern_access(struct nlookupdata *nd, int amode, int flags)
2555 {
2556         struct vnode *vp;
2557         int error, mode;
2558
2559         if (flags & ~AT_EACCESS)
2560                 return (EINVAL);
2561         if ((error = nlookup(nd)) != 0)
2562                 return (error);
2563 retry:
2564         error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, &vp);
2565         if (error)
2566                 return (error);
2567
2568         /* Flags == 0 means only check for existence. */
2569         if (amode) {
2570                 mode = 0;
2571                 if (amode & R_OK)
2572                         mode |= VREAD;
2573                 if (amode & W_OK)
2574                         mode |= VWRITE;
2575                 if (amode & X_OK)
2576                         mode |= VEXEC;
2577                 if ((mode & VWRITE) == 0 || 
2578                     (error = vn_writechk(vp, &nd->nl_nch)) == 0)
2579                         error = VOP_ACCESS_FLAGS(vp, mode, flags, nd->nl_cred);
2580
2581                 /*
2582                  * If the file handle is stale we have to re-resolve the
2583                  * entry.  This is a hack at the moment.
2584                  */
2585                 if (error == ESTALE) {
2586                         vput(vp);
2587                         cache_setunresolved(&nd->nl_nch);
2588                         error = cache_resolve(&nd->nl_nch, nd->nl_cred);
2589                         if (error == 0) {
2590                                 vp = NULL;
2591                                 goto retry;
2592                         }
2593                         return(error);
2594                 }
2595         }
2596         vput(vp);
2597         return (error);
2598 }
2599
2600 /*
2601  * access_args(char *path, int flags)
2602  *
2603  * Check access permissions.
2604  *
2605  * MPALMOSTSAFE
2606  */
2607 int
2608 sys_access(struct access_args *uap)
2609 {
2610         struct nlookupdata nd;
2611         int error;
2612
2613         get_mplock();
2614         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2615         if (error == 0)
2616                 error = kern_access(&nd, uap->flags, 0);
2617         nlookup_done(&nd);
2618         rel_mplock();
2619         return (error);
2620 }
2621
2622
2623 /*
2624  * faccessat_args(int fd, char *path, int amode, int flags)
2625  *
2626  * Check access permissions.
2627  *
2628  * MPALMOSTSAFE
2629  */
2630 int
2631 sys_faccessat(struct faccessat_args *uap)
2632 {
2633         struct nlookupdata nd;
2634         struct file *fp;
2635         int error;
2636
2637         get_mplock();
2638         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, UIO_USERSPACE, 
2639                                 NLC_FOLLOW);
2640         if (error == 0)
2641                 error = kern_access(&nd, uap->amode, uap->flags);
2642         nlookup_done_at(&nd, fp);
2643         rel_mplock();
2644         return (error);
2645 }
2646
2647
2648 /*
2649  * MPSAFE
2650  */
2651 int
2652 kern_stat(struct nlookupdata *nd, struct stat *st)
2653 {
2654         int error;
2655         struct vnode *vp;
2656         thread_t td;
2657
2658         if ((error = nlookup(nd)) != 0)
2659                 return (error);
2660 again:
2661         if ((vp = nd->nl_nch.ncp->nc_vp) == NULL)
2662                 return (ENOENT);
2663
2664         td = curthread;
2665         if ((error = vget(vp, LK_SHARED)) != 0)
2666                 return (error);
2667         error = vn_stat(vp, st, nd->nl_cred);
2668
2669         /*
2670          * If the file handle is stale we have to re-resolve the entry.  This
2671          * is a hack at the moment.
2672          */
2673         if (error == ESTALE) {
2674                 vput(vp);
2675                 cache_setunresolved(&nd->nl_nch);
2676                 error = cache_resolve(&nd->nl_nch, nd->nl_cred);
2677                 if (error == 0)
2678                         goto again;
2679         } else {
2680                 vput(vp);
2681         }
2682         return (error);
2683 }
2684
2685 /*
2686  * stat_args(char *path, struct stat *ub)
2687  *
2688  * Get file status; this version follows links.
2689  *
2690  * MPSAFE
2691  */
2692 int
2693 sys_stat(struct stat_args *uap)
2694 {
2695         CACHE_MPLOCK_DECLARE;
2696         struct nlookupdata nd;
2697         struct stat st;
2698         int error;
2699
2700         CACHE_GETMPLOCK1();
2701         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2702         if (error == 0) {
2703                 error = kern_stat(&nd, &st);
2704                 if (error == 0)
2705                         error = copyout(&st, uap->ub, sizeof(*uap->ub));
2706         }
2707         nlookup_done(&nd);
2708         CACHE_RELMPLOCK();
2709         return (error);
2710 }
2711
2712 /*
2713  * lstat_args(char *path, struct stat *ub)
2714  *
2715  * Get file status; this version does not follow links.
2716  *
2717  * MPALMOSTSAFE
2718  */
2719 int
2720 sys_lstat(struct lstat_args *uap)
2721 {
2722         CACHE_MPLOCK_DECLARE;
2723         struct nlookupdata nd;
2724         struct stat st;
2725         int error;
2726
2727         CACHE_GETMPLOCK1();
2728         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2729         if (error == 0) {
2730                 error = kern_stat(&nd, &st);
2731                 if (error == 0)
2732                         error = copyout(&st, uap->ub, sizeof(*uap->ub));
2733         }
2734         nlookup_done(&nd);
2735         CACHE_RELMPLOCK();
2736         return (error);
2737 }
2738
2739 /*
2740  * fstatat_args(int fd, char *path, struct stat *sb, int flags)
2741  *
2742  * Get status of file pointed to by fd/path.
2743  *
2744  * MPALMOSTSAFE
2745  */
2746 int
2747 sys_fstatat(struct fstatat_args *uap)
2748 {
2749         CACHE_MPLOCK_DECLARE;
2750         struct nlookupdata nd;
2751         struct stat st;
2752         int error;
2753         int flags;
2754         struct file *fp;
2755
2756         if (uap->flags & ~AT_SYMLINK_NOFOLLOW)
2757                 return (EINVAL);
2758
2759         flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
2760
2761         CACHE_GETMPLOCK1();
2762         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 
2763                                 UIO_USERSPACE, flags);
2764         if (error == 0) {
2765                 error = kern_stat(&nd, &st);
2766                 if (error == 0)
2767                         error = copyout(&st, uap->sb, sizeof(*uap->sb));
2768         }
2769         nlookup_done_at(&nd, fp);
2770         CACHE_RELMPLOCK();
2771         return (error);
2772 }
2773
2774 /*
2775  * pathconf_Args(char *path, int name)
2776  *
2777  * Get configurable pathname variables.
2778  *
2779  * MPALMOSTSAFE
2780  */
2781 int
2782 sys_pathconf(struct pathconf_args *uap)
2783 {
2784         struct nlookupdata nd;
2785         struct vnode *vp;
2786         int error;
2787
2788         vp = NULL;
2789         get_mplock();
2790         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2791         if (error == 0)
2792                 error = nlookup(&nd);
2793         if (error == 0)
2794                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
2795         nlookup_done(&nd);
2796         if (error == 0) {
2797                 error = VOP_PATHCONF(vp, uap->name, &uap->sysmsg_reg);
2798                 vput(vp);
2799         }
2800         rel_mplock();
2801         return (error);
2802 }
2803
2804 /*
2805  * XXX: daver
2806  * kern_readlink isn't properly split yet.  There is a copyin burried
2807  * in VOP_READLINK().
2808  */
2809 int
2810 kern_readlink(struct nlookupdata *nd, char *buf, int count, int *res)
2811 {
2812         struct thread *td = curthread;
2813         struct vnode *vp;
2814         struct iovec aiov;
2815         struct uio auio;
2816         int error;
2817
2818         if ((error = nlookup(nd)) != 0)
2819                 return (error);
2820         error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, &vp);
2821         if (error)
2822                 return (error);
2823         if (vp->v_type != VLNK) {
2824                 error = EINVAL;
2825         } else {
2826                 aiov.iov_base = buf;
2827                 aiov.iov_len = count;
2828                 auio.uio_iov = &aiov;
2829                 auio.uio_iovcnt = 1;
2830                 auio.uio_offset = 0;
2831                 auio.uio_rw = UIO_READ;
2832                 auio.uio_segflg = UIO_USERSPACE;
2833                 auio.uio_td = td;
2834                 auio.uio_resid = count;
2835                 error = VOP_READLINK(vp, &auio, td->td_ucred);
2836         }
2837         vput(vp);
2838         *res = count - auio.uio_resid;
2839         return (error);
2840 }
2841
2842 /*
2843  * readlink_args(char *path, char *buf, int count)
2844  *
2845  * Return target name of a symbolic link.
2846  *
2847  * MPALMOSTSAFE
2848  */
2849 int
2850 sys_readlink(struct readlink_args *uap)
2851 {
2852         struct nlookupdata nd;
2853         int error;
2854
2855         get_mplock();
2856         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2857         if (error == 0) {
2858                 error = kern_readlink(&nd, uap->buf, uap->count,
2859                                         &uap->sysmsg_result);
2860         }
2861         nlookup_done(&nd);
2862         rel_mplock();
2863         return (error);
2864 }
2865
2866 static int
2867 setfflags(struct vnode *vp, int flags)
2868 {
2869         struct thread *td = curthread;
2870         int error;
2871         struct vattr vattr;
2872
2873         /*
2874          * Prevent non-root users from setting flags on devices.  When
2875          * a device is reused, users can retain ownership of the device
2876          * if they are allowed to set flags and programs assume that
2877          * chown can't fail when done as root.
2878          */
2879         if ((vp->v_type == VCHR || vp->v_type == VBLK) && 
2880             ((error = priv_check_cred(td->td_ucred, PRIV_VFS_CHFLAGS_DEV, 0)) != 0))
2881                 return (error);
2882
2883         /*
2884          * note: vget is required for any operation that might mod the vnode
2885          * so VINACTIVE is properly cleared.
2886          */
2887         if ((error = vget(vp, LK_EXCLUSIVE)) == 0) {
2888                 VATTR_NULL(&vattr);
2889                 vattr.va_flags = flags;
2890                 error = VOP_SETATTR(vp, &vattr, td->td_ucred);
2891                 vput(vp);
2892         }
2893         return (error);
2894 }
2895
2896 /*
2897  * chflags(char *path, int flags)
2898  *
2899  * Change flags of a file given a path name.
2900  *
2901  * MPALMOSTSAFE
2902  */
2903 int
2904 sys_chflags(struct chflags_args *uap)
2905 {
2906         struct nlookupdata nd;
2907         struct vnode *vp;
2908         int error;
2909
2910         vp = NULL;
2911         get_mplock();
2912         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
2913         if (error == 0)
2914                 error = nlookup(&nd);
2915         if (error == 0)
2916                 error = ncp_writechk(&nd.nl_nch);
2917         if (error == 0)
2918                 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
2919         nlookup_done(&nd);
2920         if (error == 0) {
2921                 error = setfflags(vp, uap->flags);
2922                 vrele(vp);
2923         }
2924         rel_mplock();
2925         return (error);
2926 }
2927
2928 /*
2929  * lchflags(char *path, int flags)
2930  *
2931  * Change flags of a file given a path name, but don't follow symlinks.
2932  *
2933  * MPALMOSTSAFE
2934  */
2935 int
2936 sys_lchflags(struct lchflags_args *uap)
2937 {
2938         struct nlookupdata nd;
2939         struct vnode *vp;
2940         int error;
2941
2942         vp = NULL;
2943         get_mplock();
2944         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
2945         if (error == 0)
2946                 error = nlookup(&nd);
2947         if (error == 0)
2948                 error = ncp_writechk(&nd.nl_nch);
2949         if (error == 0)
2950                 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
2951         nlookup_done(&nd);
2952         if (error == 0) {
2953                 error = setfflags(vp, uap->flags);
2954                 vrele(vp);
2955         }
2956         rel_mplock();
2957         return (error);
2958 }
2959
2960 /*
2961  * fchflags_args(int fd, int flags)
2962  *
2963  * Change flags of a file given a file descriptor.
2964  *
2965  * MPALMOSTSAFE
2966  */
2967 int
2968 sys_fchflags(struct fchflags_args *uap)
2969 {
2970         struct thread *td = curthread;
2971         struct proc *p = td->td_proc;
2972         struct file *fp;
2973         int error;
2974
2975         if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
2976                 return (error);
2977         get_mplock();
2978         if (fp->f_nchandle.ncp)
2979                 error = ncp_writechk(&fp->f_nchandle);
2980         if (error == 0)
2981                 error = setfflags((struct vnode *) fp->f_data, uap->flags);
2982         rel_mplock();
2983         fdrop(fp);
2984         return (error);
2985 }
2986
2987 static int
2988 setfmode(struct vnode *vp, int mode)
2989 {
2990         struct thread *td = curthread;
2991         int error;
2992         struct vattr vattr;
2993
2994         /*
2995          * note: vget is required for any operation that might mod the vnode
2996          * so VINACTIVE is properly cleared.
2997          */
2998         if ((error = vget(vp, LK_EXCLUSIVE)) == 0) {
2999                 VATTR_NULL(&vattr);
3000                 vattr.va_mode = mode & ALLPERMS;
3001                 error = VOP_SETATTR(vp, &vattr, td->td_ucred);
3002                 vput(vp);
3003         }
3004         return error;
3005 }
3006
3007 int
3008 kern_chmod(struct nlookupdata *nd, int mode)
3009 {
3010         struct vnode *vp;
3011         int error;
3012
3013         if ((error = nlookup(nd)) != 0)
3014                 return (error);
3015         if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
3016                 return (error);
3017         if ((error = ncp_writechk(&nd->nl_nch)) == 0)
3018                 error = setfmode(vp, mode);
3019         vrele(vp);
3020         return (error);
3021 }
3022
3023 /*
3024  * chmod_args(char *path, int mode)
3025  *
3026  * Change mode of a file given path name.
3027  *
3028  * MPALMOSTSAFE
3029  */
3030 int
3031 sys_chmod(struct chmod_args *uap)
3032 {
3033         struct nlookupdata nd;
3034         int error;
3035
3036         get_mplock();
3037         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3038         if (error == 0)
3039                 error = kern_chmod(&nd, uap->mode);
3040         nlookup_done(&nd);
3041         rel_mplock();
3042         return (error);
3043 }
3044
3045 /*
3046  * lchmod_args(char *path, int mode)
3047  *
3048  * Change mode of a file given path name (don't follow links.)
3049  *
3050  * MPALMOSTSAFE
3051  */
3052 int
3053 sys_lchmod(struct lchmod_args *uap)
3054 {
3055         struct nlookupdata nd;
3056         int error;
3057
3058         get_mplock();
3059         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3060         if (error == 0)
3061                 error = kern_chmod(&nd, uap->mode);
3062         nlookup_done(&nd);
3063         rel_mplock();
3064         return (error);
3065 }
3066
3067 /*
3068  * fchmod_args(int fd, int mode)
3069  *
3070  * Change mode of a file given a file descriptor.
3071  *
3072  * MPALMOSTSAFE
3073  */
3074 int
3075 sys_fchmod(struct fchmod_args *uap)
3076 {
3077         struct thread *td = curthread;
3078         struct proc *p = td->td_proc;
3079         struct file *fp;
3080         int error;
3081
3082         if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
3083                 return (error);
3084         get_mplock();
3085         if (fp->f_nchandle.ncp)
3086                 error = ncp_writechk(&fp->f_nchandle);
3087         if (error == 0)
3088                 error = setfmode((struct vnode *)fp->f_data, uap->mode);
3089         rel_mplock();
3090         fdrop(fp);
3091         return (error);
3092 }
3093
3094 /*
3095  * fchmodat_args(char *path, int mode)
3096  *
3097  * Change mode of a file pointed to by fd/path.
3098  *
3099  * MPALMOSTSAFE
3100  */
3101 int
3102 sys_fchmodat(struct fchmodat_args *uap)
3103 {
3104         struct nlookupdata nd;
3105         struct file *fp;
3106         int error;
3107         int flags;
3108
3109         if (uap->flags & ~AT_SYMLINK_NOFOLLOW)
3110                 return (EINVAL);
3111         flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
3112
3113         get_mplock();
3114         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 
3115                                 UIO_USERSPACE, flags);
3116         if (error == 0)
3117                 error = kern_chmod(&nd, uap->mode);
3118         nlookup_done_at(&nd, fp);
3119         rel_mplock();
3120         return (error);
3121 }
3122
3123 static int
3124 setfown(struct vnode *vp, uid_t uid, gid_t gid)
3125 {
3126         struct thread *td = curthread;
3127         int error;
3128         struct vattr vattr;
3129
3130         /*
3131          * note: vget is required for any operation that might mod the vnode
3132          * so VINACTIVE is properly cleared.
3133          */
3134         if ((error = vget(vp, LK_EXCLUSIVE)) == 0) {
3135                 VATTR_NULL(&vattr);
3136                 vattr.va_uid = uid;
3137                 vattr.va_gid = gid;
3138                 error = VOP_SETATTR(vp, &vattr, td->td_ucred);
3139                 vput(vp);
3140         }
3141         return error;
3142 }
3143
3144 int
3145 kern_chown(struct nlookupdata *nd, int uid, int gid)
3146 {
3147         struct vnode *vp;
3148         int error;
3149
3150         if ((error = nlookup(nd)) != 0)
3151                 return (error);
3152         if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
3153                 return (error);
3154         if ((error = ncp_writechk(&nd->nl_nch)) == 0)
3155                 error = setfown(vp, uid, gid);
3156         vrele(vp);
3157         return (error);
3158 }
3159
3160 /*
3161  * chown(char *path, int uid, int gid)
3162  *
3163  * Set ownership given a path name.
3164  *
3165  * MPALMOSTSAFE
3166  */
3167 int
3168 sys_chown(struct chown_args *uap)
3169 {
3170         struct nlookupdata nd;
3171         int error;
3172
3173         get_mplock();
3174         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3175         if (error == 0)
3176                 error = kern_chown(&nd, uap->uid, uap->gid);
3177         nlookup_done(&nd);
3178         rel_mplock();
3179         return (error);
3180 }
3181
3182 /*
3183  * lchown_args(char *path, int uid, int gid)
3184  *
3185  * Set ownership given a path name, do not cross symlinks.
3186  *
3187  * MPALMOSTSAFE
3188  */
3189 int
3190 sys_lchown(struct lchown_args *uap)
3191 {
3192         struct nlookupdata nd;
3193         int error;
3194
3195         get_mplock();
3196         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3197         if (error == 0)
3198                 error = kern_chown(&nd, uap->uid, uap->gid);
3199         nlookup_done(&nd);
3200         rel_mplock();
3201         return (error);
3202 }
3203
3204 /*
3205  * fchown_args(int fd, int uid, int gid)
3206  *
3207  * Set ownership given a file descriptor.
3208  *
3209  * MPALMOSTSAFE
3210  */
3211 int
3212 sys_fchown(struct fchown_args *uap)
3213 {
3214         struct thread *td = curthread;
3215         struct proc *p = td->td_proc;
3216         struct file *fp;
3217         int error;
3218
3219         if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
3220                 return (error);
3221         get_mplock();
3222         if (fp->f_nchandle.ncp)
3223                 error = ncp_writechk(&fp->f_nchandle);
3224         if (error == 0)
3225                 error = setfown((struct vnode *)fp->f_data, uap->uid, uap->gid);
3226         rel_mplock();
3227         fdrop(fp);
3228         return (error);
3229 }
3230
3231 /*
3232  * fchownat(int fd, char *path, int uid, int gid, int flags)
3233  *
3234  * Set ownership of file pointed to by fd/path.
3235  *
3236  * MPALMOSTSAFE
3237  */
3238 int
3239 sys_fchownat(struct fchownat_args *uap)
3240 {
3241         struct nlookupdata nd;
3242         struct file *fp;
3243         int error;
3244         int flags;
3245
3246         if (uap->flags & ~AT_SYMLINK_NOFOLLOW)
3247                 return (EINVAL);
3248         flags = (uap->flags & AT_SYMLINK_NOFOLLOW) ? 0 : NLC_FOLLOW;
3249
3250         get_mplock();
3251         error = nlookup_init_at(&nd, &fp, uap->fd, uap->path, 
3252                                 UIO_USERSPACE, flags);
3253         if (error == 0)
3254                 error = kern_chown(&nd, uap->uid, uap->gid);
3255         nlookup_done_at(&nd, fp);
3256         rel_mplock();
3257         return (error);
3258 }
3259
3260
3261 static int
3262 getutimes(const struct timeval *tvp, struct timespec *tsp)
3263 {
3264         struct timeval tv[2];
3265
3266         if (tvp == NULL) {
3267                 microtime(&tv[0]);
3268                 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]);
3269                 tsp[1] = tsp[0];
3270         } else {
3271                 TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
3272                 TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
3273         }
3274         return 0;
3275 }
3276
3277 static int
3278 setutimes(struct vnode *vp, struct vattr *vattr,
3279           const struct timespec *ts, int nullflag)
3280 {
3281         struct thread *td = curthread;
3282         int error;
3283
3284         VATTR_NULL(vattr);
3285         vattr->va_atime = ts[0];
3286         vattr->va_mtime = ts[1];
3287         if (nullflag)
3288                 vattr->va_vaflags |= VA_UTIMES_NULL;
3289         error = VOP_SETATTR(vp, vattr, td->td_ucred);
3290
3291         return error;
3292 }
3293
3294 int
3295 kern_utimes(struct nlookupdata *nd, struct timeval *tptr)
3296 {
3297         struct timespec ts[2];
3298         struct vnode *vp;
3299         struct vattr vattr;
3300         int error;
3301
3302         if ((error = getutimes(tptr, ts)) != 0)
3303                 return (error);
3304
3305         /*
3306          * NOTE: utimes() succeeds for the owner even if the file
3307          * is not user-writable.
3308          */
3309         nd->nl_flags |= NLC_OWN | NLC_WRITE;
3310
3311         if ((error = nlookup(nd)) != 0)
3312                 return (error);
3313         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
3314                 return (error);
3315         if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
3316                 return (error);
3317
3318         /*
3319          * note: vget is required for any operation that might mod the vnode
3320          * so VINACTIVE is properly cleared.
3321          */
3322         if ((error = vn_writechk(vp, &nd->nl_nch)) == 0) {
3323                 error = vget(vp, LK_EXCLUSIVE);
3324                 if (error == 0) {
3325                         error = setutimes(vp, &vattr, ts, (tptr == NULL));
3326                         vput(vp);
3327                 }
3328         }
3329         vrele(vp);
3330         return (error);
3331 }
3332
3333 /*
3334  * utimes_args(char *path, struct timeval *tptr)
3335  *
3336  * Set the access and modification times of a file.
3337  *
3338  * MPALMOSTSAFE
3339  */
3340 int
3341 sys_utimes(struct utimes_args *uap)
3342 {
3343         struct timeval tv[2];
3344         struct nlookupdata nd;
3345         int error;
3346
3347         if (uap->tptr) {
3348                 error = copyin(uap->tptr, tv, sizeof(tv));
3349                 if (error)
3350                         return (error);
3351         }
3352         get_mplock();
3353         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3354         if (error == 0)
3355                 error = kern_utimes(&nd, uap->tptr ? tv : NULL);
3356         nlookup_done(&nd);
3357         rel_mplock();
3358         return (error);
3359 }
3360
3361 /*
3362  * lutimes_args(char *path, struct timeval *tptr)
3363  *
3364  * Set the access and modification times of a file.
3365  *
3366  * MPALMOSTSAFE
3367  */
3368 int
3369 sys_lutimes(struct lutimes_args *uap)
3370 {
3371         struct timeval tv[2];
3372         struct nlookupdata nd;
3373         int error;
3374
3375         if (uap->tptr) {
3376                 error = copyin(uap->tptr, tv, sizeof(tv));
3377                 if (error)
3378                         return (error);
3379         }
3380         get_mplock();
3381         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3382         if (error == 0)
3383                 error = kern_utimes(&nd, uap->tptr ? tv : NULL);
3384         nlookup_done(&nd);
3385         rel_mplock();
3386         return (error);
3387 }
3388
3389 /*
3390  * Set utimes on a file descriptor.  The creds used to open the
3391  * file are used to determine whether the operation is allowed
3392  * or not.
3393  */
3394 int
3395 kern_futimes(int fd, struct timeval *tptr)
3396 {
3397         struct thread *td = curthread;
3398         struct proc *p = td->td_proc;
3399         struct timespec ts[2];
3400         struct file *fp;
3401         struct vnode *vp;
3402         struct vattr vattr;
3403         int error;
3404
3405         error = getutimes(tptr, ts);
3406         if (error)
3407                 return (error);
3408         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
3409                 return (error);
3410         if (fp->f_nchandle.ncp)
3411                 error = ncp_writechk(&fp->f_nchandle);
3412         if (error == 0) {
3413                 vp = fp->f_data;
3414                 error = vget(vp, LK_EXCLUSIVE);
3415                 if (error == 0) {
3416                         error = VOP_GETATTR(vp, &vattr);
3417                         if (error == 0) {
3418                                 error = naccess_va(&vattr, NLC_OWN | NLC_WRITE,
3419                                                    fp->f_cred);
3420                         }
3421                         if (error == 0) {
3422                                 error = setutimes(vp, &vattr, ts,
3423                                                   (tptr == NULL));
3424                         }
3425                         vput(vp);
3426                 }
3427         }
3428         fdrop(fp);
3429         return (error);
3430 }
3431
3432 /*
3433  * futimes_args(int fd, struct timeval *tptr)
3434  *
3435  * Set the access and modification times of a file.
3436  *
3437  * MPALMOSTSAFE
3438  */
3439 int
3440 sys_futimes(struct futimes_args *uap)
3441 {
3442         struct timeval tv[2];
3443         int error;
3444
3445         if (uap->tptr) {
3446                 error = copyin(uap->tptr, tv, sizeof(tv));
3447                 if (error)
3448                         return (error);
3449         }
3450         get_mplock();
3451         error = kern_futimes(uap->fd, uap->tptr ? tv : NULL);
3452         rel_mplock();
3453
3454         return (error);
3455 }
3456
3457 int
3458 kern_truncate(struct nlookupdata *nd, off_t length)
3459 {
3460         struct vnode *vp;
3461         struct vattr vattr;
3462         int error;
3463
3464         if (length < 0)
3465                 return(EINVAL);
3466         nd->nl_flags |= NLC_WRITE | NLC_TRUNCATE;
3467         if ((error = nlookup(nd)) != 0)
3468                 return (error);
3469         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
3470                 return (error);
3471         if ((error = cache_vref(&nd->nl_nch, nd->nl_cred, &vp)) != 0)
3472                 return (error);
3473         if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) {
3474                 vrele(vp);
3475                 return (error);
3476         }
3477         if (vp->v_type == VDIR) {
3478                 error = EISDIR;
3479         } else if ((error = vn_writechk(vp, &nd->nl_nch)) == 0) {
3480                 VATTR_NULL(&vattr);
3481                 vattr.va_size = length;
3482                 error = VOP_SETATTR(vp, &vattr, nd->nl_cred);
3483         }
3484         vput(vp);
3485         return (error);
3486 }
3487
3488 /*
3489  * truncate(char *path, int pad, off_t length)
3490  *
3491  * Truncate a file given its path name.
3492  *
3493  * MPALMOSTSAFE
3494  */
3495 int
3496 sys_truncate(struct truncate_args *uap)
3497 {
3498         struct nlookupdata nd;
3499         int error;
3500
3501         get_mplock();
3502         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
3503         if (error == 0)
3504                 error = kern_truncate(&nd, uap->length);
3505         nlookup_done(&nd);
3506         rel_mplock();
3507         return error;
3508 }
3509
3510 int
3511 kern_ftruncate(int fd, off_t length)
3512 {
3513         struct thread *td = curthread;
3514         struct proc *p = td->td_proc;
3515         struct vattr vattr;
3516         struct vnode *vp;
3517         struct file *fp;
3518         int error;
3519
3520         if (length < 0)
3521                 return(EINVAL);
3522         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
3523                 return (error);
3524         if (fp->f_nchandle.ncp) {
3525                 error = ncp_writechk(&fp->f_nchandle);
3526                 if (error)
3527                         goto done;
3528         }
3529         if ((fp->f_flag & FWRITE) == 0) {
3530                 error = EINVAL;
3531                 goto done;
3532         }
3533         if (fp->f_flag & FAPPENDONLY) { /* inode was set s/uapnd */
3534                 error = EINVAL;
3535                 goto done;
3536         }
3537         vp = (struct vnode *)fp->f_data;
3538         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3539         if (vp->v_type == VDIR) {
3540                 error = EISDIR;
3541         } else if ((error = vn_writechk(vp, NULL)) == 0) {
3542                 VATTR_NULL(&vattr);
3543                 vattr.va_size = length;
3544                 error = VOP_SETATTR(vp, &vattr, fp->f_cred);
3545         }
3546         vn_unlock(vp);
3547 done:
3548         fdrop(fp);
3549         return (error);
3550 }
3551
3552 /*
3553  * ftruncate_args(int fd, int pad, off_t length)
3554  *
3555  * Truncate a file given a file descriptor.
3556  *
3557  * MPALMOSTSAFE
3558  */
3559 int
3560 sys_ftruncate(struct ftruncate_args *uap)
3561 {
3562         int error;
3563
3564         get_mplock();
3565         error = kern_ftruncate(uap->fd, uap->length);
3566         rel_mplock();
3567
3568         return (error);
3569 }
3570
3571 /*
3572  * fsync(int fd)
3573  *
3574  * Sync an open file.
3575  *
3576  * MPALMOSTSAFE
3577  */
3578 int
3579 sys_fsync(struct fsync_args *uap)
3580 {
3581         struct thread *td = curthread;
3582         struct proc *p = td->td_proc;
3583         struct vnode *vp;
3584         struct file *fp;
3585         vm_object_t obj;
3586         int error;
3587
3588         if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
3589                 return (error);
3590         get_mplock();
3591         vp = (struct vnode *)fp->f_data;
3592         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
3593         if ((obj = vp->v_object) != NULL)
3594                 vm_object_page_clean(obj, 0, 0, 0);
3595         error = VOP_FSYNC(vp, MNT_WAIT, VOP_FSYNC_SYSCALL);
3596         if (error == 0 && vp->v_mount)
3597                 error = buf_fsync(vp);
3598         vn_unlock(vp);
3599         rel_mplock();
3600         fdrop(fp);
3601
3602         return (error);
3603 }
3604
3605 int
3606 kern_rename(struct nlookupdata *fromnd, struct nlookupdata *tond)
3607 {
3608         struct nchandle fnchd;
3609         struct nchandle tnchd;
3610         struct namecache *ncp;
3611         struct vnode *fdvp;
3612         struct vnode *tdvp;
3613         struct mount *mp;
3614         int error;
3615
3616         bwillinode(1);
3617         fromnd->nl_flags |= NLC_REFDVP | NLC_RENAME_SRC;
3618         if ((error = nlookup(fromnd)) != 0)
3619                 return (error);
3620         if ((fnchd.ncp = fromnd->nl_nch.ncp->nc_parent) == NULL)
3621                 return (ENOENT);
3622         fnchd.mount = fromnd->nl_nch.mount;
3623         cache_hold(&fnchd);
3624
3625         /*
3626          * unlock the source nch so we can lookup the target nch without
3627          * deadlocking.  The target may or may not exist so we do not check
3628          * for a target vp like kern_mkdir() and other creation functions do.
3629          *
3630          * The source and target directories are ref'd and rechecked after
3631          * everything is relocked to determine if the source or target file
3632          * has been renamed.
3633          */
3634         KKASSERT(fromnd->nl_flags & NLC_NCPISLOCKED);
3635         fromnd->nl_flags &= ~NLC_NCPISLOCKED;
3636         cache_unlock(&fromnd->nl_nch);
3637
3638         tond->nl_flags |= NLC_RENAME_DST | NLC_REFDVP;
3639         if ((error = nlookup(tond)) != 0) {
3640                 cache_drop(&fnchd);
3641                 return (error);
3642         }
3643         if ((tnchd.ncp = tond->nl_nch.ncp->nc_parent) == NULL) {
3644                 cache_drop(&fnchd);
3645                 return (ENOENT);
3646         }
3647         tnchd.mount = tond->nl_nch.mount;
3648         cache_hold(&tnchd);
3649
3650         /*
3651          * If the source and target are the same there is nothing to do
3652          */
3653         if (fromnd->nl_nch.ncp == tond->nl_nch.ncp) {
3654                 cache_drop(&fnchd);
3655                 cache_drop(&tnchd);
3656                 return (0);
3657         }
3658
3659         /*
3660          * Mount points cannot be renamed or overwritten
3661          */
3662         if ((fromnd->nl_nch.ncp->nc_flag | tond->nl_nch.ncp->nc_flag) &
3663             NCF_ISMOUNTPT
3664         ) {
3665                 cache_drop(&fnchd);
3666                 cache_drop(&tnchd);
3667                 return (EINVAL);
3668         }
3669
3670         /*
3671          * Relock the source ncp.  cache_relock() will deal with any
3672          * deadlocks against the already-locked tond and will also
3673          * make sure both are resolved.
3674          *
3675          * NOTE AFTER RELOCKING: The source or target ncp may have become
3676          * invalid while they were unlocked, nc_vp and nc_mount could
3677          * be NULL.
3678          */
3679         cache_relock(&fromnd->nl_nch, fromnd->nl_cred,
3680                      &tond->nl_nch, tond->nl_cred);
3681         fromnd->nl_flags |= NLC_NCPISLOCKED;
3682
3683         /*
3684          * make sure the parent directories linkages are the same
3685          */
3686         if (fnchd.ncp != fromnd->nl_nch.ncp->nc_parent ||
3687             tnchd.ncp != tond->nl_nch.ncp->nc_parent) {
3688                 cache_drop(&fnchd);
3689                 cache_drop(&tnchd);
3690                 return (ENOENT);
3691         }
3692
3693         /*
3694          * Both the source and target must be within the same filesystem and
3695          * in the same filesystem as their parent directories within the
3696          * namecache topology.
3697          *
3698          * NOTE: fromnd's nc_mount or nc_vp could be NULL.
3699          */
3700         mp = fnchd.mount;
3701         if (mp != tnchd.mount || mp != fromnd->nl_nch.mount ||
3702             mp != tond->nl_nch.mount) {
3703                 cache_drop(&fnchd);
3704                 cache_drop(&tnchd);
3705                 return (EXDEV);
3706         }
3707
3708         /*
3709          * Make sure the mount point is writable
3710          */
3711         if ((error = ncp_writechk(&tond->nl_nch)) != 0) {
3712                 cache_drop(&fnchd);
3713                 cache_drop(&tnchd);
3714                 return (error);
3715         }
3716
3717         /*
3718          * If the target exists and either the source or target is a directory,
3719          * then both must be directories.
3720          *
3721          * Due to relocking of the source, fromnd->nl_nch.ncp->nc_vp might h
3722          * have become NULL.
3723          */
3724         if (tond->nl_nch.ncp->nc_vp) {
3725                 if (fromnd->nl_nch.ncp->nc_vp == NULL) {
3726                         error = ENOENT;
3727                 } else if (fromnd->nl_nch.ncp->nc_vp->v_type == VDIR) {
3728                         if (tond->nl_nch.ncp->nc_vp->v_type != VDIR)
3729                                 error = ENOTDIR;
3730                 } else if (tond->nl_nch.ncp->nc_vp->v_type == VDIR) {
3731                         error = EISDIR;
3732                 }
3733         }
3734
3735         /*
3736          * You cannot rename a source into itself or a subdirectory of itself.
3737          * We check this by travsersing the target directory upwards looking
3738          * for a match against the source.
3739          *
3740          * XXX MPSAFE
3741          */
3742         if (error == 0) {
3743                 for (ncp = tnchd.ncp; ncp; ncp = ncp->nc_parent) {
3744                         if (fromnd->nl_nch.ncp == ncp) {
3745                                 error = EINVAL;
3746                                 break;
3747                         }
3748                 }
3749         }
3750
3751         cache_drop(&fnchd);
3752         cache_drop(&tnchd);
3753
3754         /*
3755          * Even though the namespaces are different, they may still represent
3756          * hardlinks to the same file.  The filesystem might have a hard time
3757          * with this so we issue a NREMOVE of the source instead of a NRENAME
3758          * when we detect the situation.
3759          */
3760         if (error == 0) {
3761                 fdvp = fromnd->nl_dvp;
3762                 tdvp = tond->nl_dvp;
3763                 if (fdvp == NULL || tdvp == NULL) {
3764                         error = EPERM;
3765                 } else if (fromnd->nl_nch.ncp->nc_vp == tond->nl_nch.ncp->nc_vp) {
3766                         error = VOP_NREMOVE(&fromnd->nl_nch, fdvp,
3767                                             fromnd->nl_cred);
3768                 } else {
3769                         error = VOP_NRENAME(&fromnd->nl_nch, &tond->nl_nch, 
3770                                             fdvp, tdvp, tond->nl_cred);
3771                 }
3772         }
3773         return (error);
3774 }
3775
3776 /*
3777  * rename_args(char *from, char *to)
3778  *
3779  * Rename files.  Source and destination must either both be directories,
3780  * or both not be directories.  If target is a directory, it must be empty.
3781  *
3782  * MPALMOSTSAFE
3783  */
3784 int
3785 sys_rename(struct rename_args *uap)
3786 {
3787         struct nlookupdata fromnd, tond;
3788         int error;
3789
3790         get_mplock();
3791         error = nlookup_init(&fromnd, uap->from, UIO_USERSPACE, 0);
3792         if (error == 0) {
3793                 error = nlookup_init(&tond, uap->to, UIO_USERSPACE, 0);
3794                 if (error == 0)
3795                         error = kern_rename(&fromnd, &tond);
3796                 nlookup_done(&tond);
3797         }
3798         nlookup_done(&fromnd);
3799         rel_mplock();
3800         return (error);
3801 }
3802
3803 int
3804 kern_mkdir(struct nlookupdata *nd, int mode)
3805 {
3806         struct thread *td = curthread;
3807         struct proc *p = td->td_proc;
3808         struct vnode *vp;
3809         struct vattr vattr;
3810         int error;
3811
3812         bwillinode(1);
3813         nd->nl_flags |= NLC_WILLBEDIR | NLC_CREATE | NLC_REFDVP;
3814         if ((error = nlookup(nd)) != 0)
3815                 return (error);
3816
3817         if (nd->nl_nch.ncp->nc_vp)
3818                 return (EEXIST);
3819         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
3820                 return (error);
3821         VATTR_NULL(&vattr);
3822         vattr.va_type = VDIR;
3823         vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;
3824
3825         vp = NULL;
3826         error = VOP_NMKDIR(&nd->nl_nch, nd->nl_dvp, &vp, td->td_ucred, &vattr);
3827         if (error == 0)
3828                 vput(vp);
3829         return (error);
3830 }
3831
3832 /*
3833  * mkdir_args(char *path, int mode)
3834  *
3835  * Make a directory file.
3836  *
3837  * MPALMOSTSAFE
3838  */
3839 int
3840 sys_mkdir(struct mkdir_args *uap)
3841 {
3842         struct nlookupdata nd;
3843         int error;
3844
3845         get_mplock();
3846         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3847         if (error == 0)
3848                 error = kern_mkdir(&nd, uap->mode);
3849         nlookup_done(&nd);
3850         rel_mplock();
3851         return (error);
3852 }
3853
3854 int
3855 kern_rmdir(struct nlookupdata *nd)
3856 {
3857         int error;
3858
3859         bwillinode(1);
3860         nd->nl_flags |= NLC_DELETE | NLC_REFDVP;
3861         if ((error = nlookup(nd)) != 0)
3862                 return (error);
3863
3864         /*
3865          * Do not allow directories representing mount points to be
3866          * deleted, even if empty.  Check write perms on mount point
3867          * in case the vnode is aliased (aka nullfs).
3868          */
3869         if (nd->nl_nch.ncp->nc_flag & (NCF_ISMOUNTPT))
3870                 return (EINVAL);
3871         if ((error = ncp_writechk(&nd->nl_nch)) != 0)
3872                 return (error);
3873         error = VOP_NRMDIR(&nd->nl_nch, nd->nl_dvp, nd->nl_cred);
3874         return (error);
3875 }
3876
3877 /*
3878  * rmdir_args(char *path)
3879  *
3880  * Remove a directory file.
3881  *
3882  * MPALMOSTSAFE
3883  */
3884 int
3885 sys_rmdir(struct rmdir_args *uap)
3886 {
3887         struct nlookupdata nd;
3888         int error;
3889
3890         get_mplock();
3891         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
3892         if (error == 0)
3893                 error = kern_rmdir(&nd);
3894         nlookup_done(&nd);
3895         rel_mplock();
3896         return (error);
3897 }
3898
3899 int
3900 kern_getdirentries(int fd, char *buf, u_int count, long *basep, int *res,
3901     enum uio_seg direction)
3902 {
3903         struct thread *td = curthread;
3904         struct proc *p = td->td_proc;
3905         struct vnode *vp;
3906         struct file *fp;
3907         struct uio auio;
3908         struct iovec aiov;
3909         off_t loff;
3910         int error, eofflag;
3911
3912         if ((error = holdvnode(p->p_fd, fd, &fp)) != 0)
3913                 return (error);
3914         if ((fp->f_flag & FREAD) == 0) {
3915                 error = EBADF;
3916                 goto done;
3917         }
3918         vp = (struct vnode *)fp->f_data;
3919 unionread:
3920         if (vp->v_type != VDIR) {
3921                 error = EINVAL;
3922                 goto done;
3923         }
3924         aiov.iov_base = buf;
3925         aiov.iov_len = count;
3926         auio.uio_iov = &aiov;
3927         auio.uio_iovcnt = 1;
3928         auio.uio_rw = UIO_READ;
3929         auio.uio_segflg = direction;
3930         auio.uio_td = td;
3931         auio.uio_resid = count;
3932         loff = auio.uio_offset = fp->f_offset;
3933         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
3934         fp->f_offset = auio.uio_offset;
3935         if (error)
3936                 goto done;
3937         if (count == auio.uio_resid) {
3938                 if (union_dircheckp) {
3939                         error = union_dircheckp(td, &vp, fp);
3940                         if (error == -1)
3941                                 goto unionread;
3942                         if (error)
3943                                 goto done;
3944                 }
3945 #if 0
3946                 if ((vp->v_flag & VROOT) &&
3947                     (vp->v_mount->mnt_flag & MNT_UNION)) {
3948                         struct vnode *tvp = vp;
3949                         vp = vp->v_mount->mnt_vnodecovered;
3950                         vref(vp);
3951                         fp->f_data = vp;
3952                         fp->f_offset = 0;
3953                         vrele(tvp);
3954                         goto unionread;
3955                 }
3956 #endif
3957         }
3958
3959         /*
3960          * WARNING!  *basep may not be wide enough to accomodate the
3961          * seek offset.   XXX should we hack this to return the upper 32 bits
3962          * for offsets greater then 4G?
3963          */
3964         if (basep) {
3965                 *basep = (long)loff;
3966         }
3967         *res = count - auio.uio_resid;
3968 done:
3969         fdrop(fp);
3970         return (error);
3971 }
3972
3973 /*
3974  * getdirentries_args(int fd, char *buf, u_int conut, long *basep)
3975  *
3976  * Read a block of directory entries in a file system independent format.
3977  *
3978  * MPALMOSTSAFE
3979  */
3980 int
3981 sys_getdirentries(struct getdirentries_args *uap)
3982 {
3983         long base;
3984         int error;
3985
3986         get_mplock();
3987         error = kern_getdirentries(uap->fd, uap->buf, uap->count, &base,
3988                                    &uap->sysmsg_result, UIO_USERSPACE);
3989         rel_mplock();
3990
3991         if (error == 0 && uap->basep)
3992                 error = copyout(&base, uap->basep, sizeof(*uap->basep));
3993         return (error);
3994 }
3995
3996 /*
3997  * getdents_args(int fd, char *buf, size_t count)
3998  *
3999  * MPALMOSTSAFE
4000  */
4001 int
4002 sys_getdents(struct getdents_args *uap)
4003 {
4004         int error;
4005
4006         get_mplock();
4007         error = kern_getdirentries(uap->fd, uap->buf, uap->count, NULL,
4008                                    &uap->sysmsg_result, UIO_USERSPACE);
4009         rel_mplock();
4010
4011         return (error);
4012 }
4013
4014 /*
4015  * Set the mode mask for creation of filesystem nodes.
4016  *
4017  * umask(int newmask)
4018  *
4019  * MPSAFE
4020  */
4021 int
4022 sys_umask(struct umask_args *uap)
4023 {
4024         struct thread *td = curthread;
4025         struct proc *p = td->td_proc;
4026         struct filedesc *fdp;
4027
4028         fdp = p->p_fd;
4029         uap->sysmsg_result = fdp->fd_cmask;
4030         fdp->fd_cmask = uap->newmask & ALLPERMS;
4031         return (0);
4032 }
4033
4034 /*
4035  * revoke(char *path)
4036  *
4037  * Void all references to file by ripping underlying filesystem
4038  * away from vnode.
4039  *
4040  * MPALMOSTSAFE
4041  */
4042 int
4043 sys_revoke(struct revoke_args *uap)
4044 {
4045         struct nlookupdata nd;
4046         struct vattr vattr;
4047         struct vnode *vp;
4048         struct ucred *cred;
4049         int error;
4050
4051         vp = NULL;
4052         get_mplock();
4053         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4054         if (error == 0)
4055                 error = nlookup(&nd);
4056         if (error == 0)
4057                 error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
4058         cred = crhold(nd.nl_cred);
4059         nlookup_done(&nd);
4060         if (error == 0) {
4061                 if (error == 0)
4062                         error = VOP_GETATTR(vp, &vattr);
4063                 if (error == 0 && cred->cr_uid != vattr.va_uid)
4064                         error = priv_check_cred(cred, PRIV_VFS_REVOKE, 0);
4065                 if (error == 0 && (vp->v_type == VCHR || vp->v_type == VBLK)) {
4066                         if (vcount(vp) > 0)
4067                                 error = vrevoke(vp, cred);
4068                 } else if (error == 0) {
4069                         error = vrevoke(vp, cred);
4070                 }
4071                 vrele(vp);
4072         }
4073         if (cred)
4074                 crfree(cred);
4075         rel_mplock();
4076         return (error);
4077 }
4078
4079 /*
4080  * getfh_args(char *fname, fhandle_t *fhp)
4081  *
4082  * Get (NFS) file handle
4083  *
4084  * NOTE: We use the fsid of the covering mount, even if it is a nullfs
4085  * mount.  This allows nullfs mounts to be explicitly exported. 
4086  *
4087  * WARNING: nullfs mounts of HAMMER PFS ROOTs are safe.
4088  *
4089  *          nullfs mounts of subdirectories are not safe.  That is, it will
4090  *          work, but you do not really have protection against access to
4091  *          the related parent directories.
4092  *
4093  * MPALMOSTSAFE
4094  */
4095 int
4096 sys_getfh(struct getfh_args *uap)
4097 {
4098         struct thread *td = curthread;
4099         struct nlookupdata nd;
4100         fhandle_t fh;
4101         struct vnode *vp;
4102         struct mount *mp;
4103         int error;
4104
4105         /*
4106          * Must be super user
4107          */
4108         if ((error = priv_check(td, PRIV_ROOT)) != 0)
4109                 return (error);
4110
4111         vp = NULL;
4112         get_mplock();
4113         error = nlookup_init(&nd, uap->fname, UIO_USERSPACE, NLC_FOLLOW);
4114         if (error == 0)
4115                 error = nlookup(&nd);
4116         if (error == 0)
4117                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
4118         mp = nd.nl_nch.mount;
4119         nlookup_done(&nd);
4120         if (error == 0) {
4121                 bzero(&fh, sizeof(fh));
4122                 fh.fh_fsid = mp->mnt_stat.f_fsid;
4123                 error = VFS_VPTOFH(vp, &fh.fh_fid);
4124                 vput(vp);
4125                 if (error == 0)
4126                         error = copyout(&fh, uap->fhp, sizeof(fh));
4127         }
4128         rel_mplock();
4129         return (error);
4130 }
4131
4132 /*
4133  * fhopen_args(const struct fhandle *u_fhp, int flags)
4134  *
4135  * syscall for the rpc.lockd to use to translate a NFS file handle into
4136  * an open descriptor.
4137  *
4138  * warning: do not remove the priv_check() call or this becomes one giant
4139  * security hole.
4140  *
4141  * MPALMOSTSAFE
4142  */
4143 int
4144 sys_fhopen(struct fhopen_args *uap)
4145 {
4146         struct thread *td = curthread;
4147         struct filedesc *fdp = td->td_proc->p_fd;
4148         struct mount *mp;
4149         struct vnode *vp;
4150         struct fhandle fhp;
4151         struct vattr vat;
4152         struct vattr *vap = &vat;
4153         struct flock lf;
4154         int fmode, mode, error, type;
4155         struct file *nfp; 
4156         struct file *fp;
4157         int indx;
4158
4159         /*
4160          * Must be super user
4161          */
4162         error = priv_check(td, PRIV_ROOT);
4163         if (error)
4164                 return (error);
4165
4166         fmode = FFLAGS(uap->flags);
4167
4168         /*
4169          * Why not allow a non-read/write open for our lockd?
4170          */
4171         if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
4172                 return (EINVAL);
4173         error = copyin(uap->u_fhp, &fhp, sizeof(fhp));
4174         if (error)
4175                 return(error);
4176
4177         /*
4178          * Find the mount point
4179          */
4180         get_mplock();
4181         mp = vfs_getvfs(&fhp.fh_fsid);
4182         if (mp == NULL) {
4183                 error = ESTALE;
4184                 goto  done;
4185         }
4186         /* now give me my vnode, it gets returned to me locked */
4187         error = VFS_FHTOVP(mp, NULL, &fhp.fh_fid, &vp);
4188         if (error)
4189                 goto done;
4190         /*
4191          * from now on we have to make sure not
4192          * to forget about the vnode
4193          * any error that causes an abort must vput(vp) 
4194          * just set error = err and 'goto bad;'.
4195          */
4196
4197         /* 
4198          * from vn_open 
4199          */
4200         if (vp->v_type == VLNK) {
4201                 error = EMLINK;
4202                 goto bad;
4203         }
4204         if (vp->v_type == VSOCK) {
4205                 error = EOPNOTSUPP;
4206                 goto bad;
4207         }
4208         mode = 0;
4209         if (fmode & (FWRITE | O_TRUNC)) {
4210                 if (vp->v_type == VDIR) {
4211                         error = EISDIR;
4212                         goto bad;
4213                 }
4214                 error = vn_writechk(vp, NULL);
4215                 if (error)
4216                         goto bad;
4217                 mode |= VWRITE;
4218         }
4219         if (fmode & FREAD)
4220                 mode |= VREAD;
4221         if (mode) {
4222                 error = VOP_ACCESS(vp, mode, td->td_ucred);
4223                 if (error)
4224                         goto bad;
4225         }
4226         if (fmode & O_TRUNC) {
4227                 vn_unlock(vp);                          /* XXX */
4228                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);   /* XXX */
4229                 VATTR_NULL(vap);
4230                 vap->va_size = 0;
4231                 error = VOP_SETATTR(vp, vap, td->td_ucred);
4232                 if (error)
4233                         goto bad;
4234         }
4235
4236         /*
4237          * VOP_OPEN needs the file pointer so it can potentially override
4238          * it.
4239          *
4240          * WARNING! no f_nchandle will be associated when fhopen()ing a
4241          * directory.  XXX
4242          */
4243         if ((error = falloc(td->td_lwp, &nfp, &indx)) != 0)
4244                 goto bad;
4245         fp = nfp;
4246
4247         error = VOP_OPEN(vp, fmode, td->td_ucred, fp);
4248         if (error) {
4249                 /*
4250                  * setting f_ops this way prevents VOP_CLOSE from being
4251                  * called or fdrop() releasing the vp from v_data.   Since
4252                  * the VOP_OPEN failed we don't want to VOP_CLOSE.
4253                  */
4254                 fp->f_ops = &badfileops;
4255                 fp->f_data = NULL;
4256                 goto bad_drop;
4257         }
4258
4259         /*
4260          * The fp is given its own reference, we still have our ref and lock.
4261          *
4262          * Assert that all regular files must be created with a VM object.
4263          */
4264         if (vp->v_type == VREG && vp->v_object == NULL) {
4265                 kprintf("fhopen: regular file did not have VM object: %p\n", vp);
4266                 goto bad_drop;
4267         }
4268
4269         /*
4270          * The open was successful.  Handle any locking requirements.
4271          */
4272         if (fmode & (O_EXLOCK | O_SHLOCK)) {
4273                 lf.l_whence = SEEK_SET;
4274                 lf.l_start = 0;
4275                 lf.l_len = 0;
4276                 if (fmode & O_EXLOCK)
4277                         lf.l_type = F_WRLCK;
4278                 else
4279                         lf.l_type = F_RDLCK;
4280                 if (fmode & FNONBLOCK)
4281                         type = 0;
4282                 else
4283                         type = F_WAIT;
4284                 vn_unlock(vp);
4285                 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
4286                         /*
4287                          * release our private reference.
4288                          */
4289                         fsetfd(fdp, NULL, indx);
4290                         fdrop(fp);
4291                         vrele(vp);
4292                         goto done;
4293                 }
4294                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
4295                 fp->f_flag |= FHASLOCK;
4296         }
4297
4298         /*
4299          * Clean up.  Associate the file pointer with the previously
4300          * reserved descriptor and return it.
4301          */
4302         vput(vp);
4303         rel_mplock();
4304         fsetfd(fdp, fp, indx);
4305         fdrop(fp);
4306         uap->sysmsg_result = indx;
4307         return (0);
4308
4309 bad_drop:
4310         fsetfd(fdp, NULL, indx);
4311         fdrop(fp);
4312 bad:
4313         vput(vp);
4314 done:
4315         rel_mplock();
4316         return (error);
4317 }
4318
4319 /*
4320  * fhstat_args(struct fhandle *u_fhp, struct stat *sb)
4321  *
4322  * MPALMOSTSAFE
4323  */
4324 int
4325 sys_fhstat(struct fhstat_args *uap)
4326 {
4327         struct thread *td = curthread;
4328         struct stat sb;
4329         fhandle_t fh;
4330         struct mount *mp;
4331         struct vnode *vp;
4332         int error;
4333
4334         /*
4335          * Must be super user
4336          */
4337         error = priv_check(td, PRIV_ROOT);
4338         if (error)
4339                 return (error);
4340         
4341         error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
4342         if (error)
4343                 return (error);
4344
4345         get_mplock();
4346         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
4347                 error = ESTALE;
4348         if (error == 0) {
4349                 if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp)) == 0) {
4350                         error = vn_stat(vp, &sb, td->td_ucred);
4351                         vput(vp);
4352                 }
4353         }
4354         rel_mplock();
4355         if (error == 0)
4356                 error = copyout(&sb, uap->sb, sizeof(sb));
4357         return (error);
4358 }
4359
4360 /*
4361  * fhstatfs_args(struct fhandle *u_fhp, struct statfs *buf)
4362  *
4363  * MPALMOSTSAFE
4364  */
4365 int
4366 sys_fhstatfs(struct fhstatfs_args *uap)
4367 {
4368         struct thread *td = curthread;
4369         struct proc *p = td->td_proc;
4370         struct statfs *sp;
4371         struct mount *mp;
4372         struct vnode *vp;
4373         struct statfs sb;
4374         char *fullpath, *freepath;
4375         fhandle_t fh;
4376         int error;
4377
4378         /*
4379          * Must be super user
4380          */
4381         if ((error = priv_check(td, PRIV_ROOT)))
4382                 return (error);
4383
4384         if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
4385                 return (error);
4386
4387         get_mplock();
4388
4389         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
4390                 error = ESTALE;
4391                 goto done;
4392         }
4393         if (p != NULL && !chroot_visible_mnt(mp, p)) {
4394                 error = ESTALE;
4395                 goto done;
4396         }
4397
4398         if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp)) != 0)
4399                 goto done;
4400         mp = vp->v_mount;
4401         sp = &mp->mnt_stat;
4402         vput(vp);
4403         if ((error = VFS_STATFS(mp, sp, td->td_ucred)) != 0)
4404                 goto done;
4405
4406         error = mount_path(p, mp, &fullpath, &freepath);
4407         if (error)
4408                 goto done;
4409         bzero(sp->f_mntonname, sizeof(sp->f_mntonname));
4410         strlcpy(sp->f_mntonname, fullpath, sizeof(sp->f_mntonname));
4411         kfree(freepath, M_TEMP);
4412
4413         sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
4414         if (priv_check(td, PRIV_ROOT)) {
4415                 bcopy(sp, &sb, sizeof(sb));
4416                 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
4417                 sp = &sb;
4418         }
4419         error = copyout(sp, uap->buf, sizeof(*sp));
4420 done:
4421         rel_mplock();
4422         return (error);
4423 }
4424
4425 /*
4426  * fhstatvfs_args(struct fhandle *u_fhp, struct statvfs *buf)
4427  *
4428  * MPALMOSTSAFE
4429  */
4430 int
4431 sys_fhstatvfs(struct fhstatvfs_args *uap)
4432 {
4433         struct thread *td = curthread;
4434         struct proc *p = td->td_proc;
4435         struct statvfs *sp;
4436         struct mount *mp;
4437         struct vnode *vp;
4438         fhandle_t fh;
4439         int error;
4440
4441         /*
4442          * Must be super user
4443          */
4444         if ((error = priv_check(td, PRIV_ROOT)))
4445                 return (error);
4446
4447         if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
4448                 return (error);
4449
4450         get_mplock();
4451
4452         if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
4453                 error = ESTALE;
4454                 goto done;
4455         }
4456         if (p != NULL && !chroot_visible_mnt(mp, p)) {
4457                 error = ESTALE;
4458                 goto done;
4459         }
4460
4461         if ((error = VFS_FHTOVP(mp, NULL, &fh.fh_fid, &vp)))
4462                 goto done;
4463         mp = vp->v_mount;
4464         sp = &mp->mnt_vstat;
4465         vput(vp);
4466         if ((error = VFS_STATVFS(mp, sp, td->td_ucred)) != 0)
4467                 goto done;
4468
4469         sp->f_flag = 0;
4470         if (mp->mnt_flag & MNT_RDONLY)
4471                 sp->f_flag |= ST_RDONLY;
4472         if (mp->mnt_flag & MNT_NOSUID)
4473                 sp->f_flag |= ST_NOSUID;
4474         error = copyout(sp, uap->buf, sizeof(*sp));
4475 done:
4476         rel_mplock();
4477         return (error);
4478 }
4479
4480
4481 /*
4482  * Syscall to push extended attribute configuration information into the
4483  * VFS.  Accepts a path, which it converts to a mountpoint, as well as
4484  * a command (int cmd), and attribute name and misc data.  For now, the
4485  * attribute name is left in userspace for consumption by the VFS_op.
4486  * It will probably be changed to be copied into sysspace by the
4487  * syscall in the future, once issues with various consumers of the
4488  * attribute code have raised their hands.
4489  *
4490  * Currently this is used only by UFS Extended Attributes.
4491  *
4492  * MPALMOSTSAFE
4493  */
4494 int
4495 sys_extattrctl(struct extattrctl_args *uap)
4496 {
4497         struct nlookupdata nd;
4498         struct vnode *vp;
4499         char attrname[EXTATTR_MAXNAMELEN];
4500         int error;
4501         size_t size;
4502
4503         get_mplock();
4504
4505         attrname[0] = 0;
4506         vp = NULL;
4507         error = 0;
4508
4509         if (error == 0 && uap->filename) {
4510                 error = nlookup_init(&nd, uap->filename, UIO_USERSPACE,
4511                                      NLC_FOLLOW);
4512                 if (error == 0)
4513                         error = nlookup(&nd);
4514                 if (error == 0)
4515                         error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
4516                 nlookup_done(&nd);
4517         }
4518
4519         if (error == 0 && uap->attrname) {
4520                 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
4521                                   &size);
4522         }
4523
4524         if (error == 0) {
4525                 error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4526                 if (error == 0)
4527                         error = nlookup(&nd);
4528                 if (error == 0)
4529                         error = ncp_writechk(&nd.nl_nch);
4530                 if (error == 0) {
4531                         error = VFS_EXTATTRCTL(nd.nl_nch.mount, uap->cmd, vp,
4532                                                uap->attrnamespace,
4533                                                uap->attrname, nd.nl_cred);
4534                 }
4535                 nlookup_done(&nd);
4536         }
4537
4538         rel_mplock();
4539
4540         return (error);
4541 }
4542
4543 /*
4544  * Syscall to get a named extended attribute on a file or directory.
4545  *
4546  * MPALMOSTSAFE
4547  */
4548 int
4549 sys_extattr_set_file(struct extattr_set_file_args *uap)
4550 {
4551         char attrname[EXTATTR_MAXNAMELEN];
4552         struct nlookupdata nd;
4553         struct vnode *vp;
4554         struct uio auio;
4555         struct iovec aiov;
4556         int error;
4557
4558         error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN);
4559         if (error)
4560                 return (error);
4561
4562         vp = NULL;
4563         get_mplock();
4564
4565         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4566         if (error == 0)
4567                 error = nlookup(&nd);
4568         if (error == 0)
4569                 error = ncp_writechk(&nd.nl_nch);
4570         if (error == 0)
4571                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
4572         if (error) {
4573                 nlookup_done(&nd);
4574                 rel_mplock();
4575                 return (error);
4576         }
4577
4578         bzero(&auio, sizeof(auio));
4579         aiov.iov_base = uap->data;
4580         aiov.iov_len = uap->nbytes;
4581         auio.uio_iov = &aiov;
4582         auio.uio_iovcnt = 1;
4583         auio.uio_offset = 0;
4584         auio.uio_resid = uap->nbytes;
4585         auio.uio_rw = UIO_WRITE;
4586         auio.uio_td = curthread;
4587
4588         error = VOP_SETEXTATTR(vp, uap->attrnamespace, attrname,
4589                                &auio, nd.nl_cred);
4590
4591         vput(vp);
4592         nlookup_done(&nd);
4593         rel_mplock();
4594         return (error);
4595 }
4596
4597 /*
4598  * Syscall to get a named extended attribute on a file or directory.
4599  *
4600  * MPALMOSTSAFE
4601  */
4602 int
4603 sys_extattr_get_file(struct extattr_get_file_args *uap)
4604 {
4605         char attrname[EXTATTR_MAXNAMELEN];
4606         struct nlookupdata nd;
4607         struct uio auio;
4608         struct iovec aiov;
4609         struct vnode *vp;
4610         int error;
4611
4612         error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN);
4613         if (error)
4614                 return (error);
4615
4616         vp = NULL;
4617         get_mplock();
4618
4619         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4620         if (error == 0)
4621                 error = nlookup(&nd);
4622         if (error == 0)
4623                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
4624         if (error) {
4625                 nlookup_done(&nd);
4626                 rel_mplock();
4627                 return (error);
4628         }
4629
4630         bzero(&auio, sizeof(auio));
4631         aiov.iov_base = uap->data;
4632         aiov.iov_len = uap->nbytes;
4633         auio.uio_iov = &aiov;
4634         auio.uio_iovcnt = 1;
4635         auio.uio_offset = 0;
4636         auio.uio_resid = uap->nbytes;
4637         auio.uio_rw = UIO_READ;
4638         auio.uio_td = curthread;
4639
4640         error = VOP_GETEXTATTR(vp, uap->attrnamespace, attrname,
4641                                 &auio, nd.nl_cred);
4642         uap->sysmsg_result = uap->nbytes - auio.uio_resid;
4643
4644         vput(vp);
4645         nlookup_done(&nd);
4646         rel_mplock();
4647         return(error);
4648 }
4649
4650 /*
4651  * Syscall to delete a named extended attribute from a file or directory.
4652  * Accepts attribute name.  The real work happens in VOP_SETEXTATTR().
4653  *
4654  * MPALMOSTSAFE
4655  */
4656 int
4657 sys_extattr_delete_file(struct extattr_delete_file_args *uap)
4658 {
4659         char attrname[EXTATTR_MAXNAMELEN];
4660         struct nlookupdata nd;
4661         struct vnode *vp;
4662         int error;
4663
4664         error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN);
4665         if (error)
4666                 return(error);
4667
4668         get_mplock();
4669         error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW);
4670         if (error == 0)
4671                 error = nlookup(&nd);
4672         if (error == 0)
4673                 error = ncp_writechk(&nd.nl_nch);
4674         if (error == 0) {
4675                 error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp);
4676                 if (error == 0) {
4677                         error = VOP_SETEXTATTR(vp, uap->attrnamespace,
4678                                                attrname, NULL, nd.nl_cred);
4679                         vput(vp);
4680                 }
4681         }
4682         nlookup_done(&nd);
4683         rel_mplock();
4684         return(error);
4685 }
4686
4687 /*
4688  * Determine if the mount is visible to the process.
4689  */
4690 static int
4691 chroot_visible_mnt(struct mount *mp, struct proc *p)
4692 {
4693         struct nchandle nch;
4694
4695         /*
4696          * Traverse from the mount point upwards.  If we hit the process
4697          * root then the mount point is visible to the process.
4698          */
4699         nch = mp->mnt_ncmountpt;
4700         while (nch.ncp) {
4701                 if (nch.mount == p->p_fd->fd_nrdir.mount &&
4702                     nch.ncp == p->p_fd->fd_nrdir.ncp) {
4703                         return(1);
4704                 }
4705                 if (nch.ncp == nch.mount->mnt_ncmountpt.ncp) {
4706                         nch = nch.mount->mnt_ncmounton;
4707                 } else {
4708                         nch.ncp = nch.ncp->nc_parent;
4709                 }
4710         }
4711
4712         /*
4713          * If the mount point is not visible to the process, but the
4714          * process root is in a subdirectory of the mount, return
4715          * TRUE anyway.
4716          */
4717         if (p->p_fd->fd_nrdir.mount == mp)
4718                 return(1);
4719
4720         return(0);
4721 }
4722