MFC: fstest regression fixes - POSIX error codes.
[dragonfly.git] / sys / kern / vfs_nlookup.c
1 /*
2  * Copyright (c) 2004 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  * 
34  * $DragonFly: src/sys/kern/vfs_nlookup.c,v 1.25 2008/07/19 04:43:33 dillon Exp $
35  */
36 /*
37  * nlookup() is the 'new' namei interface.  Rather then return directory and
38  * leaf vnodes (in various lock states) the new interface instead deals in
39  * namecache records.  Namecache records may represent both a positive or
40  * a negative hit.  The namespace is locked via the namecache record instead
41  * of via the vnode, and only the leaf namecache record (representing the
42  * filename) needs to be locked.
43  *
44  * This greatly improves filesystem parallelism and is a huge simplification
45  * of the API verses the old vnode locking / namei scheme.
46  *
47  * Filesystems must actively control the caching aspects of the namecache,
48  * and since namecache pointers are used as handles they are non-optional
49  * even for filesystems which do not generally wish to cache things.  It is
50  * intended that a separate cache coherency API will be constructed to handle
51  * these issues.
52  */
53
54 #include "opt_ktrace.h"
55
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/kernel.h>
59 #include <sys/vnode.h>
60 #include <sys/mount.h>
61 #include <sys/filedesc.h>
62 #include <sys/proc.h>
63 #include <sys/namei.h>
64 #include <sys/nlookup.h>
65 #include <sys/malloc.h>
66 #include <sys/stat.h>
67 #include <sys/objcache.h>
68
69 #ifdef KTRACE
70 #include <sys/ktrace.h>
71 #endif
72
73 static int naccess_va(struct vattr *va, int vmode, struct ucred *cred);
74
75 /*
76  * Initialize a nlookup() structure, early error return for copyin faults
77  * or a degenerate empty string (which is not allowed).
78  *
79  * The first process proc0's credentials are used if the calling thread
80  * is not associated with a process context.
81  */
82 int
83 nlookup_init(struct nlookupdata *nd, 
84              const char *path, enum uio_seg seg, int flags)
85 {
86     size_t pathlen;
87     struct proc *p;
88     thread_t td;
89     int error;
90
91     td = curthread;
92     p = td->td_proc;
93
94     /*
95      * note: the pathlen set by copy*str() includes the terminating \0.
96      */
97     bzero(nd, sizeof(struct nlookupdata));
98     nd->nl_path = objcache_get(namei_oc, M_WAITOK);
99     nd->nl_flags |= NLC_HASBUF;
100     if (seg == UIO_SYSSPACE) 
101         error = copystr(path, nd->nl_path, MAXPATHLEN, &pathlen);
102     else
103         error = copyinstr(path, nd->nl_path, MAXPATHLEN, &pathlen);
104
105     /*
106      * Don't allow empty pathnames.
107      * POSIX.1 requirement: "" is not a vaild file name.
108      */
109     if (error == 0 && pathlen <= 1)
110         error = ENOENT;
111
112     if (error == 0) {
113         if (p && p->p_fd) {
114             cache_copy(&p->p_fd->fd_ncdir, &nd->nl_nch);
115             cache_copy(&p->p_fd->fd_nrdir, &nd->nl_rootnch);
116             if (p->p_fd->fd_njdir.ncp)
117                 cache_copy(&p->p_fd->fd_njdir, &nd->nl_jailnch);
118             nd->nl_cred = crhold(p->p_ucred);
119         } else {
120             cache_copy(&rootnch, &nd->nl_nch);
121             cache_copy(&nd->nl_nch, &nd->nl_rootnch);
122             cache_copy(&nd->nl_nch, &nd->nl_jailnch);
123             nd->nl_cred = crhold(proc0.p_ucred);
124         }
125         nd->nl_td = td;
126         nd->nl_flags |= flags;
127     } else {
128         nlookup_done(nd);
129     }
130     return(error);
131 }
132
133 /*
134  * This works similarly to nlookup_init() but does not assume a process
135  * context.  rootnch is always chosen for the root directory and the cred
136  * and starting directory are supplied in arguments.
137  */
138 int
139 nlookup_init_raw(struct nlookupdata *nd, 
140              const char *path, enum uio_seg seg, int flags,
141              struct ucred *cred, struct nchandle *ncstart)
142 {
143     size_t pathlen;
144     thread_t td;
145     int error;
146
147     td = curthread;
148
149     bzero(nd, sizeof(struct nlookupdata));
150     nd->nl_path = objcache_get(namei_oc, M_WAITOK);
151     nd->nl_flags |= NLC_HASBUF;
152     if (seg == UIO_SYSSPACE) 
153         error = copystr(path, nd->nl_path, MAXPATHLEN, &pathlen);
154     else
155         error = copyinstr(path, nd->nl_path, MAXPATHLEN, &pathlen);
156
157     /*
158      * Don't allow empty pathnames.
159      * POSIX.1 requirement: "" is not a vaild file name.
160      */
161     if (error == 0 && pathlen <= 1)
162         error = ENOENT;
163
164     if (error == 0) {
165         cache_copy(ncstart, &nd->nl_nch);
166         cache_copy(&rootnch, &nd->nl_rootnch);
167         cache_copy(&rootnch, &nd->nl_jailnch);
168         nd->nl_cred = crhold(cred);
169         nd->nl_td = td;
170         nd->nl_flags |= flags;
171     } else {
172         nlookup_done(nd);
173     }
174     return(error);
175 }
176
177 /*
178  * Set a different credential; this credential will be used by future
179  * operations performed on nd.nl_open_vp and nlookupdata structure.
180  */
181 void
182 nlookup_set_cred(struct nlookupdata *nd, struct ucred *cred)
183 {
184         KKASSERT(nd->nl_cred != NULL);
185
186         if (nd->nl_cred != cred) {
187                 cred = crhold(cred);
188                 crfree(nd->nl_cred);
189                 nd->nl_cred = cred;
190         }
191 }
192
193 /*
194  * Cleanup a nlookupdata structure after we are through with it.  This may
195  * be called on any nlookupdata structure initialized with nlookup_init().
196  * Calling nlookup_done() is mandatory in all cases except where nlookup_init()
197  * returns an error, even if as a consumer you believe you have taken all
198  * dynamic elements out of the nlookupdata structure.
199  */
200 void
201 nlookup_done(struct nlookupdata *nd)
202 {
203     if (nd->nl_nch.ncp) {
204         if (nd->nl_flags & NLC_NCPISLOCKED) {
205             nd->nl_flags &= ~NLC_NCPISLOCKED;
206             cache_unlock(&nd->nl_nch);
207         }
208         cache_drop(&nd->nl_nch);
209     }
210     if (nd->nl_rootnch.ncp)
211         cache_drop(&nd->nl_rootnch);
212     if (nd->nl_jailnch.ncp)
213         cache_drop(&nd->nl_jailnch);
214     if ((nd->nl_flags & NLC_HASBUF) && nd->nl_path) {
215         objcache_put(namei_oc, nd->nl_path);
216         nd->nl_path = NULL;
217     }
218     if (nd->nl_cred) {
219         crfree(nd->nl_cred);
220         nd->nl_cred = NULL;
221     }
222     if (nd->nl_open_vp) {
223         if (nd->nl_flags & NLC_LOCKVP) {
224                 vn_unlock(nd->nl_open_vp);
225                 nd->nl_flags &= ~NLC_LOCKVP;
226         }
227         vn_close(nd->nl_open_vp, nd->nl_vp_fmode);
228         nd->nl_open_vp = NULL;
229     }
230     if (nd->nl_dvp) {
231         vrele(nd->nl_dvp);
232         nd->nl_dvp = NULL;
233     }
234     nd->nl_flags = 0;   /* clear remaining flags (just clear everything) */
235 }
236
237 void
238 nlookup_zero(struct nlookupdata *nd)
239 {
240     bzero(nd, sizeof(struct nlookupdata));
241 }
242
243 /*
244  * Simple all-in-one nlookup.  Returns a locked namecache structure or NULL
245  * if an error occured. 
246  *
247  * Note that the returned ncp is not checked for permissions, though VEXEC
248  * is checked on the directory path leading up to the result.  The caller
249  * must call naccess() to check the permissions of the returned leaf.
250  */
251 struct nchandle
252 nlookup_simple(const char *str, enum uio_seg seg,
253                int niflags, int *error)
254 {
255     struct nlookupdata nd;
256     struct nchandle nch;
257
258     *error = nlookup_init(&nd, str, seg, niflags);
259     if (*error == 0) {
260             if ((*error = nlookup(&nd)) == 0) {
261                     nch = nd.nl_nch;    /* keep hold ref from structure */
262                     cache_zero(&nd.nl_nch); /* and NULL out */
263             } else {
264                     cache_zero(&nch);
265             }
266             nlookup_done(&nd);
267     } else {
268             cache_zero(&nch);
269     }
270     return(nch);
271 }
272
273 /*
274  * Do a generic nlookup.  Note that the passed nd is not nlookup_done()'d
275  * on return, even if an error occurs.  If no error occurs the returned
276  * nl_nch is always referenced and locked, otherwise it may or may not be.
277  *
278  * Intermediate directory elements, including the current directory, require
279  * execute (search) permission.  nlookup does not examine the access 
280  * permissions on the returned element.
281  *
282  * If NLC_CREATE is set the last directory must allow node creation,
283  * and an error code of 0 will be returned for a non-existant
284  * target (not ENOENT).
285  *
286  * If NLC_RENAME is set the last directory mut allow node deletion,
287  * plus the sticky check is made, and an error code of 0 will be returned
288  * for a non-existant target (not ENOENT).  NLC_RENAME is set used for
289  * the rename target.
290  *
291  * If NLC_DELETE is set the last directory mut allow node deletion,
292  * plus the sticky check is made.
293  *
294  * If NLC_REFDVP is set nd->nl_dvp will be set to the directory vnode
295  * of the returned entry.  The vnode will be referenced, but not locked,
296  * and will be released by nlookup_done() along with everything else.
297  */
298 int
299 nlookup(struct nlookupdata *nd)
300 {
301     struct nlcomponent nlc;
302     struct nchandle nch;
303     struct mount *mp;
304     int wasdotordotdot;
305     char *ptr;
306     char *xptr;
307     int error;
308     int len;
309
310 #ifdef KTRACE
311     if (KTRPOINT(nd->nl_td, KTR_NAMEI))
312         ktrnamei(nd->nl_td->td_lwp, nd->nl_path);
313 #endif
314     bzero(&nlc, sizeof(nlc));
315
316     /*
317      * Setup for the loop.  The current working namecache element must
318      * be in a refd + unlocked state.  This typically the case on entry except
319      * when stringing nlookup()'s along in a chain, since nlookup() always
320      * returns nl_nch in a locked state.
321      */
322     nd->nl_loopcnt = 0;
323     if (nd->nl_flags & NLC_NCPISLOCKED) {
324         nd->nl_flags &= ~NLC_NCPISLOCKED;
325         cache_unlock(&nd->nl_nch);
326     }
327     if (nd->nl_dvp ) {
328         vrele(nd->nl_dvp);
329         nd->nl_dvp = NULL;
330     }
331     ptr = nd->nl_path;
332
333     /*
334      * Loop on the path components.  At the top of the loop nd->nl_nch
335      * is ref'd and unlocked and represents our current position.
336      */
337     for (;;) {
338         /*
339          * Check if the root directory should replace the current
340          * directory.  This is done at the start of a translation
341          * or after a symbolic link has been found.  In other cases
342          * ptr will never be pointing at a '/'.
343          */
344         if (*ptr == '/') {
345             do {
346                 ++ptr;
347             } while (*ptr == '/');
348             cache_copy(&nd->nl_rootnch, &nch);
349             cache_drop(&nd->nl_nch);
350             nd->nl_nch = nch;
351
352             /*
353              * Fast-track termination.  There is no parent directory of
354              * the root in the same mount from the point of view of
355              * the caller so return EPERM if NLC_REFDVP is specified.
356              * e.g. 'rmdir /' is not allowed.
357              */
358             if (*ptr == 0) {
359                 if (nd->nl_flags & NLC_REFDVP) {
360                         error = EPERM;
361                 } else {
362                         cache_lock(&nd->nl_nch);
363                         nd->nl_flags |= NLC_NCPISLOCKED;
364                         error = 0;
365                 }
366                 break;
367             }
368             continue;
369         }
370
371         /*
372          * Check directory search permissions.
373          */
374         if ((error = naccess(&nd->nl_nch, VEXEC, nd->nl_cred, NULL)) != 0)
375             break;
376
377         /*
378          * Extract the path component.  Path components are limited to
379          * 255 characters.
380          */
381         nlc.nlc_nameptr = ptr;
382         while (*ptr && *ptr != '/')
383             ++ptr;
384         nlc.nlc_namelen = ptr - nlc.nlc_nameptr;
385         if (nlc.nlc_namelen >= 256) {
386             error = ENAMETOOLONG;
387             break;
388         }
389
390         /*
391          * Lookup the path component in the cache, creating an unresolved
392          * entry if necessary.  We have to handle "." and ".." as special
393          * cases.
394          *
395          * When handling ".." we have to detect a traversal back through a
396          * mount point.   If we are at the root, ".." just returns the root.
397          *
398          * This subsection returns a locked, refd 'nch' unless it errors out.
399          * The namecache topology is not allowed to be disconnected, so 
400          * encountering a NULL parent will generate EINVAL.  This typically
401          * occurs when a directory is removed out from under a process.
402          */
403         if (nlc.nlc_namelen == 1 && nlc.nlc_nameptr[0] == '.') {
404             cache_get(&nd->nl_nch, &nch);
405             wasdotordotdot = 1;
406         } else if (nlc.nlc_namelen == 2 && 
407                    nlc.nlc_nameptr[0] == '.' && nlc.nlc_nameptr[1] == '.') {
408             if (nd->nl_nch.mount == nd->nl_rootnch.mount &&
409                 nd->nl_nch.ncp == nd->nl_rootnch.ncp
410             ) {
411                 /*
412                  * ".." at the root returns the root
413                  */
414                 cache_get(&nd->nl_nch, &nch);
415             } else {
416                 /*
417                  * Locate the parent ncp.  If we are at the root of a
418                  * filesystem mount we have to skip to the mounted-on
419                  * point in the underlying filesystem.
420                  */
421                 nch = nd->nl_nch;
422                 while (nch.ncp == nch.mount->mnt_ncmountpt.ncp)
423                         nch = nch.mount->mnt_ncmounton;
424                 nch.ncp = nch.ncp->nc_parent;
425                 KKASSERT(nch.ncp != NULL);
426                 cache_get(&nch, &nch);
427             }
428             wasdotordotdot = 2;
429         } else {
430             nch = cache_nlookup(&nd->nl_nch, &nlc);
431             while ((error = cache_resolve(&nch, nd->nl_cred)) == EAGAIN) {
432                 kprintf("[diagnostic] nlookup: relookup %*.*s\n", 
433                         nch.ncp->nc_nlen, nch.ncp->nc_nlen, nch.ncp->nc_name);
434                 cache_put(&nch);
435                 nch = cache_nlookup(&nd->nl_nch, &nlc);
436             }
437             wasdotordotdot = 0;
438         }
439         /*
440          * [end of subsection] ncp is locked and ref'd.  nd->nl_nch is ref'd
441          */
442
443         /*
444          * Resolve the namespace if necessary.  The ncp returned by
445          * cache_nlookup() is referenced and locked.
446          *
447          * XXX neither '.' nor '..' should return EAGAIN since they were
448          * previously resolved and thus cannot be newly created ncp's.
449          */
450         if (nch.ncp->nc_flag & NCF_UNRESOLVED) {
451             error = cache_resolve(&nch, nd->nl_cred);
452             KKASSERT(error != EAGAIN);
453         } else {
454             error = nch.ncp->nc_error;
455         }
456
457         /*
458          * Early completion.  ENOENT is not an error if this is the last
459          * component and NLC_CREATE or NLC_RENAME (rename target) was
460          * requested.  Note that ncp->nc_error is left as ENOENT in that
461          * case, which we check later on.
462          *
463          * NOTE: For NLC_RENAME in the ENOENT case we do a VCREATE test,
464          *       same as for NLC_CREATE.
465          *
466          * Also handle invalid '.' or '..' components terminating a path
467          * for a create/rename/delete.  The standard requires this and pax
468          * pretty stupidly depends on it.
469          */
470         for (xptr = ptr; *xptr == '/'; ++xptr)
471                 ;
472         if (*xptr == 0) {
473             if (error == ENOENT && (nd->nl_flags & (NLC_CREATE | NLC_RENAME))) {
474                 if (nd->nl_flags & NLC_NFS_RDONLY)
475                         error = EROFS;
476                 else
477                         error = naccess(&nch, VCREATE, nd->nl_cred, NULL);
478             }
479             if (error == 0 && wasdotordotdot &&
480                 (nd->nl_flags & (NLC_CREATE | NLC_RENAME | NLC_DELETE))) {
481                 /*
482                  * POSIX junk
483                  */
484                 if (nd->nl_flags & NLC_CREATE)
485                         error = EEXIST;
486                 else if (nd->nl_flags & NLC_DELETE)
487                         error = (wasdotordotdot == 1) ? EINVAL : ENOTEMPTY;
488                 else
489                         error = EINVAL;
490             }
491         }
492
493         /*
494          * Early completion on error.
495          */
496         if (error) {
497             cache_put(&nch);
498             break;
499         }
500
501         /*
502          * If the element is a symlink and it is either not the last
503          * element or it is the last element and we are allowed to
504          * follow symlinks, resolve the symlink.
505          */
506         if ((nch.ncp->nc_flag & NCF_ISSYMLINK) &&
507             (*ptr || (nd->nl_flags & NLC_FOLLOW))
508         ) {
509             if (nd->nl_loopcnt++ >= MAXSYMLINKS) {
510                 error = ELOOP;
511                 cache_put(&nch);
512                 break;
513             }
514             error = nreadsymlink(nd, &nch, &nlc);
515             cache_put(&nch);
516             if (error)
517                 break;
518
519             /*
520              * Concatenate trailing path elements onto the returned symlink.
521              * Note that if the path component (ptr) is not exhausted, it
522              * will being with a '/', so we do not have to add another one.
523              *
524              * The symlink may not be empty.
525              */
526             len = strlen(ptr);
527             if (nlc.nlc_namelen == 0 || nlc.nlc_namelen + len >= MAXPATHLEN) {
528                 error = nlc.nlc_namelen ? ENAMETOOLONG : ENOENT;
529                 objcache_put(namei_oc, nlc.nlc_nameptr);
530                 break;
531             }
532             bcopy(ptr, nlc.nlc_nameptr + nlc.nlc_namelen, len + 1);
533             if (nd->nl_flags & NLC_HASBUF)
534                 objcache_put(namei_oc, nd->nl_path);
535             nd->nl_path = nlc.nlc_nameptr;
536             nd->nl_flags |= NLC_HASBUF;
537             ptr = nd->nl_path;
538
539             /*
540              * Go back up to the top to resolve any initial '/'s in the
541              * symlink.
542              */
543             continue;
544         }
545
546         /*
547          * If the element is a directory and we are crossing a mount point,
548          * Locate the mount.
549          */
550         while ((nch.ncp->nc_flag & NCF_ISMOUNTPT) && 
551             (nd->nl_flags & NLC_NOCROSSMOUNT) == 0 &&
552             (mp = cache_findmount(&nch)) != NULL
553         ) {
554             struct vnode *tdp;
555
556             cache_put(&nch);
557             cache_get(&mp->mnt_ncmountpt, &nch);
558
559             if (nch.ncp->nc_flag & NCF_UNRESOLVED) {
560                 while (vfs_busy(mp, 0))
561                     ;
562                 error = VFS_ROOT(mp, &tdp);
563                 vfs_unbusy(mp);
564                 if (error)
565                     break;
566                 cache_setvp(&nch, tdp);
567                 vput(tdp);
568             }
569         }
570         if (error) {
571             cache_put(&nch);
572             break;
573         }
574             
575         /*
576          * Skip any slashes to get to the next element.  If there 
577          * are any slashes at all the current element must be a
578          * directory or, in the create case, intended to become a directory.
579          * If it isn't we break without incrementing ptr and fall through
580          * to the failure case below.
581          */
582         while (*ptr == '/') {
583             if ((nch.ncp->nc_flag & NCF_ISDIR) == 0 && 
584                 !(nd->nl_flags & NLC_WILLBEDIR)
585             ) {
586                 break;
587             }
588             ++ptr;
589         }
590
591         /*
592          * Continuation case: additional elements and the current
593          * element is a directory.
594          */
595         if (*ptr && (nch.ncp->nc_flag & NCF_ISDIR)) {
596             cache_drop(&nd->nl_nch);
597             cache_unlock(&nch);
598             nd->nl_nch = nch;
599             continue;
600         }
601
602         /*
603          * Failure case: additional elements and the current element
604          * is not a directory
605          */
606         if (*ptr) {
607             cache_put(&nch);
608             error = ENOTDIR;
609             break;
610         }
611
612         /*
613          * Successful lookup of last element.
614          *
615          * Check directory permissions if a deletion or rename (target)
616          * is specified.  This also handles the sticky test.
617          *
618          * We already checked permissions for creates in the early
619          * termination code above.
620          */
621         if (*ptr == 0 && (nd->nl_flags & (NLC_DELETE | NLC_RENAME))) {
622             if (nd->nl_flags & NLC_DELETE)
623                 error = naccess(&nch, VDELETE, nd->nl_cred, NULL);
624             else
625                 error = naccess(&nch, VRENAME, nd->nl_cred, NULL);
626             if (error) {
627                 cache_put(&nch);
628                 break;
629             }
630         }
631
632         /*
633          * Termination: no more elements.  If NLC_CREATE was set the
634          * ncp may represent a negative hit (ncp->nc_error will be ENOENT),
635          * but we still return an error code of 0.
636          *
637          * If NLC_REFDVP is set acquire a referenced parent dvp.
638          */
639         if (nd->nl_flags & NLC_REFDVP) {
640                 error = cache_vref(&nd->nl_nch, nd->nl_cred, &nd->nl_dvp);
641                 if (error) {
642                         kprintf("NLC_REFDVP: Cannot ref dvp of %p\n", nch.ncp);
643                         cache_put(&nch);
644                         break;
645                 }
646         }
647         cache_drop(&nd->nl_nch);
648         nd->nl_nch = nch;
649         nd->nl_flags |= NLC_NCPISLOCKED;
650         error = 0;
651         break;
652     }
653     return(error);
654 }
655
656 /*
657  * Resolve a mount point's glue ncp.  This ncp connects creates the illusion
658  * of continuity in the namecache tree by connecting the ncp related to the
659  * vnode under the mount to the ncp related to the mount's root vnode.
660  *
661  * If no error occured a locked, ref'd ncp is stored in *ncpp.
662  */
663 int
664 nlookup_mp(struct mount *mp, struct nchandle *nch)
665 {
666     struct vnode *vp;
667     int error;
668
669     error = 0;
670     cache_get(&mp->mnt_ncmountpt, nch);
671     if (nch->ncp->nc_flag & NCF_UNRESOLVED) {
672         while (vfs_busy(mp, 0))
673             ;
674         error = VFS_ROOT(mp, &vp);
675         vfs_unbusy(mp);
676         if (error) {
677             cache_put(nch);
678         } else {
679             cache_setvp(nch, vp);
680             vput(vp);
681         }
682     }
683     return(error);
684 }
685
686 /*
687  * Read the contents of a symlink, allocate a path buffer out of the
688  * namei_oc and initialize the supplied nlcomponent with the result.
689  *
690  * If an error occurs no buffer will be allocated or returned in the nlc.
691  */
692 int
693 nreadsymlink(struct nlookupdata *nd, struct nchandle *nch, 
694                 struct nlcomponent *nlc)
695 {
696     struct vnode *vp;
697     struct iovec aiov;
698     struct uio auio;
699     int linklen;
700     int error;
701     char *cp;
702
703     nlc->nlc_nameptr = NULL;
704     nlc->nlc_namelen = 0;
705     if (nch->ncp->nc_vp == NULL)
706         return(ENOENT);
707     if ((error = cache_vget(nch, nd->nl_cred, LK_SHARED, &vp)) != 0)
708         return(error);
709     cp = objcache_get(namei_oc, M_WAITOK);
710     aiov.iov_base = cp;
711     aiov.iov_len = MAXPATHLEN;
712     auio.uio_iov = &aiov;
713     auio.uio_iovcnt = 1;
714     auio.uio_offset = 0;
715     auio.uio_rw = UIO_READ;
716     auio.uio_segflg = UIO_SYSSPACE;
717     auio.uio_td = nd->nl_td;
718     auio.uio_resid = MAXPATHLEN - 1;
719     error = VOP_READLINK(vp, &auio, nd->nl_cred);
720     if (error)
721         goto fail;
722     linklen = MAXPATHLEN - 1 - auio.uio_resid;
723     if (varsym_enable) {
724         linklen = varsymreplace(cp, linklen, MAXPATHLEN - 1);
725         if (linklen < 0) {
726             error = ENAMETOOLONG;
727             goto fail;
728         }
729     }
730     cp[linklen] = 0;
731     nlc->nlc_nameptr = cp;
732     nlc->nlc_namelen = linklen;
733     vput(vp);
734     return(0);
735 fail:
736     objcache_put(namei_oc, cp);
737     vput(vp);
738     return(error);
739 }
740
741 /*
742  * Check access [XXX cache vattr!] [XXX quota]
743  *
744  * Generally check the V* access bits from sys/vnode.h.  All specified bits
745  * must pass for this function to return 0.
746  *
747  * The file does not have to exist when checking VCREATE or VRENAME access.
748  *
749  * The file must not exist if VEXCL is specified.
750  *
751  * Directory permissions in general are tested for VCREATE if the file
752  * does not exist, VDELETE if the file does exist, and VRENAME whether
753  * the file exists or not.
754  *
755  * The directory sticky bit is tested for VDELETE and VRENAME.  NOTE: For
756  * VRENAME we only care if the target exists.
757  *
758  * The passed ncp may or may not be locked.  The caller should use a
759  * locked ncp on leaf lookups, especially for VCREATE, VRENAME, VDELETE,
760  * and VEXCL checks.
761  */
762 int
763 naccess(struct nchandle *nch, int vmode, struct ucred *cred, int *stickyp)
764 {
765     struct nchandle par;
766     struct vnode *vp;
767     struct vattr va;
768     int error;
769     int sticky;
770
771     if (nch->ncp->nc_flag & NCF_UNRESOLVED) {
772         cache_lock(nch);
773         cache_resolve(nch, cred);
774         cache_unlock(nch);
775     }
776     error = nch->ncp->nc_error;
777     sticky = 0;
778
779     /*
780      * Directory permissions and VEXCL checks.  Do a precursor conditional
781      * to reduce overhead since most access checks are for read-only.
782      */
783     if (vmode & (VDELETE|VRENAME|VCREATE|VEXCL)) {
784         if (((vmode & VCREATE) && nch->ncp->nc_vp == NULL) ||
785             ((vmode & VDELETE) && nch->ncp->nc_vp != NULL) ||
786             (vmode & VRENAME)
787         ) {
788             if ((par.ncp = nch->ncp->nc_parent) == NULL) {
789                 if (error != EAGAIN)
790                         error = EINVAL;
791             } else {
792                 par.mount = nch->mount;
793                 cache_hold(&par);
794                 error = naccess(&par, VWRITE, cred, &sticky);
795                 if ((vmode & (VDELETE | VRENAME)) && sticky)
796                     vmode |= VSVTX;
797                 cache_drop(&par);
798             }
799         }
800         if ((vmode & VEXCL) && nch->ncp->nc_vp != NULL)
801             error = EEXIST;
802     }
803     if (error == 0) {
804         error = cache_vget(nch, cred, LK_SHARED, &vp);
805         if (error == ENOENT) {
806             if (vmode & (VCREATE | VRENAME))
807                 error = 0;
808         } else if (error == 0) {
809             /* XXX cache the va in the namecache or in the vnode */
810             if ((error = VOP_GETATTR(vp, &va)) == 0) {
811                 if ((vmode & VWRITE) && vp->v_mount) {
812                     if (vp->v_mount->mnt_flag & MNT_RDONLY)
813                         error = EROFS;
814                 }
815             }
816             vput(vp);
817
818             if (error == 0) {
819                 /*
820                  * Set the returned (*stickyp) if VSVTX is set and the uid
821                  * is not the owner of the directory.  The caller uses this
822                  * disallow deletions of files not owned by the user if the
823                  * user also does not own the directory and the sticky bit
824                  * is set on the directory.  Weird, I know.
825                  */
826                 if (stickyp && va.va_uid != cred->cr_uid)
827                     *stickyp = (va.va_mode & VSVTX);
828
829                 /*
830                  * Process general access.
831                  */
832                 error = naccess_va(&va, vmode, cred);
833             }
834         }
835     }
836     return(error);
837 }
838
839 /*
840  * Check the requested access against the given vattr using cred.
841  */
842 static
843 int
844 naccess_va(struct vattr *va, int vmode, struct ucred *cred)
845 {
846     int i;
847
848     /*
849      * Test the immutable bit for files, directories, and softlinks.
850      *
851      * NOTE: Only called for VRENAME if the target exists.
852      */
853     if (vmode & (VWRITE|VDELETE|VRENAME)) {
854         if (va->va_type == VDIR || va->va_type == VLNK || va->va_type == VREG) {
855             if (va->va_flags & IMMUTABLE)
856                 return (EPERM);
857         }
858     }
859
860     /*
861      * root gets universal access
862      */
863     if (cred->cr_uid == 0)
864         return(0);
865
866     /*
867      * Check owner perms.
868      *
869      * If VOWN is set the owner of the file is allowed no matter when
870      * the owner-mode bits say (utimes).
871      */
872     if (cred->cr_uid == va->va_uid) {
873         if ((vmode & VOWN) == 0) {
874             vmode &= S_IRWXU;
875             if ((vmode & va->va_mode) != vmode)
876                 return(EACCES);
877         }
878         return(0);
879     }
880
881     /*
882      * If VSVTX is set only the owner may create or delete the file.
883      * This bit is typically set for VDELETE checks from unlink or
884      * the source file in a rename, and for VCREATE checks from the
885      * target file in a rename.
886      *
887      * Note that other V bits are not typically set in the VSVTX case.
888      * For creations and deletions we usually just care about directory
889      * permissions, not file permissions.  So if this test passes the
890      * return value winds up being 0.
891      */
892     if (vmode & VSVTX)
893         return(EACCES);
894
895     /*
896      * Check group perms
897      */
898     vmode &= S_IRWXU;
899     vmode >>= 3;
900     for (i = 0; i < cred->cr_ngroups; ++i) {
901         if (va->va_gid == cred->cr_groups[i]) {
902             if ((vmode & va->va_mode) != vmode)
903                 return(EACCES);
904             return(0);
905         }
906     }
907
908     /*
909      * Check world perms
910      */
911     vmode >>= 3;
912     if ((vmode & va->va_mode) != vmode)
913         return(EACCES);
914     return(0);
915 }
916