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