VFS messaging/interfacing work stage 7e/99: More firming up of stage 7.
[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.4 2004/10/05 07:57:40 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 <vm/vm_zone.h>
68
69 #ifdef KTRACE
70 #include <sys/ktrace.h>
71 #endif
72
73 /*
74  * Initialize a nlookup() structure, early error return for copyin faults
75  * or a degenerate empty string (which is not allowed).
76  */
77 int
78 nlookup_init(struct nlookupdata *nd, 
79              const char *path, enum uio_seg seg, int flags)
80 {
81     size_t pathlen;
82     struct proc *p;
83     thread_t td;
84     int error;
85
86     td = curthread;
87     p = td->td_proc;
88
89     /*
90      * note: the pathlen set by copy*str() includes the terminating \0.
91      */
92     bzero(nd, sizeof(struct nlookupdata));
93     nd->nl_path = zalloc(namei_zone);
94     nd->nl_flags |= NLC_HASBUF;
95     if (seg == UIO_SYSSPACE) 
96         error = copystr(path, nd->nl_path, MAXPATHLEN, &pathlen);
97     else
98         error = copyinstr(path, nd->nl_path, MAXPATHLEN, &pathlen);
99
100     /*
101      * Don't allow empty pathnames.
102      * POSIX.1 requirement: "" is not a vaild file name.
103      */
104     if (error == 0 && pathlen <= 1)
105         error = ENOENT;
106
107     if (error == 0) {
108         if (p && p->p_fd) {
109             nd->nl_ncp = cache_hold(p->p_fd->fd_ncdir);
110             nd->nl_rootncp = cache_hold(p->p_fd->fd_nrdir);
111             if (p->p_fd->fd_njdir)
112                 nd->nl_jailncp = cache_hold(p->p_fd->fd_njdir);
113             nd->nl_cred = crhold(p->p_ucred);
114         } else {
115             nd->nl_ncp = cache_hold(rootncp);
116             nd->nl_rootncp = cache_hold(nd->nl_ncp);
117             nd->nl_jailncp = cache_hold(nd->nl_ncp);
118             nd->nl_cred = crhold(proc0.p_ucred);
119         }
120         nd->nl_td = td;
121         nd->nl_flags |= flags;
122     } else {
123         nlookup_done(nd);
124     }
125     return(error);
126 }
127
128 /*
129  * Cleanup a nlookupdata structure after we are through with it.  This may
130  * be called on any nlookupdata structure initialized with nlookup_init().
131  * Calling nlookup_done() is mandatory in all cases except where nlookup_init()
132  * returns an error, even if as a consumer you believe you have taken all
133  * dynamic elements out of the nlookupdata structure.
134  */
135 void
136 nlookup_done(struct nlookupdata *nd)
137 {
138     if (nd->nl_ncp) {
139         if (nd->nl_flags & NLC_NCPISLOCKED) {
140             nd->nl_flags &= ~NLC_NCPISLOCKED;
141             cache_unlock(nd->nl_ncp);
142         }
143         cache_drop(nd->nl_ncp);
144         nd->nl_ncp = NULL;
145     }
146     if (nd->nl_rootncp) {
147         cache_drop(nd->nl_rootncp);
148         nd->nl_rootncp = NULL;
149     }
150     if (nd->nl_jailncp) {
151         cache_drop(nd->nl_jailncp);
152         nd->nl_jailncp = NULL;
153     }
154     if ((nd->nl_flags & NLC_HASBUF) && nd->nl_path) {
155         zfree(namei_zone, nd->nl_path);
156         nd->nl_path = NULL;
157     }
158     if (nd->nl_cred) {
159         crfree(nd->nl_cred);
160         nd->nl_cred = NULL;
161     }
162     nd->nl_flags = 0;
163 }
164
165 /*
166  * Simple all-in-one nlookup.  Returns a locked namecache structure or NULL
167  * if an error occured. 
168  *
169  * Note that the returned ncp is not checked for permissions, though VEXEC
170  * is checked on the directory path leading up to the result.  The caller
171  * must call naccess() to check the permissions of the returned leaf.
172  */
173 struct namecache *
174 nlookup_simple(const char *str, enum uio_seg seg,
175                int niflags, int *error)
176 {
177     struct nlookupdata nd;
178     struct namecache *ncp;
179
180     *error = nlookup_init(&nd, str, seg, niflags);
181     if (*error == 0) {
182             if ((*error = nlookup(&nd)) == 0) {
183                     ncp = nd.nl_ncp;    /* keep hold ref from structure */
184                     nd.nl_ncp = NULL;   /* and NULL out */
185             } else {
186                     ncp = NULL;
187             }
188             nlookup_done(&nd);
189     } else {
190             ncp = NULL;
191     }
192     return(ncp);
193 }
194
195 /*
196  * Do a generic nlookup.  Note that the passed nd is not nlookup_done()'d
197  * on return, even if an error occurs.  If no error occurs the returned
198  * nl_ncp is always referenced and locked, otherwise it may or may not be.
199  *
200  * Intermediate directory elements, including the current directory, require
201  * execute (search) permission.  nlookup does not examine the access 
202  * permissions on the returned element.
203  */
204 int
205 nlookup(struct nlookupdata *nd)
206 {
207     struct nlcomponent nlc;
208     struct namecache *ncp;
209     char *ptr;
210     int error;
211     int len;
212
213 #ifdef KTRACE
214     if (KTRPOINT(nd->nl_td, KTR_NAMEI))
215         ktrnamei(nd->nl_td->td_proc->p_tracep, nd->nl_path);
216 #endif
217     bzero(&nlc, sizeof(nlc));
218
219     /*
220      * Setup for the loop.  The current working namecache element must
221      * be in a refd + unlocked state.  This typically the case on entry except
222      * when stringing nlookup()'s along in a chain, since nlookup() always
223      * returns nl_ncp in a locked state.
224      */
225     nd->nl_loopcnt = 0;
226     if (nd->nl_flags & NLC_NCPISLOCKED) {
227         nd->nl_flags &= ~NLC_NCPISLOCKED;
228         cache_unlock(nd->nl_ncp);
229     }
230     ptr = nd->nl_path;
231
232     /*
233      * Loop on the path components.  At the top of the loop nd->nl_ncp
234      * is ref'd and unlocked and represents our current position.
235      */
236     for (;;) {
237         /*
238          * Check if the root directory should replace the current
239          * directory.  This is done at the start of a translation
240          * or after a symbolic link has been found.  In other cases
241          * ptr will never be pointing at a '/'.
242          */
243         if (*ptr == '/') {
244             do {
245                 ++ptr;
246             } while (*ptr == '/');
247             ncp = cache_hold(nd->nl_rootncp);
248             cache_drop(nd->nl_ncp);
249             nd->nl_ncp = ncp;
250             if (*ptr == 0) {
251                 cache_lock(nd->nl_ncp);
252                 nd->nl_flags |= NLC_NCPISLOCKED;
253                 error = 0;
254                 break;
255             }
256             continue;
257         }
258
259         /*
260          * Check directory search permissions
261          */
262         if ((error = naccess(nd->nl_ncp, VEXEC, nd->nl_cred)) != 0)
263             break;
264
265         /*
266          * Extract the path component
267          */
268         nlc.nlc_nameptr = ptr;
269         while (*ptr && *ptr != '/')
270             ++ptr;
271         nlc.nlc_namelen = ptr - nlc.nlc_nameptr;
272
273         /*
274          * Lookup the path component in the cache, creating an unresolved
275          * entry if necessary.  We have to handle "." and ".." as special
276          * cases.
277          *
278          * When handling ".." we have to detect a traversal back through a
279          * mount point and skip the mount-under node.  If we are at the root
280          * ".." just returns the root.
281          *
282          * This subsection returns a locked, refd 'ncp'.
283          */
284         if (nlc.nlc_namelen == 1 && nlc.nlc_nameptr[0] == '.') {
285             ncp = cache_get(nd->nl_ncp);
286         } else if (nlc.nlc_namelen == 2 && 
287                    nlc.nlc_nameptr[0] == '.' && nlc.nlc_nameptr[1] == '.') {
288             ncp = nd->nl_ncp;
289             if (ncp == nd->nl_rootncp) {
290                 ncp = cache_get(ncp);
291             } else {
292                 while ((ncp->nc_flag & NCF_MOUNTPT) && ncp != nd->nl_rootncp) {
293                     /* ignore NCF_REVALPARENT on a mount point */
294                     ncp = ncp->nc_parent;       /* get to underlying node */
295                     KKASSERT(ncp != NULL && 1);
296                 }
297                 if (ncp->nc_flag & NCF_REVALPARENT) {
298                     printf("[diagnostic] nlookup can't .. past a renamed directory: %*.*s\n", ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name);
299                     error = EINVAL;
300                     break;
301                 }
302                 if (ncp != nd->nl_rootncp)
303                         ncp = ncp->nc_parent;
304                 KKASSERT(ncp != NULL && 2);
305                 ncp = cache_get(ncp);
306             }
307         } else {
308             ncp = cache_nlookup(nd->nl_ncp, &nlc);
309             while ((error = cache_resolve(ncp, nd->nl_cred)) == EAGAIN) {
310                 printf("[diagnostic] nlookup: relookup %*.*s\n", 
311                         ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name);
312                 cache_put(ncp);
313                 ncp = cache_nlookup(nd->nl_ncp, &nlc);
314                 error = cache_resolve(ncp, nd->nl_cred);
315             }
316         }
317         /*
318          * [end of subsection] ncp is locked and ref'd.  nd->nl_ncp is ref'd
319          */
320
321         /*
322          * Resolve the namespace if necessary.  The ncp returned by
323          * cache_nlookup() is referenced and locked.
324          *
325          * XXX neither '.' nor '..' should return EAGAIN since they were
326          * previously resolved and thus cannot be newly created ncp's.
327          */
328         if (ncp->nc_flag & NCF_UNRESOLVED) {
329             error = cache_resolve(ncp, nd->nl_cred);
330             KKASSERT(error != EAGAIN);
331         } else {
332             error = ncp->nc_error;
333         }
334
335         /*
336          * Early completion
337          */
338         if (error) {
339             cache_put(ncp);
340             break;
341         }
342
343         /*
344          * If the element is a symlink and it is either not the last
345          * element or it is the last element and we are allowed to
346          * follow symlinks, resolve the symlink.
347          */
348         if ((ncp->nc_flag & NCF_ISSYMLINK) &&
349             (*ptr || (nd->nl_flags & NLC_FOLLOW))
350         ) {
351             if (nd->nl_loopcnt++ >= MAXSYMLINKS) {
352                 error = ELOOP;
353                 cache_put(ncp);
354                 break;
355             }
356             error = nreadsymlink(nd, ncp, &nlc);
357             cache_put(ncp);
358             if (error)
359                 break;
360
361             /*
362              * Concatenate trailing path elements onto the returned symlink.
363              * Note that if the path component (ptr) is not exhausted, it
364              * will being with a '/', so we do not have to add another one.
365              *
366              * The symlink may not be empty.
367              */
368             len = strlen(ptr);
369             if (nlc.nlc_namelen == 0 || nlc.nlc_namelen + len >= MAXPATHLEN) {
370                 error = nlc.nlc_namelen ? ENAMETOOLONG : ENOENT;
371                 zfree(namei_zone, nlc.nlc_nameptr);
372                 break;
373             }
374             bcopy(ptr, nlc.nlc_nameptr + nlc.nlc_namelen, len + 1);
375             if (nd->nl_flags & NLC_HASBUF)
376                 zfree(namei_zone, nd->nl_path);
377             nd->nl_path = nlc.nlc_nameptr;
378             nd->nl_flags |= NLC_HASBUF;
379             ptr = nd->nl_path;
380
381             /*
382              * Go back up to the top to resolve any initial '/'s in the
383              * symlink.
384              */
385             continue;
386         }
387
388         /*
389          * If the element is a directory and we are crossing a mount point,
390          * retrieve the root of the mounted filesystem from mnt_ncp and
391          * resolve it if necessary.
392          *
393          * XXX mnt_ncp should really be resolved in the mount code.
394          * NOTE!  the normal nresolve() code cannot resolve mount point ncp's!
395          *
396          * XXX NOCROSSMOUNT
397          */
398         while ((ncp->nc_flag & NCF_ISDIR) && ncp->nc_vp->v_mountedhere &&
399                 (nd->nl_flags & NLC_NOCROSSMOUNT) == 0
400         ) {
401             struct mount *mp;
402             struct vnode *tdp;
403
404             mp = ncp->nc_vp->v_mountedhere;
405             cache_put(ncp);
406             ncp = cache_get(mp->mnt_ncp);
407
408             if (ncp->nc_flag & NCF_UNRESOLVED) {
409                 while (vfs_busy(mp, 0, NULL, nd->nl_td))
410                     ;
411                 error = VFS_ROOT(mp, &tdp);
412                 vfs_unbusy(mp, nd->nl_td);
413                 if (error)
414                     break;
415                 cache_setvp(ncp, tdp);
416                 vput(tdp);
417             }
418         }
419         if (error) {
420             cache_put(ncp);
421             break;
422         }
423             
424         /*
425          * Skip any slashes to get to the next element.  If there 
426          * are any slashes at all the current element must be a
427          * directory.  If it isn't we break without incrementing
428          * ptr and fall through to the failure case below.
429          */
430         while (*ptr == '/') {
431             if ((ncp->nc_flag & NCF_ISDIR) == 0)
432                 break;
433             ++ptr;
434         }
435
436         /*
437          * Continuation case: additional elements and the current
438          * element is a directory.
439          */
440         if (*ptr && (ncp->nc_flag & NCF_ISDIR)) {
441             cache_drop(nd->nl_ncp);
442             cache_unlock(ncp);
443             nd->nl_ncp = ncp;
444             continue;
445         }
446
447         /*
448          * Failure case: additional elements and the current element
449          * is not a directory
450          */
451         if (*ptr) {
452             cache_put(ncp);
453             error = ENOTDIR;
454             break;
455         }
456
457         /*
458          * XXX vnode canvmio (test in mmap(), read(), and write())
459          */
460
461         /*
462          * Termination: no more elements.
463          */
464         cache_drop(nd->nl_ncp);
465         nd->nl_ncp = ncp;
466         nd->nl_flags |= NLC_NCPISLOCKED;
467         error = 0;
468         break;
469     }
470     return(error);
471 }
472
473 /*
474  * Resolve a mount point's glue ncp.  This ncp connects creates the illusion
475  * of continuity in the namecache tree by connecting the ncp related to the
476  * vnode under the mount to the ncp related to the mount's root vnode.
477  *
478  * If no error occured a locked, ref'd ncp is stored in *ncpp.
479  */
480 int
481 nlookup_mp(struct mount *mp, struct namecache **ncpp)
482 {
483     struct namecache *ncp;
484     struct vnode *vp;
485     int error;
486
487     error = 0;
488     ncp = mp->mnt_ncp;
489     cache_get(ncp);
490     if (ncp->nc_flag & NCF_UNRESOLVED) {
491         while (vfs_busy(mp, 0, NULL, curthread))
492             ;
493         error = VFS_ROOT(mp, &vp);
494         vfs_unbusy(mp, curthread);
495         if (error) {
496             cache_put(ncp);
497             ncp = NULL;
498         } else {
499             cache_setvp(ncp, vp);
500             vput(vp);
501         }
502     }
503     *ncpp = ncp;
504     return(error);
505 }
506
507 /*
508  * Read the contents of a symlink, allocate a path buffer out of the
509  * namei_zone and initialize the supplied nlcomponent with the result.
510  *
511  * If an error occurs no buffer will be allocated or returned in the nlc.
512  */
513 int
514 nreadsymlink(struct nlookupdata *nd, struct namecache *ncp, 
515                 struct nlcomponent *nlc)
516 {
517     struct vnode *vp;
518     struct iovec aiov;
519     struct uio auio;
520     int linklen;
521     int error;
522     char *cp;
523
524     nlc->nlc_nameptr = NULL;
525     nlc->nlc_namelen = 0;
526     if (ncp->nc_vp == NULL)
527         return(ENOENT);
528     if ((error = cache_vget(ncp, nd->nl_cred, LK_SHARED, &vp)) != 0)
529         return(error);
530     cp = zalloc(namei_zone);
531     aiov.iov_base = cp;
532     aiov.iov_len = MAXPATHLEN;
533     auio.uio_iov = &aiov;
534     auio.uio_iovcnt = 1;
535     auio.uio_offset = 0;
536     auio.uio_rw = UIO_READ;
537     auio.uio_segflg = UIO_SYSSPACE;
538     auio.uio_td = nd->nl_td;
539     auio.uio_resid = MAXPATHLEN - 1;
540     error = VOP_READLINK(vp, &auio, nd->nl_cred);
541     if (error)
542         goto fail;
543     linklen = MAXPATHLEN - 1 - auio.uio_resid;
544     if (varsym_enable) {
545         linklen = varsymreplace(cp, linklen, MAXPATHLEN - 1);
546         if (linklen < 0) {
547             error = ENAMETOOLONG;
548             goto fail;
549         }
550     }
551     cp[linklen] = 0;
552     nlc->nlc_nameptr = cp;
553     nlc->nlc_namelen = linklen;
554     vput(vp);
555     return(0);
556 fail:
557     zfree(namei_zone, cp);
558     vput(vp);
559     return(error);
560 }
561
562 /*
563  * Check access [XXX cache vattr!] [XXX quota]
564  *
565  * Generally check the V* access bits from sys/vnode.h.  All specified bits
566  * must pass for this function to return 0.
567  *
568  * If VCREATE is specified and the target ncp represents a non-existant
569  * file or dir, or if VDELETE is specified and the target exists, the parent
570  * directory is checked for VWRITE.  If VEXCL is specified and the target
571  * ncp represents a positive hit, an error is returned.
572  *
573  * If VCREATE is not specified and the target does not exist (negative hit),
574  * ENOENT is returned.  Note that nlookup() does not (and should not) return
575  * ENOENT for non-existant leafs.
576  *
577  * The passed ncp may or may not be locked.  The caller should use a
578  * locked ncp on leaf lookups, especially for VCREATE, VDELETE, and VEXCL
579  * checks.
580  */
581 int
582 naccess(struct namecache *ncp, int vmode, struct ucred *cred)
583 {
584     struct vnode *vp;
585     struct vattr va;
586     int error;
587
588     if (ncp->nc_flag & NCF_UNRESOLVED) {
589         cache_lock(ncp);
590         cache_resolve(ncp, cred);
591         cache_unlock(ncp);
592     }
593     error = ncp->nc_error;
594     if (vmode & (VDELETE|VCREATE|VEXCL)) {
595         if (((vmode & VCREATE) && ncp->nc_vp == NULL) ||
596             ((vmode & VDELETE) && ncp->nc_vp != NULL)
597         ) {
598             if (ncp->nc_parent == NULL) {
599                 if (error != EAGAIN)
600                         error = EROFS;
601             } else {
602                 error = naccess(ncp->nc_parent, VWRITE, cred);
603             }
604         }
605         if ((vmode & VEXCL) && ncp->nc_vp != NULL)
606             error = EEXIST;
607     }
608     if (error == 0) {
609         error = cache_vget(ncp, cred, LK_SHARED, &vp);
610         if (error == ENOENT) {
611             if (vmode & VCREATE)
612                 error = 0;
613         } else if (error == 0) {
614             /* XXX cache the va in the namecache or in the vnode */
615             if ((error = VOP_GETATTR(vp, &va, curthread)) == 0) {
616                 if ((vmode & VWRITE) && vp->v_mount) {
617                     if (vp->v_mount->mnt_flag & MNT_RDONLY)
618                         error = EROFS;
619                 }
620             }
621             vput(vp);
622             if (error == 0)
623                 error = naccess_va(&va, vmode, cred);
624         }
625     }
626     return(error);
627 }
628
629 /*
630  * Check the requested access against the given vattr using cred.
631  */
632 int
633 naccess_va(struct vattr *va, int vmode, struct ucred *cred)
634 {
635     int i;
636
637     /*
638      * Test the immutable bit for files, directories, and softlinks.
639      */
640     if (vmode & (VWRITE|VDELETE)) {
641         if (va->va_type == VDIR || va->va_type == VLNK || va->va_type == VREG) {
642             if (va->va_flags & IMMUTABLE)
643                 return (EPERM);
644         }
645     }
646
647     /*
648      * root gets universal access
649      */
650     if (cred->cr_uid == 0)
651         return(0);
652
653     /*
654      * Check owner perms, group perms, and world perms
655      */
656     vmode &= S_IRWXU;
657     if (cred->cr_uid == va->va_uid) {
658         if ((vmode & va->va_mode) != vmode)
659             return(EACCES);
660         return(0);
661     }
662
663     vmode >>= 3;
664     for (i = 0; i < cred->cr_ngroups; ++i) {
665         if (va->va_gid == cred->cr_groups[i]) {
666             if ((vmode & va->va_mode) != vmode)
667                 return(EACCES);
668             return(0);
669         }
670     }
671
672     vmode >>= 3;
673     if ((vmode & va->va_mode) != vmode)
674         return(EACCES);
675     return(0);
676 }
677